首页 > IT职业 > IT生活 > Spring MVC返回视图原理(五)
Spring MVC非常灵活,在使用的时候可以返回视图,也可以直接返回普通数据,在想,内部是怎么实现的呢?
经过了几天研究Spring MVC的源码,可以看前几篇文章,今天再弄明白下为什么有时候返回视图,有时候直接返回数据呢。
dispatcher org.springframework.web.servlet.DispatcherServlet dispatcher / dispatcher-servlet.xml中视图配置
Controller类
@RequestMapping("/hello")
@ResponseBody
public String hello(){
return "hello";
}
@RequestMapping("/index")
public String indexView(){
return "index";
} 
访问进行调试,关于DispatcherServlet的流程,我们前面的文章已经都说过了,这里不做太多的赘述,getHandler, getHandlerAdapter,基本不变,在HandlerAdapter.handler(Handler)的时候内部有些不同。
返回视图与返回数据刚开始步骤基本都一样,invoke返回的值也是相同的。
真正产生变化的地方,在处理最后的返回值时

HandlerMethodReturnValueHandler有两个方法:
/**
* Iterate over registered {@link HandlerMethodReturnValueHandler}s and invoke the one that supports it.
* @throws IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found.
*/
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
} 
如果是@ResponseBody注解的时候由RequestResponseBodyMethodProcessor处理。
//RequestResponseBodyMethodProcessor
@Override
public boolean supportsReturnType(MethodParameter returnType) {
//判断是否有ResponseBody.class的注解
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
} 返回值是String,但不加@ResponseBody注解的时候由ViewNameMethodReturnValueHandler处理。
// ViewNameMethodReturnValueHandler
@Override
public boolean supportsReturnType(MethodParameter returnType) {
//参数类型如果是void或者可以CharSequence.class.isAssignableFrom
Class> paramType = returnType.getParameterType();
return (void.class == paramType || CharSequence.class.isAssignableFrom(paramType));
} 如果返回值为ModelAndView的时候,由ModelAndViewMethodReturnValueHandler处理
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
} 其余的可以自行查看。
对于返回数据类型的操作,其将mavContainer的requestHandled设置为true,然后ModelAndView就会返回为null,后续的处理就不按照视图来处理。
如果返回的是视图,那么requestHandled仍然为false,后续再processDispatchResult中进行render.
Spring MVC对不同的返回值处理的方式不同,依靠的是HandlerMethodReturnValueHandler的不同实现。
主要在invoke方法之后,返回值与刚才激发的方法都被封装在ServletInvocableHandlerMethod里面了,其可以通过Method对象获取加在方法上的注解,类等等信息,最后做出结果。
抓住DispatcherServlet的大体框架之后,其中的细节就简答的多了。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2718/viewspace-2812410/ ,如需转载,请注明出处,否则将追究法律责任。