首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

Summercool-Web框架简介 (6)

2012-09-04 
Summercool-Web框架简介 (六)?简介:轻量封装Spring MVC? ? ? ? ?因为本人在国内最大的电子商务公司工作期

Summercool-Web框架简介 (六)

?

简介:轻量封装Spring MVC

? ? ? ? ?因为本人在国内最大的电子商务公司工作期间,深感一个好的Web框架可以大大提高工作效率,而一个不好的Web框架,又可以大大的降低开发效率。所以,在根据笔者在从事电子商务开发的这几年中,对各个应用场景而开发的一个轻量封装Spring MVC的一个Web框架。

? ? ? ? ?笔者工作的这几年之中,总结并开发了如下几个框架: summercool-web(Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-ddl(基于Mybaits的分表分库框架,已经应用国内某移动互联网公司);相继缓存方案、和消息系统解决方案也会慢慢开源。Summercool框架做为笔者的第一个开源框架

?

?

框架地址:http://summercool.googlecode.com/svn/trunk/summercool-web?

应用地址:http://summercool.googlecode.com/svn/trunk/summercool-petstore?

工具地址:http://summercool.googlecode.com/svn/trunk/summercool-tools

说明:此框架要用到spring-tools文件夹中的security文件夹中的文件,使用此框架的人员请将security文件夹的内容替换到JDK中的security文件夹中

?

? ? 在介绍summercool框架的几个点的时候,在这里我们再看一下summercool的框架,如下:

Summercool-Web框架简介 (6)

?

一、Pipeline介绍

?

? ? 1. AroundPipeline

?

package org.summercool.web.servlet.pipeline;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.core.PriorityOrdered;import org.summercool.web.servlet.AroundPipelineChain;/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * */public interface AroundPipeline extends PriorityOrdered {/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * @param request * @param response * @param aroundPipelineChain * @throws Exception */public void handleAroundInternal(HttpServletRequest request, HttpServletResponse response,AroundPipelineChain aroundPipelineChain) throws Exception;}

? ? ? ? 说明: 1) 通过总的summercool框架图我们可以看出,AroundPipeline相当于Filter的功能,其实笔者也是这么设计的

? ? ? ? ? ? ? ? ? 2) 那有人问为什么这么设计呢,因为之前笔者的summercool是基于servlet的,后来才改成基于filter的;所以这块也就保留了下来,而且笔者也想把整个summercool的框架内部的一些设计接口完整化,所以也没有想去掉。还有一个原因是,因为summercool框架对Response进行了缓冲。

? ? ? ? ? ? ? ? ? 3) AroundPipeline会拦截所有的request请求,所以我们就可以做很多东西在这个层面上,比如说,我们可以做一个web应用的请求监控,监控每秒钟应用请求量,如下:

? ? 打开monitor-configurer.xml里面的【RequestMonitor】类的源码:

?

