SPRING的映射机制

 

通过处理器映射,你可以将web请求映射到正确的处理器(handler)上。Spring内置了很多处理器映射策略,例如:SimpleUrlHandlerMapping或者BeanNameUrlHandlerMapping。现在我们先来看一下HandlerMapping的基本概念。

HandlerMapping的基本功能是将请求传递到HandlerExecutionChain上。首先,这个HandlerExecutionChain必须包含一个能处理该请求的处理器。其次,这个链也可以包含一系列可以拦截请求的拦截器。当收到请求时,DispatcherServlet将请求交给处理器映射,让它检查请求并找到一个适当的HandlerExecutionChain。然后,DispatcherServlet执行定义在链中的处理器和拦截器(interceptor)。

在处理器映射中通过配置拦截器(包括处理器执行前、执行后、或者执行前后运行拦截器)将使其功能更强大。同时也可以通过自定义HandlerMapping来支持更多的功能。比如,一个自定义的处理器映射不仅可以根据请求的URL,而且还可以根据和请求相关的session状态来选择处理器。

下面我们将讲述Spring中最常用的两个处理器映射。它们都是AbstractHandlerMapping的子类,同时继承了下面这些属性:

interceptors: 在映射中使用的拦截器列表。HandlerInterceptor将在第 13.4.3 节 “拦截器(HandlerInterceptor)”这一节讲述。

defaultHandler: 默认的处理器。当没有合适的处理器可以匹配请求时,这个处理器就会被使用。

order: 根据每个映射的order属性值 (由org.springframework.core.Ordered 接口定义),Spring 将上下文中可用的映射进行排序,然后选用第一个和请求匹配的处理器。 

alwaysUseFullPath:如果这个属性被设成true,Spring 将会使用绝对路径在当前的servlet context中寻找合适的处理器。 这个属性的默认值是false,在这种情况下,Spring会使用当前servlet context中的相对路径。例如,如果一个servlet在servlet-mapping中用的值是/testing/*,当alwaysUseFullPath 设成true时,处理器映射中的URL格式应该使用/testing/viewPage.html,当这个属性设成false, 同一个URL应该写成 /viewPage.html。

urlPathHelper:指定在分析URL时使用的UrlPathHelper。通常使用其默认值。

urlDecode: 这个属性的默认值是false。HttpServletRequest返回未解码的访问URL和URI。HttpServletRequest中请求的URL和URI还保留在HTTP协议所定义编码状态,如果你想在HandlerMapping使用它们发现合适的处理器之前对URL进行解码,你应该把这个属性设成true (注意这需要JDK 1.4的支持)。解码方法会选用HTTP请求中指定的编码格式,或缺省的ISO-8859-1编码方法。 HTTP请求中一般会声明编码的格式,如果没有的话,默认值是ISO-8859-1。Spring会使用相应的解码算法。

lazyInitHandlers: 这个属性允许你设置是否延迟singleton处理器的初始化工作(prototype处理器的初始化都是延迟的)。 这个属性的默认值是false.

(注意:最后四个属性只有org.springframework.web.servlet.handler.AbstractUrlHandlerMapping的子类才有。)

 

BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping是一个简单但很强大的处理器映射,它将收到的HTTP请求映射到bean的名字上(这些bean需要在web应用上下文中定义)。例如,为了实现一个用户新建账号的功能,我们提供了FormController (关于CommandController和FormController请参考第 13.3.4 节 “命令控制器”)和显示表单的JSP视图(或Velocity模版)。当使用BeanNameUrlHandlerMapping时,我们用如下方式将包含http://samples.com/editaccount.form的访问请求映射到指定的FormController上:

  
  
< beans >
  
< bean  id ="handlerMapping"  class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

  
< bean  name ="/editaccount.form"  class ="org.springframework.web.servlet.mvc.SimpleFormController" >
    
< property  name ="formView"  value ="account" />
    
< property  name ="successView"  value ="account-created" />
    
< property  name ="commandName"  value ="account" />
    
< property  name ="commandClass"  value ="samples.Account" />
  
</ bean >
< beans >

所有对/editaccount.form的请求就会由上面的FormController处理。当然我们得在web.xml中定义servlet-mapping,接受所有以.form结尾的请求。

< web-app >
    ...
    
< servlet >
        
< servlet-name > sample </ servlet-name >
        
< servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class >
        
< load-on-startup > 1 </ load-on-startup >
    
</ servlet >

   
<!--  maps the sample dispatcher to *.form  -->
    
< servlet-mapping >
        
< servlet-name > sample </ servlet-name >
        
< url-pattern > *.form </ url-pattern >
    
</ servlet-mapping >
    ...
</ web-app >
注意

要使用BeanNameUrlHandlerMapping,无须(如上所示)在web应用上下文中定义它。缺省情况下,如果在上下文中没有找到处理器映射,DispatcherServlet会为你创建一个BeanNameUrlHandlerMapping

13.4.2. SimpleUrlHandlerMapping

另一个更强大的处理器映射是SimpleUrlHandlerMapping。它在应用上下文中可以进行配置,并且有Ant风格的路径匹配功能。(请参考org.springframework.util.PathMatcher的JavaDoc)。下面几个例子可以帮助理解:

 

< web - app >
    ...
    
< servlet >
        
< servlet - name > sample </ servlet - name >
        
< servlet - class > org.springframework.web.servlet.DispatcherServlet </ servlet - class >
        
< load - on - startup > 1 </ load - on - startup >
    
</ servlet >

    
<!--  maps the sample dispatcher to  * .form  -->
    
< servlet - mapping >
        
< servlet - name > sample </ servlet - name >
        
< url - pattern >* .form </ url - pattern >
    
</ servlet - mapping >

    
<!--  maps the sample dispatcher to  * .html  -->
    
< servlet - mapping >
        
< servlet - name > sample </ servlet - name >
        
< url - pattern >* .html </ url - pattern >
    
</ servlet - mapping >
    ...
</ web - app >

The above web.xml configuration snippet enables all requests ending with .html and .form to be handled by the sample dispatcher servlet.

上面的web.xml设置允许所有以.html.form结尾的请求都由这个sample DispatcherServlet处理。

  
  
< beans >
        
    
<!--  no 'id' required, HandlerMapping beans are automatically detected by the DispatcherServlet  -->
    
< bean  class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
        
< property  name ="mappings" >
            
< value >
                /*/account.form=editAccountFormController
                /*/editaccount.form=editAccountFormController
                /ex/view*.html=helpController
                /**/help.html=helpController
            
