1:mvc annotation-driven 新增标签 
以下为spring mvc 3.1中annotation-driven所支持的全部配置。 

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven  message-codes-resolver ="bean ref" validator="" conversion-service="">  
  2.       
  3.      <mvc:return-value-handlers>  
  4.         <bean></bean>  
  5.     </mvc:return-value-handlers>  
  6.        
  7.     <mvc:argument-resolvers>  
  8.     </mvc:argument-resolvers>  
  9.        
  10.     <mvc:message-converters>  
  11.     </mvc:message-converters>[/color]   
  12. </mvc:annotation-driven>  
<mvc:annotation-driven  message-codes-resolver ="bean ref" validator="" conversion-service="">
   
     <mvc:return-value-handlers>
        <bean></bean>
    </mvc:return-value-handlers>
    
    <mvc:argument-resolvers>
    </mvc:argument-resolvers>
    
    <mvc:message-converters>
    </mvc:message-converters>[/color]
</mvc:annotation-driven>



其中3.1新增部分如下    
return-value-handlers 
允许注册实现了HandlerMethodReturnValueHandler接口的bean,来对handler method的特定的返回类型做处理。 
HandlerMethodReturnValueHandler接口中定义了两个方法 
supportsReturnType 方法用来确定此实现类是否支持对应返回类型。 
handleReturnValue 则用来处理具体的返回类型。 

例如以下的handlerMethod 

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/testReturnHandlers")   
  2. public User testHandlerReturnMethod(){   
  3.     User u  = new User();   
  4.     u.setUserName("test");   
  5.     return u;   
  6. }  
	@RequestMapping("/testReturnHandlers")
	public User testHandlerReturnMethod(){
		User u  = new User();
		u.setUserName("test");
		return u;
	}


所返回的类型为一个pojo,正常情况下spring mvc无法解析,将转由DefaultRequestToViewNameTranslator 解析出一个缺省的view name,转到 testReturnHandlers.jsp, 
我们增加以下配置

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator">  
  2. color=red]        <mvc:return-value-handlers>    
  3.            <bean  class="net.zhepu.web.handlers.returnHandler.UserHandlers"></bean>    
  4.     </mvc:return-value-handlers>[/color]   
  5. </mvc:annotation-driven>  
	<mvc:annotation-driven validator="validator">
[color=red]        <mvc:return-value-handlers> 
            <bean  class="net.zhepu.web.handlers.returnHandler.UserHandlers"></bean> 
		</mvc:return-value-handlers>[/color]
	</mvc:annotation-driven>


及如下实现类

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class UserHandlers implements HandlerMethodReturnValueHandler {   
  2.     Logger logger = LoggerFactory.getLogger(this.getClass());   
  3.     @Override  
  4.     public boolean supportsReturnType(MethodParameter returnType) {   
  5.         Class<?> type = returnType.getParameterType();   
  6.         if(User.class.equals(type))   
  7.         {   
  8.             return true;   
  9.         }   
  10.         return false;   
  11.     }   
  12.   
  13.     @Override  
  14.     public void handleReturnValue(Object returnValue,   
  15.             MethodParameter returnType, ModelAndViewContainer mavContainer,   
  16.             NativeWebRequest webRequest) throws Exception {   
  17.         logger.info("handler  for return type users ");   
  18.         mavContainer.setViewName("helloworld");   
  19.     }   
  20.   
  21. }  
public class UserHandlers implements HandlerMethodReturnValueHandler {
    Logger logger = LoggerFactory.getLogger(this.getClass());
	@Override
	public boolean supportsReturnType(MethodParameter returnType) {
		Class<?> type = returnType.getParameterType();
		if(User.class.equals(type))
		{
			return true;
		}
		return false;
	}

	@Override
	public void handleReturnValue(Object returnValue,
			MethodParameter returnType, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest) throws Exception {
		logger.info("handler  for return type users ");
		mavContainer.setViewName("helloworld");
	}

}


此时再访问 http://localhost:8080/springmvc/testReturnHandlers ,将交由 UserHandlers来处理返回类型为User的返回值。 

argument-resolvers 
允许注册实现了WebArgumentResolver接口的bean,来对handlerMethod中的用户自定义的参数或annotation进行解析 
例如 

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator">  
  2.     <mvc:argument-resolvers>  
  3.         <bean  
  4.             class="net.zhepu.web.handlers.argumentHandler.MyCustomerWebArgumentHandler" />  
  5.     </mvc:argument-resolvers>  
  6.   
  7. </mvc:annotation-driven>  
	<mvc:annotation-driven validator="validator">
		<mvc:argument-resolvers>
			<bean
				class="net.zhepu.web.handlers.argumentHandler.MyCustomerWebArgumentHandler" />
		</mvc:argument-resolvers>

	</mvc:annotation-driven>


