在使用springmvc提供的註解進行方法參數的解析綁定和方法返回值處理的時候,比如說有時候會報出令人不解的400或500之類的錯誤;自以爲掌握了註解的用法但是實現起來複雜不簡潔,這情況下進行參數綁定的擴展更爲合理,等等這些情況都需要我們能深入地瞭解springmvc的內部實現。在進行錯誤調試的時候,如果能根據不同的參數類型,註解和返回值類型深入到springmvc具體的實現類源代碼進行跟蹤查看,有助於我們高效優雅地使用springmvc。
1.進行方法參數值的解析的接口是HandlerMethodArgumentResolver
下面是一些具體的實現類,它們針對不同的註解實現不同的解析綁定功能:
1. RequestParamMethodArgumentResolver
支持帶有@RequestParam註解的參數或帶有MultipartFile類型的參數
2. RequestParamMapMethodArgumentResolver
支持帶有@RequestParam註解的參數 && @RequestParam註解的屬性value存在 && 參數類型是實現Map接口的屬性
3. PathVariableMethodArgumentResolver
支持帶有@PathVariable註解的參數 且如果參數實現了Map接口,@PathVariable註解需帶有value屬性
4. MatrixVariableMethodArgumentResolver
支持帶有@MatrixVariable註解的參數 且如果參數實現了Map接口,@MatrixVariable註解需帶有value屬性
5. RequestResponseBodyMethodProcessor
解析綁定帶有@RequestBody的方法參數和帶有@ResponseBody的方法返回值
6. ServletRequestMethodArgumentResolver
參數類型是實現或繼承或是WebRequest、ServletRequest、MultipartRequest、HttpSession、Principal、Locale、TimeZone、InputStream、Reader、HttpMethod這些類。
7. ServletResponseMethodArgumentResolver
參數類型是實現或繼承或是ServletResponse、OutputStream、Writer這些類
8. RedirectAttributesMethodArgumentResolver
參數是實現了RedirectAttributes接口的類
9. HttpEntityMethodProcessor
參數類型是HttpEntity
從名字我們也看的出來, 以Resolver結尾的是實現了HandlerMethodArgumentResolver接口的類,以Processor結尾的是實現了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler的類。
注意:如果controller的方法沒有任何參數的註解,但有參數對象而且參數對象的類型是簡單類型,則會默認調用RequestParamMethodArgumentResolver類進行解析,從httpServletRequest中獲取parameter,然後調用參數對象的set方法進行注入。
這是RequestParamMethodArgumentResolver類所支持的解析類型方法:
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
if (parameter.hasParameterAnnotation(RequestParam.class)) {
if (Map.class.isAssignableFrom(paramType)) {
String paramName = parameter.getParameterAnnotation(RequestParam.class).value();
return StringUtils.hasText(paramName);
}
else {
return true;
}
}
else {
if (parameter.hasParameterAnnotation(RequestPart.class)) {
return false;
}
else if (MultipartFile.class.equals(paramType) || "javax.servlet.http.Part".equals(paramType.getName())) {
return true;
}
else if (this.useDefaultResolution) {
return BeanUtils.isSimpleProperty(paramType);//判斷是否是簡單類型
}
else {
return false;
}
}
}
判斷簡單類型的方法:
public static boolean isSimpleValueType(Class<?> clazz) {
return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||//isPrimitiveOrWrapper方法是判斷參數類型是否是基本類或基本類的包裝類
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
clazz.equals(URI.class) || clazz.equals(URL.class) ||
clazz.equals(Locale.class) || clazz.equals(Class.class);
}
如果沒有註解的參數的類型不是簡單類型而是複合類型,就是用類ModelAttributeMethodProcessor來解析:
/**
* @return true if the parameter is annotated with {@link ModelAttribute}
* or in default resolution mode also if it is not a simple type.
*/
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
return true;
}
else if (this.annotationNotRequired) {
return !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
else {
return false;
}
}
2.方法返回值處理接口HandlerMethodReturnValueHandler
下面是一些具體的實現類,它們針對不同的註解或返回值類型實現不同的功能:
1. ModelAndViewMethodReturnValueHandler
返回值類型是ModelAndView或其子類
2. ModelMethodProcessor
返回值類型是Model或其子類
3. ViewMethodReturnValueHandler
返回值類型是View或其子類
4. HttpHeadersReturnValueHandler
返回值類型是HttpHeaders或其子類
5. ModelAttributeMethodProcessor
返回值有@ModelAttribute註解
6. ViewNameMethodReturnValueHandler
返回值是void或String,並且返回值沒有註解
7.RequestResponseBodyMethodProcessor
返回值有@ResponseBody註解
參考自:http://www.cnblogs.com/fangjian0423/p/springMVC-request-param-analysis.html