package org.summercool.platform.web.module.petstore.config.monitor;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.util.UrlPathHelper;import org.summercool.platform.utils.NumberStatisticUtil;import org.summercool.web.servlet.AroundPipelineChain;import org.summercool.web.servlet.pipeline.AroundPipeline;public class RequestMonitor implements AroundPipeline {private static final String N_CHAR = "/";private final Logger logger = LoggerFactory.getLogger(RequestMonitor.class);private int order;private UrlPathHelper urlPathHelper = new UrlPathHelper();private NumberStatisticUtil numberStatisticUtil = new NumberStatisticUtil();public RequestMonitor() {numberStatisticUtil.setInterval(N_CHAR, 1000L);urlPathHelper.setUrlDecode(false);}public void handleAroundInternal(HttpServletRequest request, HttpServletResponse response,AroundPipelineChain aroundPipelineChain) throws Exception {//if (!logger.isDebugEnabled()) {aroundPipelineChain.handleAroundInternal(request, response, aroundPipelineChain);return;}//long beginTime = System.currentTimeMillis();//numberStatisticUtil.incrementAndGet(N_CHAR);long threadCount = numberStatisticUtil.getValue(N_CHAR);//try {aroundPipelineChain.handleAroundInternal(request, response, aroundPipelineChain);} finally {if (logger.isInfoEnabled()) {String url = urlPathHelper.getLookupPathForRequest(request);long endTime = System.currentTimeMillis();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String message = "当前Dispatcher[" + request.getRemoteAddr() + "-->" + url + "]"+ "当执行的时间为:[" + sdf.format(new Date(beginTime)) + "], " + "当前时间内(秒)执行线程数为:[" + threadCount + "], "+ "请求执行的时间为:[" + (endTime - beginTime) + "毫秒]";logger.info(message);}}}public void setOrder(int order) {this.order = order;}public int getOrder() {return order;}}

? ? A. 启动应用,请求应用页面,会打印出如下信息:INFO ?o.s.p.w.m.p.c.monitor.RequestMonitor - 当前Dispatcher[127.0.0.1-->/images/tb_pet_2.jpg]当执行的时间为:[2012-03-26 12:08:38], 当前时间内(秒)执行线程数为:[24], 请求执行的时间为:[0毫秒]

? ? B. 上面的信息的含义是:127.0.0.1这个应用,每秒钟的请求量;如上面的一秒种的请求量为24次,最后一次请求的是“/images/tb_pet_2.jpg”资源(因为summercool是基于filter的,所以静态信息的请求也会被拦截)。

? ? C. 其实NumberStatisticUtil类是并发安全的记数工具类,是以"key : value"Map结构的工具类,可以跟据时间设置有效期的时间段。

?

? ? 2. PreProcessPipeline

?

package org.summercool.web.servlet.pipeline;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.core.PriorityOrdered;import org.springframework.web.servlet.ModelAndView;/** *  * @author:shaochuan.wangsc * @date:2010-3-10 *  */public interface PreProcessPipeline extends PriorityOrdered {/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * @param request * @param response * @return * @throws Exception */public boolean isPermitted(HttpServletRequest request, HttpServletResponse response) throws Exception;/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * @param request * @param response * @return * @throws Exception */public ModelAndView handleProcessInternal(HttpServletRequest request, HttpServletResponse response)throws Exception;}

?

? ? petstore-module.xml

?

<bean name="code">package org.summercool.platform.web.module.petstore.config.security;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;import org.summercool.platform.web.module.petstore.config.cookie.CookieUtils;import org.summercool.web.servlet.pipeline.PreProcessPipeline;/** * @Title: LoginSecurity.java * @Package com.gexin.platform.web.module.manager.config.security * @Description: * @author 简道 * @date 2011-11-24 下午1:29:27 * @version V1.0 */public class LoginSecurity extends AbstractSecurity implements PreProcessPipeline {private int order;// set 方法public void setOrder(int order) {this.order = order;}public ModelAndView handleProcessInternal(HttpServletRequest request, HttpServletResponse response)throws Exception {return new ModelAndView("redirect:/" + "login.htm");}public boolean isPermitted(HttpServletRequest request, HttpServletResponse response) throws Exception {if (match(request)) {return true;} else {if (CookieUtils.isLogin(request)) {return true;} else {return false;}}}public int getOrder() {return order;}}

?

? ?security-configurer.xml

?

<bean name="loginSecurity" value="1" /><property name="filterPaths"><util:list><value>/</value><value>/index.htm</value><value>/login.htm</value><value>/logout.htm</value><value>/helper.htm</value></util:list></property></bean>

?

? ? 说明:首先,在Spring的配置里面配置一下面PreProcessPipeline的实现类,summercool框架会自动将其扫描到容器中并加载成单例的。

? ? ? ? ? ? ?再次,所有的请求都会按PreProcessPipeline的序列进行请求处理,比如说summercool-petstore应用里面只有LoginSecurity权限处理类。

? ? ? ? ? ? ?然后,request ---> PreProcessPipeline ?( isPermitted() -- [true|false] -->?handleProcessInternal()?)

? ? ? ? ? ? ? ? ? ? ? 如果isPermitted()函数返回为true,则不会执行handleProcessInternal()函数,请求会继续交给下一个PreProcessPipeline或是Controller继续向下面执行

? ? ? ? ? ? ? ? ? ? ? 如果isPermitted()函数返回为false,则会执行handleProcessInternal()函数,并返回ModelAndView接口并直接返回,不再继续交给下面的请求处理类,而是直接处理ModelAndView接口直接返回给客户端。

? ? ? ? ? ? ?在上面的这个LoginSecurity处理类中,所有的请求都经过isPermitted()函数判断用户是否登录,如果登录则返回true;如果不登录则返回false,然后执行handleProcessInternal()函数,handleProcessInternal()函数将用户重定向到登录页面。

? ? ? ? ? ? ?在LoginSecurity处理类中,用户是否登录是通过Cookies进行判断的。而不需要权限过滤的请求url是通过AbstractSecurity类里面的match()函数实现,通过xml配置完成。

?

? ? 3. PostProcessPipeline

?

package org.summercool.web.servlet.pipeline;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.core.PriorityOrdered;import org.springframework.web.servlet.ModelAndView;/** *  * @author:shaochuan.wangsc * @date:2010-3-10 *  */public interface PostProcessPipeline extends PriorityOrdered {/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * @param request * @param response * @param modelAndView * @return * @throws Exception */public boolean isPermitted(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView)throws Exception;public ModelAndView handleProcessInternal(HttpServletRequest request, HttpServletResponse response)throws Exception;}

? ? 说明:1) PostProcessPipeline其实只是在isPermitted()函数中,多了一个ModelAndView对象;其余的用法和PreProcessPipeline是一样的。

? ? ? ? ? ? ?2) 在Controller请求处理完成之后,在渲染页面之前会执行PostProcessPipeline这个接口的实现类。

? ? ? ? ? ? ?3) 为什么要多一个ModelAndView接口呢?因为,我们在这里可以做很多的文章,如这样的一个需求:

? ? 我们为了web应用的安全考虑,我们肯定希望在一个请求在处理外部重定向的时候,我们需要肯定一些特定的参数进行重定向到一个页面。如:淘宝应用的在访问“已买到的宝贝”的时候,需要登录才能查看,所以在重定向到登录页面的时候,url后面会带一个redirectURL参数来让用户登录后继续回去上一次访问的页面。那么,这个时候问题来了!

? ? A. redirectURL后面是一个安全的淘宝内部的url地址,那么在应用登录后重定向到goto指定的地址是没有问题的。

? ? B. 如果要是被黑客给黑了,redirectURL的地址是一个不安全的地址,那么要怎么处理呢?

? ? C. 我们是否有一个统一的办法来处理这样的情况呢?

? ? D. 当然是PostProcessPipeline了;所有的Controller执行完成后,在跳转到页面之前都会执行PostProcessPipeline,所以我们可以通过ModelAndView参数来查看是否View中的地址是否在我们应用允许跳转的白名单之中,如果允许则通过;如果不允许则做另一处理。(在summercool-petstore应用中,笔者没有给出这个接口的实现)

?

? ? 4. ExceptionPipeline

?

package org.summercool.web.servlet.pipeline;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.core.PriorityOrdered;import org.springframework.web.servlet.ModelAndView;/** *  * @author:shaochuan.wangsc * @date:2010-3-10 *  */public interface ExceptionPipeline extends PriorityOrdered {/** *  * @author:shaochuan.wangsc * @date:2010-3-10 * @param request * @param response * @param modelAndView * @param throwable * @throws Exception */public void handleExceptionInternal(HttpServletRequest request, HttpServletResponse response,ModelAndView modelAndView, Throwable throwable) throws Exception;}
?

? ? 说明:Spring MVC在处理Controller抛出的错误信息的时候可以拦截,交给ExceptionResolver处理,但是如果vm、jsp和ftl这样的页面出错的时候,Spring MVC的ExceptionResolver是无法处理的;直接抛出给Response并且示给客户端。

? ? ? ? ? ? ?Spring MVC只能定制在异常信息类型进行统一错误信息进行处理,如: UserException --> /user/error

? ? ? ? ? ? ?而我们经常会遇到跟据UserException中的某一属性,如errorCode属性的不同值来渲染不出的页面。