对应java代码如下

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class MyCustomerWebArgumentHandler implements WebArgumentResolver {   
  2.   
  3.     @Override  
  4.     public Object resolveArgument(MethodParameter methodParameter,   
  5.             NativeWebRequest webRequest) throws Exception {   
  6.         if (methodParameter.getParameterType().equals(MyArgument.class)) {   
  7.             MyArgument argu = new MyArgument();   
  8.             argu.setArgumentName("winzip");   
  9.             argu.setArgumentValue("123456");   
  10.             return argu;   
  11.         }   
  12.         return UNRESOLVED;   
  13.     }   
  14.   
  15. }  
public class MyCustomerWebArgumentHandler implements WebArgumentResolver {

	@Override
	public Object resolveArgument(MethodParameter methodParameter,
			NativeWebRequest webRequest) throws Exception {
		if (methodParameter.getParameterType().equals(MyArgument.class)) {
			MyArgument argu = new MyArgument();
			argu.setArgumentName("winzip");
			argu.setArgumentValue("123456");
			return argu;
		}
		return UNRESOLVED;
	}

}


这里我们定义了一个 customer webArgumentHandler,当handler method中参数类型为 MyArgument时生成对参数的类型绑定操作。 
注意新注册的webArgumentHandler的优先级最低,即如果系统缺省注册的ArgumentHandler已经可以解析对应的参数类型时,就不会再调用到新注册的customer ArgumentHandler了。 