</ value >
        
</ property >
    
</ bean >

    
< bean  id ="helpController"
          class
="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

    
< bean  id ="editAccountFormController"
          class
="org.springframework.web.servlet.mvc.SimpleFormController" >
        
< property  name ="formView"  value ="account" />
        
< property  name ="successView"  value ="account-created" />
        
< property  name ="commandName"  value ="Account" />
        
< property  name ="commandClass"  value ="samples.Account" />
    
</ bean >
< beans >

这个处理器映射首先将对所有目录中文件名为help.html的请求传递给helpControllerhelpController是一个UrlFilenameViewController (要了解更多关于控制器的信息,请参阅 第 13.3 节 “控制器”)。对ex目录中所有以view开始,以.html 结尾的请求都会被传递给helpController。 同样的,我们也为editAccountFormController定义了两个映射。

13.4.3. 拦截器(HandlerInterceptor

Spring的处理器映射支持拦截器。当你想要为某些请求提供特殊功能时,例如对用户进行身份认证,这就非常有用。

处理器映射中的拦截器必须实现org.springframework.web.servlet包中的HandlerInterceptor接口。这个接口定义了三个方法,一个在处理器执行前被调用,一个在处理器执行后被调用,另一个在整个请求处理完后调用。这三个方法提供你足够的灵活度做任何处理前后的操作。

preHandle(..)方法有一个boolean返回值。使用这个值,你可以调整执行链的行为。当返回true时,处理器执行链将继续执行,当返回false时,DispatcherServlet认为该拦截器已经处理完了请求(比如显示正确的视图),而不继续执行执行链中的其它拦截器和处理器。

下面的例子提供了一个拦截器,它拦截所有请求,如果当前时间不是在上午9点到下午6点,它将用户重定向到某个页面。

  
  
< beans >
    
< bean  id ="handlerMapping"
          class
="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
        
< property  name ="interceptors" >
            
< list >
                
< ref  bean ="officeHoursInterceptor" />
            
</ list >
        
</ property >
        
< property  name ="mappings" >
            
< value >
                /*.form=editAccountFormController
                /*.view=editAccountFormController
            
</ value >
        
</ property >
    
</ bean >

    
< bean  id ="officeHoursInterceptor"
          class
="samples.TimeBasedAccessInterceptor" >
        
< property  name ="openingTime"  value ="9" />
        
< property  name ="closingTime"  value ="18" />
    
</ bean >
< beans >
  
  
package  samples;

public   class  TimeBasedAccessInterceptor  extends  HandlerInterceptorAdapter  {

    
private int openingTime;
    
private int closingTime;

    
public void setOpeningTime(int openingTime) {
        
this.openingTime = openingTime;
    }


    
public void setClosingTime(int closingTime) {
        
this.closingTime = closingTime;
    }


    
public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler) 
throws Exception {

        Calendar cal 
= Calendar.getInstance();
        
int hour = cal.get(HOUR_OF_DAY);
        
if (openingTime <= hour < closingTime) {
            
return true;
        }
 else {
            response.sendRedirect(
"http://host.com/outsideOfficeHours.html");
            
return false;
        }

    }

}

所有的请求都将被TimeBasedAccessInterceptor截获,如果当前时间不在上班时间,用户会被重定向到一个静态html页面,提供诸如只有上班时间才能访问网站之类的告示。

Spring还提供了一个adapter类HandlerInterceptorAdapter让用户更方便的扩展HandlerInterceptor接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值