? ? ? ? ? ? ?如果我们有上面的需求,那么我们怎么处理呢?那么我们就要用ExceptionPipeline了,因为该类会拦截所有的异常信息,并且交给handExceptionInternal()函数处理;

expception-configurer.xml里面有一个默认的ExceptionPipeline实现,如下:

?

package org.summercool.platform.web.module.petstore.config.exception;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.servlet.ModelAndView;import org.summercool.util.StackTraceUtil;import org.summercool.web.servlet.pipeline.ExceptionPipeline;public class DefaultExceptionHandler implements ExceptionPipeline {private Logger logger = LoggerFactory.getLogger(getClass());private int order;public void handleExceptionInternal(HttpServletRequest request, HttpServletResponse response,ModelAndView mv, Throwable throwable) throws Exception {// 打印错误信息String stackTrace = StackTraceUtil.getStackTrace(throwable);// 记录错误信息logger.error(stackTrace);if (mv != null) {mv.setViewName("redirect:/index.htm");} else {throwable.printStackTrace();}}public void setOrder(int order) {this.order = order;}public int getOrder() {return order;}}

? ? 说明:上面的代码的意思是,如果发生异常;handleExceptionInternal()函数会先获取异常信息并打印到日志中,然后通过ModelAndView对象来跟据业务的需要来自定义要跳转的页面。

? ? ? ? ? ? ? 上面的代码就是如果发生任何的异常,则跳转到/index.htm页面

?

?

二、summercool框架对Cookies封装

?

? ? 1. cookie-configurer.xml

?

<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-3.0.xsd"><bean name="cookieConfigurer" value="^#16qweqv8cde729!@#$3450abfg^%" /><property name="cookieConfigurerList"><util:list><bean name="id" value="${org.summercool.petstore.domain}" /><property name="lifeTime" value="-1" /><property name="name" value="id" /><property name="clientName" value="__i__" /><property name="encrypted" value="true" /></bean><bean name="uname" value="${org.summercool.petstore.domain}" /><property name="lifeTime" value="-1" /><property name="name" value="uname" /><property name="clientName" value="__uli__" /><property name="encrypted" value="true" /></bean><bean name="password" value="${org.summercool.petstore.domain}" /><property name="lifeTime" value="-1" /><property name="name" value="password" /><property name="clientName" value="__up__" /><property name="encrypted" value="true" /></bean><bean name="csrf" value="${org.summercool.petstore.domain}" /><property name="lifeTime" value="-1" /><property name="name" value="csrf" /><property name="clientName" value="__rf__" /><property name="encrypted" value="true" /></bean></util:list></property></bean></beans>

?

在上面这个配置文件中,最重要的是CookieConfigurer类配置,如下:

?

<bean name="id" value="${org.summercool.petstore.domain}" /><property name="lifeTime" value="-1" /><property name="name" value="id" /><property name="clientName" value="__i__" /><property name="encrypted" value="true" /></bean>

? ? 说明:1) domain: cookie存放在的域名(笔者建议设置为一级域名,这样二级域名的应用也可以获取和共享一级域名的cookie)

? ? ? ? ? ? ?2) lifeTime:设置cookie的有效期

? ? ? ? ? ? ?3) name:服务端的cookie名称,因为开发者在使用时,要知道设置了哪个cookie

? ? ? ? ? ? ?4) clientName:相对于服务端的cookie名称,这个是客户端的cookie名称。

? ? ? ? ? ? ? ? ?比如说吧,我们设置了一个cookie的值,是不想让客户端的用户可以通过工具查看到我们设置的cookie名称能猜出我们的含义的,那么我们就要设置clientName,让用户端看到的是不知道何意义的cookie名称,而在服务端,开发人员又可以明确知道cookie的名称name。

? ? ? ? ? ? ?5) encrypted:是否进行加密处理;设置了此属性,CookieConfigurer类会自动对该cookie进行加密和解密。

?

?

<property name="cryptoKey" value="^#16qweqv8cde729!@#$3450abfg^%" />