message-converters 
允许注册实现了HttpMessageConverter接口的bean,来对requestbody 或responsebody中的数据进行解析 
例如 
假设我们使用 text/plain格式发送一串字符串来表示User对象,各个属性值使用”|”来分隔。例如 winzip|123456|13818888888,期望转为user对象,各属性内容为user.username = winzip,user.password=123456;user.mobileNO = 13818888888 
以下代码中supports表示此httpmessageConverter实现类针对 User类进行解析。 
构造函数中调用 super(new MediaType("text", "plain"));以表示支持 text/plain格式的输入。 

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class MyCustomerMessageConverter extends  
  2.         AbstractHttpMessageConverter<Object> {   
  3.     @Override  
  4.     protected boolean supports(Class<?> clazz) {   
  5.         if (clazz.equals(User.class)) {   
  6.             return true;   
  7.         }   
  8.         return false;   
  9.     }   
  10.   
  11.     public MyCustomerMessageConverter() {   
  12.         super(new MediaType("text""plain"));   
  13.     }   
  14.   
  15.     @Override  
  16.     protected Object readInternal(Class<? extends Object> clazz,   
  17.             HttpInputMessage inputMessage) throws IOException,   
  18.             HttpMessageNotReadableException {   
  19.         Charset charset;   
  20.         MediaType contentType = inputMessage.getHeaders().getContentType();   
  21.         if (contentType != null && contentType.getCharSet() != null) {   
  22.             charset = contentType.getCharSet();   
  23.         } else {   
  24.             charset = Charset.forName("UTF-8");   
  25.         }   
  26.         String input = FileCopyUtils.copyToString(new InputStreamReader(   
  27.                 inputMessage.getBody(), charset));   
  28.         logger.info(input);   
  29.         String[] s = input.split("\\|");   
  30.         User u = new User();   
  31.         u.setUserName(s[0]);   
  32.         u.setPassword(s[1]);   
  33.         u.setMobileNO(s[2]);   
  34.         return u;   
  35.     }   
  36.   
  37.     @Override  
  38.     protected void writeInternal(Object t, HttpOutputMessage outputMessage)   
  39.             throws IOException, HttpMessageNotWritableException {   
  40.   
  41.     }  
public class MyCustomerMessageConverter extends
		AbstractHttpMessageConverter<Object> {
	@Override
	protected boolean supports(Class<?> clazz) {
		if (clazz.equals(User.class)) {
			return true;
		}
		return false;
	}

	public MyCustomerMessageConverter() {
		super(new MediaType("text", "plain"));
	}

	@Override
	protected Object readInternal(Class<? extends Object> clazz,
			HttpInputMessage inputMessage) throws IOException,
			HttpMessageNotReadableException {
		Charset charset;
		MediaType contentType = inputMessage.getHeaders().getContentType();
		if (contentType != null && contentType.getCharSet() != null) {
			charset = contentType.getCharSet();
		} else {
			charset = Charset.forName("UTF-8");
		}
		String input = FileCopyUtils.copyToString(new InputStreamReader(
				inputMessage.getBody(), charset));
		logger.info(input);
		String[] s = input.split("\\|");
		User u = new User();
		u.setUserName(s[0]);
		u.setPassword(s[1]);
		u.setMobileNO(s[2]);
		return u;
	}

	@Override
	protected void writeInternal(Object t, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException {

	}


修改servlet context xml配置文件,增加message-converters的相应配置如下。

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:message-converters>  
  2.     <bean class="net.zhepu.web.handlers.messageConverterHandler.MyCustomerMessageConverter"></bean>  
  3. </mvc:message-converters>  
        <mvc:message-converters>
            <bean class="net.zhepu.web.handlers.messageConverterHandler.MyCustomerMessageConverter"></bean>
        </mvc:message-converters>




message-codes-resolver 
先看看spring mvc中对于messageCodeResolver的用法。 
spring mvc中使用DefaultMessageCodesResolver作为缺省的MessageCodesResolver的实现类,其作用是对valid errors中的errorcode进行解析。其解析方式如下 
当解析error global object注册的errorcode时,errorcode的查找顺序为 
1:errorcode.validationobjectname 
2:errorcode 
例如 
以下声明中

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public String helloWorld2(@ModelAttribute("user") User u,   
  2.             BindingResult result)  
public String helloWorld2(@ModelAttribute("user") User u,
			BindingResult result)


当使用 result.reject("testFlag");来注册一个globat error object时,spring mvc将在messageSource中先查找 testFlag.user这个errorcode,当找不到时再查找testFlag这个errorcode。 

当解析fields error时,将按以下顺序生成error code 
1.: code + "." + object name + "." + field 
2.: code + "." + field 
3.: code + "." + field type 
4.: code 

还是以上面的代码为例,当使用 result.rejectValue("userName", "testFlag");来注册一个针对user.UserName属性的错误描述时,errors对象中将生成以下的error code list, 
1.: testFlag.user.userName 
2.: testFlag.userName 
3.: testFlag.java.lang.String 
4.: testFlag 

而mvc:annotation-driven新增的属性message-codes-resolver则提供了注册自定义的MessageCodesResolver的手段。 
例如上面想要在所有的error code前增加前缀validation.的话,可以这么来做

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator" message-codes-resolver="messageCodeResolver">  
  2. </mvc:annotation-driven>  
<mvc:annotation-driven validator="validator" message-codes-resolver="messageCodeResolver">
</mvc:annotation-driven>


新增messageCodeResolver bean定义如下

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <bean id="messageCodeResolver" class="org.springframework.validation.DefaultMessageCodesResolver">   
  2.     <property name="prefix" value="validation."></property>   
  3. </bean>  
	<bean >
	    <property name="prefix" value="validation."></property>
	</bean>


此时,所有的errorcode都会生成缺省前缀 validation. 
例如前面的 result.reject("testFlag"); 生成的error code list就变为了 
validation.testFlag.user 和 validation.testFlag了。 




2: @RequestMapping 新增参数Consumes 和Produces 
前面介绍过@RequestMapping的参数中有一个header的参数,来指定handler method能接受的http request 请求的header内容。 
而consumes和produces则更进一步,直接指定所能接受或产生的request请求的content type。 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(value="/testMsgConverter",consumes="text/plain",produces="application/json")  
@RequestMapping(value="/testMsgConverter",consumes="text/plain",produces="application/json")


表示handlermethod接受的请求的header中的 Content-Type为text/plain; 
Accept为application/json 


3: URI Template 新增功能 
这部分的例子直接照抄Spring 3.1 M2: Spring MVC Enhancements中的示例 

1: @PathVariable 声明的参数可自动加入到model中。 
    例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/develop/apps/edit/{slug}")   
  2. public String editForm(@PathVariable String slug, Model model) {   
  3.     model.addAttribute("slug", slug);   
  4.     // ...   
  5. }  
@RequestMapping("/develop/apps/edit/{slug}")
public String editForm(@PathVariable String slug, Model model) {
	model.addAttribute("slug", slug);
    // ...
}


现在可以写为

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/develop/apps/edit/{slug}")   
  2. public String editForm(@PathVariable String slug, Model model) {   
  3.     // model contains "slug" variable   
  4. }  
@RequestMapping("/develop/apps/edit/{slug}")
public String editForm(@PathVariable String slug, Model model) {
    // model contains "slug" variable
}



2:handler method中的redirect string可支持url template了 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(   
  2.     value="/groups/{group}/events/{year}/{month}/{slug}/rooms",   
  3.     method=RequestMethod.POST)   
  4. public String createRoom(   
  5.     @PathVariable String group, @PathVariable Integer year,   
  6.     @PathVariable Integer month, @PathVariable String slug) {   
  7.     // ...   
  8.     return "redirect:/groups/" + group + "/events/" + year + "/" + month + "/" + slug;   
  9. }  
@RequestMapping(
    value="/groups/{group}/events/{year}/{month}/{slug}/rooms",
    method=RequestMethod.POST)
public String createRoom(
    @PathVariable String group, @PathVariable Integer year,
    @PathVariable Integer month, @PathVariable String slug) {
    // ...
    return "redirect:/groups/" + group + "/events/" + year + "/" + month + "/" + slug;
}


现在可写为

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(   
  2.     value="/groups/{group}/events/{year}/{month}/{slug}/rooms",   
  3.     method=RequestMethod.POST)   
  4. public String createRoom(   
  5.     @PathVariable String group, @PathVariable Integer year,   
  6.     @PathVariable Integer month, @PathVariable String slug) {   
  7.     // ...   
  8.     return "redirect:/groups/{group}/events/{year}/{month}/{slug}";   
  9. }  
@RequestMapping(
    value="/groups/{group}/events/{year}/{month}/{slug}/rooms",
    method=RequestMethod.POST)
public String createRoom(
    @PathVariable String group, @PathVariable Integer year,
    @PathVariable Integer month, @PathVariable String slug) {
    // ...
    return "redirect:/groups/{group}/events/{year}/{month}/{slug}";
}


3:url template中可支持databinding 了 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/people/{firstName}/{lastName}/SSN")   
  2. public String find(Person person,   
  3.                    @PathVariable String firstName,   
  4.                    @PathVariable String lastName) {   
  5.     person.setFirstName(firstName);   
  6.     person.setLastName(lastName);   
  7.     // ...   
  8. }  
@RequestMapping("/people/{firstName}/{lastName}/SSN")
public String find(Person person,
                   @PathVariable String firstName,
                   @PathVariable String lastName) {
    person.setFirstName(firstName);
    person.setLastName(lastName);
    // ...
}



现在可以写成

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/people/{firstName}/{lastName}/SSN")   
  2. public String search(Person person) {   
  3.     // person.getFirstName() and person.getLastName() are populated   
  4.     // ...   
  5. }  
@RequestMapping("/people/{firstName}/{lastName}/SSN")
public String search(Person person) {
    // person.getFirstName() and person.getLastName() are populated
    // ...
}



4: Validation For @RequestBody 

@RequestBody现在直接支持@valid标注了,如果validation失败,将抛出 
RequestBodyNotValidException。 
具体处理逻辑可见 spring 中的RequestResponseBodyMethodProcessor中的以下代码。

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1.        
  2. public Object resolveArgument(MethodParameter parameter,   
  3.                                   ModelAndViewContainer mavContainer,   
  4.                                   NativeWebRequest webRequest,   
  5.                                   WebDataBinderFactory binderFactory) throws Exception {   
  6.         Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType());   
  7.         if (shouldValidate(parameter, arg)) {   
  8.             String argName = Conventions.getVariableNameForParameter(parameter);   
  9.             WebDataBinder binder = binderFactory.createBinder(webRequest, arg, argName);   
  10.             binder.validate();   
  11.             Errors errors = binder.getBindingResult();   
  12.             if (errors.hasErrors()) {   
  13.                 throw new RequestBodyNotValidException(errors);   
  14.             }   
  15.         }   
  16.         return arg;   
  17.     }  
	
public Object resolveArgument(MethodParameter parameter,
								  ModelAndViewContainer mavContainer,
								  NativeWebRequest webRequest,
								  WebDataBinderFactory binderFactory) throws Exception {
		Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType());
		if (shouldValidate(parameter, arg)) {
			String argName = Conventions.getVariableNameForParameter(parameter);
			WebDataBinder binder = binderFactory.createBinder(webRequest, arg, argName);
			binder.validate();
			Errors errors = binder.getBindingResult();
			if (errors.hasErrors()) {
				throw new RequestBodyNotValidException(errors);
			}
		}
		return arg;
	}



5:annotation-driven缺省注册类的改变 

Spring 3.0.x中使用了annotation-driven后,缺省使用DefaultAnnotationHandlerMapping 来注册handler method和request的mapping关系。 

AnnotationMethodHandlerAdapter来在实际调用handlermethod前对其参数进行处理。 

并在dispatcherServlet中,当用户未注册自定义的ExceptionResolver时,注册AnnotationMethodHandlerExceptionResolver来对使用@ExceptionHandler标注的异常处理函数进行解析处理(这也导致当用户注册了自定义的exeptionResolver时将可能导致无法处理@ExceptionHandler)。 

在spring mvc 3.1中,对应变更为 
DefaultAnnotationHandlerMapping -> RequestMappingHandlerMapping 
AnnotationMethodHandlerAdapter -> RequestMappingHandlerAdapter 
AnnotationMethodHandlerExceptionResolver -> ExceptionHandlerExceptionResolver 

以上都在使用了annotation-driven后自动注册。 
  而且对应分别提供了AbstractHandlerMethodMapping , AbstractHandlerMethodAdapter和 AbstractHandlerMethodExceptionResolver以便于让用户更方便的实现自定义的实现类。

 
 
 

1:mvc annotation-driven 新增标签 
以下为spring mvc 3.1中annotation-driven所支持的全部配置。 

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven  message-codes-resolver ="bean ref" validator="" conversion-service="">  
  2.       
  3.      <mvc:return-value-handlers>  
  4.         <bean></bean>  
  5.     </mvc:return-value-handlers>  
  6.        
  7.     <mvc:argument-resolvers>  
  8.     </mvc:argument-resolvers>  
  9.        
  10.     <mvc:message-converters>  
  11.     </mvc:message-converters>[/color]   
  12. </mvc:annotation-driven>  
<mvc:annotation-driven  message-codes-resolver ="bean ref" validator="" conversion-service="">
   
     <mvc:return-value-handlers>
        <bean></bean>
    </mvc:return-value-handlers>
    
    <mvc:argument-resolvers>
    </mvc:argument-resolvers>
    
    <mvc:message-converters>
    </mvc:message-converters>[/color]
</mvc:annotation-driven>



其中3.1新增部分如下    
return-value-handlers 
允许注册实现了HandlerMethodReturnValueHandler接口的bean,来对handler method的特定的返回类型做处理。 
HandlerMethodReturnValueHandler接口中定义了两个方法 
supportsReturnType 方法用来确定此实现类是否支持对应返回类型。 
handleReturnValue 则用来处理具体的返回类型。 

例如以下的handlerMethod 

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/testReturnHandlers")   
  2. public User testHandlerReturnMethod(){   
  3.     User u  = new User();   
  4.     u.setUserName("test");   
  5.     return u;   
  6. }  
	@RequestMapping("/testReturnHandlers")
	public User testHandlerReturnMethod(){
		User u  = new User();
		u.setUserName("test");
		return u;
	}


所返回的类型为一个pojo,正常情况下spring mvc无法解析,将转由DefaultRequestToViewNameTranslator 解析出一个缺省的view name,转到 testReturnHandlers.jsp, 
我们增加以下配置

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator">  
  2. color=red]        <mvc:return-value-handlers>    
  3.            <bean  class="net.zhepu.web.handlers.returnHandler.UserHandlers"></bean>    
  4.     </mvc:return-value-handlers>[/color]   
  5. </mvc:annotation-driven>  
	<mvc:annotation-driven validator="validator">
