Spring 4.x官方参考文档中文版——第21章 Web MVC框架(5)

@Controller与AOP代理

       在有些情况下,控制器可能需要在运行时使用AOP代理,比如你在一个控制器上直接写上了@Transactional注解。在这种特定某个控制器的情况,我们推荐你使用基于类的代理。这是控制器默认选择的代理方式。但是,如果一个控制器必须实现一个不属于Spring Context回调的接口(比如InitializaingBean,  *Aware等等),你可能需要显式地配置一个基于类的代理。例如:把<tx:annotation-driven/>,改为<tx:annotation-drivenproxy-target-class=”true”>

 

在SpringMVC 3.1中,支持@RequestMapping方法的新的类

        Spring 3.1中介绍了支持@RequestMapping方法的一些新的类,分别叫做RequestMappingHandlerMapping和RequestMappingHandlerAdapter。在Spring3.1中,它们被推荐使用,或是在要使用Spring MVC 3.1及以后版本中新特性的情况下,它们是必须被使用的。这些新的类是被MVC namespace(命名空间)和MVCJava配置默认启用的,如果都不使用,则需要显式地去配置它们。这部分文章描述了新旧支持类间的一些重要的不同点。

        在Spring 3.1之前,类型和方法等级的request请求映射是被分开检测的,一个控制器首先是被DefaultAnnotaionHandlerMapping选中,然后,具体调用方法的选择则被AnnotationMethodHandlerAdapter来收窄。

        在Spring 3.1新的支持类下,只使用RequestMappingHandlerMapping,它把控制器中的方法看成一个带有映射的不同节点的集合,这些映射里,一个映射对应一个方法,这些方法来自于类型或方法级别@RequestMapping注解中的信息。

        这种方式能提供更多的可能性,HandlerInterceptor或者HandlerExceptionResolver现在能够把基于对象的handler处理器视作一个HandlerMethod,这样,就可以检测到这些handler处理器中准确的方法,它的参数,和与之协同的注解。这样,一个URL的处理就再也不需要在不同控制器中进行拆分。

同时,也有一些事情变得不可能了:

  • 利用SimpleUrlHandlerMapping或者BeanNameUrlHandlerMapping来选取一个控制器,之后,使用@RequestMapping注解来收窄所要使用的具体方法。
  • 依赖于方法名作为回退机制,以区分两个既没有显式的URL映射路径,又没有其他匹配规则(例如基于HTTP方法区分)的@RequestMapping方法。
  • 如果一个request没有一个合适的控制器方法匹配,可以有一个没有定义显式路径映射的方法来处理它。在新的支持类中,如果没找到匹配方法,就会显示404。

以上这些特性,在存在有支持类的情况下依然支持,但是,为了使用Spring MVC 3.1的新特性,你需要使用新的支持类。

 

URI(统一资源标识符)模板模式

        URI模板可以方便的访问在@RequestMapping方法中所选中的部分URL。

URI模板是一个类似URI的字符串,包含了任意个变量名,当你改变这些变量时,这个模板会变成一个URI,URI模板的proposed RFC(RFC提案)定义了URI是怎样传参的。例如:http://www.example.com/users/{userId}这样的URI,包含了userId变量,如果给其设置为”fred”,则地址就变为”http://www.example.com/users/fred”。

        在Spring MVC中,你能在一个方法参数前使用@PathVariable注解来绑定一个URI模板变量:


        URI模板中的”/owners/{ownerId}”表示变量名”ownerId”,当controller控制器处理这个request请求时,ownerId会从URI中适当的地方找出这个值,并赋值给这个变量,例如:当一个request请求以”/owners/fred”这样的链接访问的时候,ownerId的值就是fred。

小提示:

         为了处理@pathVariable注解,Spring MVC需要根据名称去匹配对应的URI模板,你能在注解中定义它:


  或者,如果URI模板的变量名与方法参数名一致,你就可以省略注解的定义:


一个方法中可以有多个@PathVariable注解:

 

       当在一个方法的Map<String, String>类型的参数上使用@PathVariable注解,所有的URI模板变量将被填充进这个map。

URI 模板可以装配到类,或者路径级别的@RequestMapping注解上,在下面的例子中,findPet()方法能在”/owner/42/pets/21”这样的URL下被调用:


       @PathVariable的入参可以是基本类型中的一种,比如int,long,Date等等,Spring会自动地转换成合适的类型,或者在转换失败的时候,抛出TypeMismatchException。你也能为新的数据类型进行注册并支持转换,详见“方法参数和类型转换”和”自定义WebDataBinder初始化”这两部分文章。

 

正则表达式的URI模板模式

       有时候,你在定义URI模板变量时需要更精确,比如这个URL:“/spring-web/spring-web-3.0.5.jar”,你会怎样分割这个URL为多个部分?

       @RequestMapping注解支持使用正则表达式的URI模板变量。语法是:{varName : regex},其中第一部分定义变量名,第二部分是正则表达式,例如:

 

路径模式

       除了URI模板之外,@RequestMapping注解也支持类似Ant风格的路径模式(比如:”/myPath/*.do”),ant风格路径与URI模板变量组合起来使用也是支持的(比如:”/owners/*/pets/{petId}”)。

 

路径模式对比

       如果一个URL匹配到了多个路径,为了找到最合适的路径,会按照一定顺序去寻找它。

一个拥有更少量的URI变量,并且通配符最少的路径被认为是更匹配的。例如:”/hotels/{hotel}/*”里面有1个URI变量和1个通配符,这种路径比”hotels/{hotel}/**”(1个URI变量,2个通配符)这样的路径更匹配。

如果两个路径的变量及通配符数量是一样的,则越长的路径越匹配,比如:”/foo/bar*”比“/foo/*”这种路径更匹配。

还有一些附加的特殊规则:

  • 默认映射模式“/**”是匹配优先度最低的,比如:”/api/{a}/{b}/{c}”这样的路径会比”/**”更匹配。
  • 类似”/public/**”的前缀模式,比其他不含双通配符的模式匹配优先度更低,比如:”/public/path3/{a}/{b}/{c}”比上面的路径更匹配。

如需详细了解,见AntPathMatcher中的AntPatternComparator。注意,PathMatcher可以被自定义。(见”路径匹配”这部分文章)。


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值