? ? xml中上面这段的配置就是加密混淆串,笔者建议不用的开发者如何使用summercool框架的时候,请更改此加密混淆串。

?

应用举例:CookiesUtils.java

?

public static void writeCookie(HttpServletRequest request, UserDO userDO) {if (request == null || userDO == null) {throw new IllegalArgumentException();}CookieModule jar = (CookieModule) request.getAttribute(CookieModule.COOKIE);if (jar == null) {throw new NullPointerException();}jar.remove(CookieConstants.MANAGER_ID_COOKIE);jar.remove(CookieConstants.MANAGER_PWD_COOKIE);jar.remove(CookieConstants.MANAGER_UNAME_COOKIE);jar.set(CookieConstants.MANAGER_ID_COOKIE, userDO.getId().toString());try {jar.set(CookieConstants.MANAGER_UNAME_COOKIE, URLEncoder.encode(userDO.getUserName(), "UTF-8"));} catch (UnsupportedEncodingException e) {}jar.set(CookieConstants.MANAGER_PWD_COOKIE, userDO.getPassword());}public static void clearCookie(HttpServletRequest request) {CookieModule jar = (CookieModule) request.getAttribute(CookieModule.COOKIE);if (jar != null) {jar.remove(CookieConstants.MANAGER_ID_COOKIE);jar.remove(CookieConstants.MANAGER_UNAME_COOKIE);jar.remove(CookieConstants.MANAGER_PWD_COOKIE);}}public static Long getUserId(HttpServletRequest request) {if (request == null) {throw new IllegalArgumentException();}CookieModule jar = (CookieModule) request.getAttribute(CookieModule.COOKIE);if (jar == null) {return null;}String idStr = jar.get(CookieConstants.MANAGER_ID_COOKIE);if (StringUtils.isNumeric(idStr)) {return Long.valueOf(idStr);}return null;}

? ? 说明:summercool框架已经对cookies进行了封装,在配置文件配置完成后就可以直接使用了

? ? ? ? ? ? ?只要通过reqeust对象就可以直接设置和获取cookie的相关信息了。

? ? ? ? ? ? ?笔者认为,所有的用户登录信息最好不用要session实现,因为session还要解决分布式的问题。笔者建议登录信息全部都存放在cookie里面是非常好的,因这样不仅可以实现登录信息的保存而且大大降低了开发难度;相关于变相的实现了无状态登录。

?

三、summercool框架对UrlRewrite封装

? ? ? 1. 比如说我们有这样的一个需求,所有的页面都要通过/item/1.htm这样的url地址来访问“产品的详细页面”

? ? ? 2. 像上面这样的配置规则,我不需要多于的代码编写,可以自动生成上面这样风格的url或是自定义的url风格

? ? ? 3. 上面成生的url风格中,我们还可以提取“1”这样的参数或是url中的参数可以直接提取出来

请看url-configurer.xml的配置:

?

<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-3.0.xsd"><bean value="/item/item_detail.htm" /></map></property></bean><bean name="urlModuleConfigurer" value="1" /><property name="uriTemplate" value="/item/{id}.htm" /></bean></entry></util:map></property></bean></beans>