[color=red]        <mvc:return-value-handlers> 
            <bean  class="net.zhepu.web.handlers.returnHandler.UserHandlers"></bean> 
		</mvc:return-value-handlers>[/color]
	</mvc:annotation-driven>


及如下实现类

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class UserHandlers implements HandlerMethodReturnValueHandler {   
  2.     Logger logger = LoggerFactory.getLogger(this.getClass());   
  3.     @Override  
  4.     public boolean supportsReturnType(MethodParameter returnType) {   
  5.         Class<?> type = returnType.getParameterType();   
  6.         if(User.class.equals(type))   
  7.         {   
  8.             return true;   
  9.         }   
  10.         return false;   
  11.     }   
  12.   
  13.     @Override  
  14.     public void handleReturnValue(Object returnValue,   
  15.             MethodParameter returnType, ModelAndViewContainer mavContainer,   
  16.             NativeWebRequest webRequest) throws Exception {   
  17.         logger.info("handler  for return type users ");   
  18.         mavContainer.setViewName("helloworld");   
  19.     }   
  20.   
  21. }  
public class UserHandlers implements HandlerMethodReturnValueHandler {
    Logger logger = LoggerFactory.getLogger(this.getClass());
	@Override
	public boolean supportsReturnType(MethodParameter returnType) {
		Class<?> type = returnType.getParameterType();
		if(User.class.equals(type))
		{
			return true;
		}
		return false;
	}

	@Override
	public void handleReturnValue(Object returnValue,
			MethodParameter returnType, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest) throws Exception {
		logger.info("handler  for return type users ");
		mavContainer.setViewName("helloworld");
	}

}


此时再访问 http://localhost:8080/springmvc/testReturnHandlers ,将交由 UserHandlers来处理返回类型为User的返回值。 

argument-resolvers 
允许注册实现了WebArgumentResolver接口的bean,来对handlerMethod中的用户自定义的参数或annotation进行解析 
例如 

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator">  
  2.     <mvc:argument-resolvers>  
  3.         <bean  
  4.             class="net.zhepu.web.handlers.argumentHandler.MyCustomerWebArgumentHandler" />  
  5.     </mvc:argument-resolvers>  
  6.   
  7. </mvc:annotation-driven>  
	<mvc:annotation-driven validator="validator">
		<mvc:argument-resolvers>
			<bean
				class="net.zhepu.web.handlers.argumentHandler.MyCustomerWebArgumentHandler" />
		</mvc:argument-resolvers>

	</mvc:annotation-driven>


对应java代码如下

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class MyCustomerWebArgumentHandler implements WebArgumentResolver {   
  2.   
  3.     @Override  
  4.     public Object resolveArgument(MethodParameter methodParameter,   
  5.             NativeWebRequest webRequest) throws Exception {   
  6.         if (methodParameter.getParameterType().equals(MyArgument.class)) {   
  7.             MyArgument argu = new MyArgument();   
  8.             argu.setArgumentName("winzip");   
  9.             argu.setArgumentValue("123456");   
  10.             return argu;   
  11.         }   
  12.         return UNRESOLVED;   
  13.     }   
  14.   
  15. }  