? ? 说明:1)?SimpleUrlHandlerMapping:可以配置/item/*.htm这样的url地址全部都交给/item/item_detail.htm地址对应的Controller(/item/ItemDetailController.java)来处理。

? ? ? ? ? ? ?2)?UrlBuilderModuleConfigurer:可以配置以模块为单位的url地址映射规则,并加入序号,如:

?

                               <entry><key><value>item</value></key><bean name="id" value="1" /><property name="uriTemplate" value="/item/{id}.htm" /></bean></entry>

? ? 在上面这段配置中,我们可以配置一个item模块的url地址规则为:/item/{id}.htm

? ? 在freemarker页面中,如果想使用上面规则的地址,则使用url内置函数:${url("item",param("id","1"))}

? ? 在上面这个函数中,item:代表模块名,param是freemarker的内置函数,返回为map类型的数据,key=id, value=1

? ? 如果大家细点一点,会发现上面有一个人seq的一个参数,这个是干什么用的呢?因为有时候,一个item模块可能会有很多的模版规则,如/item/c{category}.htm

? ? ? ? ? ?上面这个模版的意思是,查到一个item某类目下面的详细信息,这样的话我们可以将seq设置成2

? ? ? ? ? ?页面上可以做这样的使用:${url("item",param("category","1"),"2")} --> 其中的"2"就是seq的值,是让url函数调用url模版的时候,只调用seq=2的那个模版。当然,也可以不写(默认会调用第一个配置的url模版,即seq=1的模版)。

? ? 所以,url地址规则:${url("item",param("id","1"))} ?--> /item/1.htm;具体的应用请查看summercool-petstore应用的/index.ftl页面,如下:

?

<!DOCTYPE html><html lang="zh">  <head>    <meta charset="utf-8">    <title>Summercool, Petstore</title>    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta name="description" content="">    <meta name="author" content="">    <!-- Le styles -->    <link href="/css/bootstrap.css" rel="stylesheet">    <style type="text/css">      body {        padding-top: 60px;        padding-bottom: 40px;      }  #tb td ,#tb th{border-top: 0px;  }    </style>    <link href="/css/bootstrap-responsive.css" rel="stylesheet">    <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->    <!--[if lt IE 9]>      <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>    <![endif]-->  </head>  <body>  ${widget("/petstore/widgets/header")}    <div name="code">package org.summercool.platform.web.module.petstore.controllers.item;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.AbstractController;import org.summercool.beans.url.UrlBuilderBeanDefinition;import org.summercool.web.module.url.UrlBuilderModule;public class ItemDetailController extends AbstractController {@Overrideprotected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception {UrlBuilderModule urlBuilderModule = (UrlBuilderModule) request.getAttribute(UrlBuilderModule.URL_BUILDER);UrlBuilderBeanDefinition urlBuilderBean = urlBuilderModule.matchUrlBuilderBean();// 如果在访问detail页面时,没有找查到相对应的url规则直接返回到/login.htm页面if (urlBuilderBean == null || !urlBuilderBean.isMatched()) {return new ModelAndView("redirect:/index.htm");}//Map<String, String> map = urlBuilderBean.getUriTemplateVariables();try {String id = map.get("id");// 在这里可以写一些业务逻辑,比如在DB中查找到item信息收直接显示detail页面,否则返回到/login.htm页面Long.valueOf(id);} catch (Exception e) {return new ModelAndView("redirect:/index.htm");}//return new ModelAndView("/petstore/views/item/itemDetail", map);}}

? ? 说明:上面的代码中,有两行代码比较关键,如下:

?

UrlBuilderModule urlBuilderModule = (UrlBuilderModule) request.getAttribute(UrlBuilderModule.URL_BUILDER);UrlBuilderBeanDefinition urlBuilderBean = urlBuilderModule.matchUrlBuilderBean();

? ? ? ? ? ? ? 这段代码中的两行,是让开发人员可以通过上面的方式来获得url模版所匹配的地址,如果匹配到则可以提取出url模版中所对应的参数,如:

?

if (urlBuilderBean == null || !urlBuilderBean.isMatched()) {return new ModelAndView("redirect:/index.htm");}

? ? 上面的代码是,如果匹配不到url对应的模版或是匹配不到其中的具体的规则,则重定向到/index.htm页面。

?

Map<String, String> map = urlBuilderBean.getUriTemplateVariables();try {String id = map.get("id");// 在这里可以写一些业务逻辑,比如在DB中查找到item信息收直接显示detail页面,否则返回到/login.htm页面Long.valueOf(id);} catch (Exception e) {return new ModelAndView("redirect:/index.htm");}

? ? 上面的代码中,如果匹配到的url模版则可以通过上面的方式直接获取模版中url的参数map。

? ? 上面的代码中加入了判断map参数的合法行(笔者也只是示意一下而已)。

?

补充:到这为止,差不多summercool的框架的主要特性就差不多全都介绍完了。因为笔者的工作调动原因,没有太多的时间来写文档,所以只能写这些了,下一篇会简单介绍一下summercool框架其他的一些小特性。

?

?

?

?

热点排行