public class MyCustomerWebArgumentHandler implements WebArgumentResolver {

	@Override
	public Object resolveArgument(MethodParameter methodParameter,
			NativeWebRequest webRequest) throws Exception {
		if (methodParameter.getParameterType().equals(MyArgument.class)) {
			MyArgument argu = new MyArgument();
			argu.setArgumentName("winzip");
			argu.setArgumentValue("123456");
			return argu;
		}
		return UNRESOLVED;
	}

}


这里我们定义了一个 customer webArgumentHandler,当handler method中参数类型为 MyArgument时生成对参数的类型绑定操作。 
注意新注册的webArgumentHandler的优先级最低,即如果系统缺省注册的ArgumentHandler已经可以解析对应的参数类型时,就不会再调用到新注册的customer ArgumentHandler了。 

message-converters 
允许注册实现了HttpMessageConverter接口的bean,来对requestbody 或responsebody中的数据进行解析 
例如 
假设我们使用 text/plain格式发送一串字符串来表示User对象,各个属性值使用”|”来分隔。例如 winzip|123456|13818888888,期望转为user对象,各属性内容为user.username = winzip,user.password=123456;user.mobileNO = 13818888888 
以下代码中supports表示此httpmessageConverter实现类针对 User类进行解析。 
构造函数中调用 super(new MediaType("text", "plain"));以表示支持 text/plain格式的输入。 

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public class MyCustomerMessageConverter extends  
  2.         AbstractHttpMessageConverter<Object> {   
  3.     @Override  
  4.     protected boolean supports(Class<?> clazz) {   
  5.         if (clazz.equals(User.class)) {   
  6.             return true;   
  7.         }   
  8.         return false;   
  9.     }   
  10.   
  11.     public MyCustomerMessageConverter() {   
  12.         super(new MediaType("text""plain"));   
  13.     }   
  14.   
  15.     @Override  
  16.     protected Object readInternal(Class<? extends Object> clazz,   
  17.             HttpInputMessage inputMessage) throws IOException,   
  18.             HttpMessageNotReadableException {   
  19.         Charset charset;   
  20.         MediaType contentType = inputMessage.getHeaders().getContentType();   
  21.         if (contentType != null && contentType.getCharSet() != null) {   
  22.             charset = contentType.getCharSet();   
  23.         } else {   
  24.             charset = Charset.forName("UTF-8");   
  25.         }   
  26.         String input = FileCopyUtils.copyToString(new InputStreamReader(   
  27.                 inputMessage.getBody(), charset));   
  28.         logger.info(input);   
  29.         String[] s = input.split("\\|");   
  30.         User u = new User();   
  31.         u.setUserName(s[0]);   
  32.         u.setPassword(s[1]);   
  33.         u.setMobileNO(s[2]);   
  34.         return u;   
  35.     }   
  36.   
  37.     @Override  
  38.     protected void writeInternal(Object t, HttpOutputMessage outputMessage)   
  39.             throws IOException, HttpMessageNotWritableException {   
  40.   
  41.     }  
public class MyCustomerMessageConverter extends
		AbstractHttpMessageConverter<Object> {
	@Override
	protected boolean supports(Class<?> clazz) {
		if (clazz.equals(User.class)) {
			return true;
		}
		return false;
	}

	public MyCustomerMessageConverter() {
		super(new MediaType("text", "plain"));
	}

	@Override
	protected Object readInternal(Class<? extends Object> clazz,
			HttpInputMessage inputMessage) throws IOException,
			HttpMessageNotReadableException {
		Charset charset;
		MediaType contentType = inputMessage.getHeaders().getContentType();
		if (contentType != null && contentType.getCharSet() != null) {
			charset = contentType.getCharSet();
		} else {
			charset = Charset.forName("UTF-8");
		}
		String input = FileCopyUtils.copyToString(new InputStreamReader(
				inputMessage.getBody(), charset));
		logger.info(input);
		String[] s = input.split("\\|");
		User u = new User();
		u.setUserName(s[0]);
		u.setPassword(s[1]);
		u.setMobileNO(s[2]);
		return u;
	}

	@Override
	protected void writeInternal(Object t, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException {

	}


修改servlet context xml配置文件,增加message-converters的相应配置如下。

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:message-converters>  
  2.     <bean class="net.zhepu.web.handlers.messageConverterHandler.MyCustomerMessageConverter"></bean>  
  3. </mvc:message-converters>  
        <mvc:message-converters>
            <bean class="net.zhepu.web.handlers.messageConverterHandler.MyCustomerMessageConverter"></bean>
        </mvc:message-converters>




message-codes-resolver 
先看看spring mvc中对于messageCodeResolver的用法。 
spring mvc中使用DefaultMessageCodesResolver作为缺省的MessageCodesResolver的实现类,其作用是对valid errors中的errorcode进行解析。其解析方式如下 
当解析error global object注册的errorcode时,errorcode的查找顺序为 
1:errorcode.validationobjectname 
2:errorcode 
例如 
以下声明中

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. public String helloWorld2(@ModelAttribute("user") User u,   
  2.             BindingResult result)  
public String helloWorld2(@ModelAttribute("user") User u,
			BindingResult result)


当使用 result.reject("testFlag");来注册一个globat error object时,spring mvc将在messageSource中先查找 testFlag.user这个errorcode,当找不到时再查找testFlag这个errorcode。 

当解析fields error时,将按以下顺序生成error code 
1.: code + "." + object name + "." + field 
2.: code + "." + field 
3.: code + "." + field type 
4.: code 

还是以上面的代码为例,当使用 result.rejectValue("userName", "testFlag");来注册一个针对user.UserName属性的错误描述时,errors对象中将生成以下的error code list, 
1.: testFlag.user.userName 
2.: testFlag.userName 
3.: testFlag.java.lang.String 
4.: testFlag 

而mvc:annotation-driven新增的属性message-codes-resolver则提供了注册自定义的MessageCodesResolver的手段。 
例如上面想要在所有的error code前增加前缀validation.的话,可以这么来做

Xml代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <mvc:annotation-driven validator="validator" message-codes-resolver="messageCodeResolver">  
  2. </mvc:annotation-driven>  
<mvc:annotation-driven validator="validator" message-codes-resolver="messageCodeResolver">
</mvc:annotation-driven>


新增messageCodeResolver bean定义如下

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. <bean id="messageCodeResolver" class="org.springframework.validation.DefaultMessageCodesResolver">   
  2.     <property name="prefix" value="validation."></property>   
  3. </bean>  
	<bean >
	    <property name="prefix" value="validation."></property>
	</bean>


此时,所有的errorcode都会生成缺省前缀 validation. 
例如前面的 result.reject("testFlag"); 生成的error code list就变为了 
validation.testFlag.user 和 validation.testFlag了。 




2: @RequestMapping 新增参数Consumes 和Produces 
前面介绍过@RequestMapping的参数中有一个header的参数,来指定handler method能接受的http request 请求的header内容。 
而consumes和produces则更进一步,直接指定所能接受或产生的request请求的content type。 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(value="/testMsgConverter",consumes="text/plain",produces="application/json")  
@RequestMapping(value="/testMsgConverter",consumes="text/plain",produces="application/json")


表示handlermethod接受的请求的header中的 Content-Type为text/plain; 
Accept为application/json 


3: URI Template 新增功能 
这部分的例子直接照抄Spring 3.1 M2: Spring MVC Enhancements中的示例 

1: @PathVariable 声明的参数可自动加入到model中。 
    例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/develop/apps/edit/{slug}")   
  2. public String editForm(@PathVariable String slug, Model model) {   
  3.     model.addAttribute("slug", slug);   
  4.     // ...   
  5. }  
@RequestMapping("/develop/apps/edit/{slug}")
public String editForm(@PathVariable String slug, Model model) {
	model.addAttribute("slug", slug);
    // ...
}


现在可以写为

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/develop/apps/edit/{slug}")   
  2. public String editForm(@PathVariable String slug, Model model) {   
  3.     // model contains "slug" variable   
  4. }  
@RequestMapping("/develop/apps/edit/{slug}")
public String editForm(@PathVariable String slug, Model model) {
    // model contains "slug" variable
}



2:handler method中的redirect string可支持url template了 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(   
  2.     value="/groups/{group}/events/{year}/{month}/{slug}/rooms",   
  3.     method=RequestMethod.POST)   
  4. public String createRoom(   
  5.     @PathVariable String group, @PathVariable Integer year,   
  6.     @PathVariable Integer month, @PathVariable String slug) {   
  7.     // ...   
  8.     return "redirect:/groups/" + group + "/events/" + year + "/" + month + "/" + slug;   
  9. }  
@RequestMapping(
    value="/groups/{group}/events/{year}/{month}/{slug}/rooms",
    method=RequestMethod.POST)
public String createRoom(
    @PathVariable String group, @PathVariable Integer year,
    @PathVariable Integer month, @PathVariable String slug) {
    // ...
    return "redirect:/groups/" + group + "/events/" + year + "/" + month + "/" + slug;
}


现在可写为

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping(   
  2.     value="/groups/{group}/events/{year}/{month}/{slug}/rooms",   
  3.     method=RequestMethod.POST)   
  4. public String createRoom(   
  5.     @PathVariable String group, @PathVariable Integer year,   
  6.     @PathVariable Integer month, @PathVariable String slug) {   
  7.     // ...   
  8.     return "redirect:/groups/{group}/events/{year}/{month}/{slug}";   
  9. }  
@RequestMapping(
    value="/groups/{group}/events/{year}/{month}/{slug}/rooms",
    method=RequestMethod.POST)
public String createRoom(
    @PathVariable String group, @PathVariable Integer year,
    @PathVariable Integer month, @PathVariable String slug) {
    // ...
    return "redirect:/groups/{group}/events/{year}/{month}/{slug}";
}


3:url template中可支持databinding 了 
例如

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/people/{firstName}/{lastName}/SSN")   
  2. public String find(Person person,   
  3.                    @PathVariable String firstName,   
  4.                    @PathVariable String lastName) {   
  5.     person.setFirstName(firstName);   
  6.     person.setLastName(lastName);   
  7.     // ...   
  8. }  
@RequestMapping("/people/{firstName}/{lastName}/SSN")
public String find(Person person,
                   @PathVariable String firstName,
                   @PathVariable String lastName) {
    person.setFirstName(firstName);
    person.setLastName(lastName);
    // ...
}



现在可以写成

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1. @RequestMapping("/people/{firstName}/{lastName}/SSN")   
  2. public String search(Person person) {   
  3.     // person.getFirstName() and person.getLastName() are populated   
  4.     // ...   
  5. }  
@RequestMapping("/people/{firstName}/{lastName}/SSN")
public String search(Person person) {
    // person.getFirstName() and person.getLastName() are populated
    // ...
}



4: Validation For @RequestBody 

@RequestBody现在直接支持@valid标注了,如果validation失败,将抛出 
RequestBodyNotValidException。 
具体处理逻辑可见 spring 中的RequestResponseBodyMethodProcessor中的以下代码。

Java代码 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1 Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
    





            
Spring MVC 学习笔记 十五 what's new in spring mvc 3.1
  1.        
  2. public Object resolveArgument(MethodParameter parameter,   
  3.                                   ModelAndViewContainer mavContainer,   
  4.                                   NativeWebRequest webRequest,   
  5.                                   WebDataBinderFactory binderFactory) throws Exception {   
  6.         Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType());   
  7.         if (shouldValidate(parameter, arg)) {   
  8.             String argName = Conventions.getVariableNameForParameter(parameter);   
  9.             WebDataBinder binder = binderFactory.createBinder(webRequest, arg, argName);   
  10.             binder.validate();   
  11.             Errors errors = binder.getBindingResult();   
  12.             if (errors.hasErrors()) {   
  13.                 throw new RequestBodyNotValidException(errors);   
  14.             }   
  15.         }   
  16.         return arg;   
  17.     }  
	
public Object resolveArgument(MethodParameter parameter,
								  ModelAndViewContainer mavContainer,
								  NativeWebRequest webRequest,
								  WebDataBinderFactory binderFactory) throws Exception {
		Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType());
		if (shouldValidate(parameter, arg)) {
			String argName = Conventions.getVariableNameForParameter(parameter);
			WebDataBinder binder = binderFactory.createBinder(webRequest, arg, argName);
			binder.validate();
			Errors errors = binder.getBindingResult();
			if (errors.hasErrors()) {
				throw new RequestBodyNotValidException(errors);
			}
		}
		return arg;
	}



5:annotation-driven缺省注册类的改变 

Spring 3.0.x中使用了annotation-driven后,缺省使用DefaultAnnotationHandlerMapping 来注册handler method和request的mapping关系。 

AnnotationMethodHandlerAdapter来在实际调用handlermethod前对其参数进行处理。 

并在dispatcherServlet中,当用户未注册自定义的ExceptionResolver时,注册AnnotationMethodHandlerExceptionResolver来对使用@ExceptionHandler标注的异常处理函数进行解析处理(这也导致当用户注册了自定义的exeptionResolver时将可能导致无法处理@ExceptionHandler)。 

在spring mvc 3.1中,对应变更为 
DefaultAnnotationHandlerMapping -> RequestMappingHandlerMapping 
AnnotationMethodHandlerAdapter -> RequestMappingHandlerAdapter 
AnnotationMethodHandlerExceptionResolver -> ExceptionHandlerExceptionResolver 

以上都在使用了annotation-driven后自动注册。 
  而且对应分别提供了AbstractHandlerMethodMapping , AbstractHandlerMethodAdapter和 AbstractHandlerMethodExceptionResolver以便于让用户更方便的实现自定义的实现类。

相关文章:

  • 2021-10-17
  • 2021-04-21
  • 2021-05-02
  • 2021-06-29
  • 2021-07-13
  • 2021-08-22
猜你喜欢
  • 2022-12-23
  • 2021-09-23
  • 2021-05-01
  • 2021-12-21
  • 2022-03-09
  • 2021-09-29
  • 2021-08-06
相关资源
相似解决方案