在学习Spring框架时,我在《 Spring in Action 》一书中注意到,作者并未ModelandView在控制器中使用方法返回类型。作者将控制器方法声明为的返回类型,String并且该方法中的return子句仅返回诸如以下的字符串return "/views/theview";
ModelandView
String
return "/views/theview";
有人可以详细说明其工作方式的内部差异吗?
这是深入了解。
Spring提供了一个DispatcherServlet通常处理所有请求的类。它以其doDispatch(HttpServletRequest request, HttpServletResponse response)方法做到这一点
DispatcherServlet
doDispatch(HttpServletRequest request, HttpServletResponse response)
// Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
mv最终ModelAndView对象在哪里,ha是用注释的控制器方法的包装@RequestMapping。
mv
ModelAndView
ha
@RequestMapping
这通常会经过一堆方法调用,最终以 ServletInvocableHandlerMethod.invokeAndHandle
ServletInvocableHandlerMethod.invokeAndHandle
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle at org.springframework.web.servlet.DispatcherServlet.doDispatch
看源头
public final void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue == null) { if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) { mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(this.responseReason)) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); try { this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex); } throw ex; } }
returnValue是您的@RequestMapping方法返回的对象。它经历了
returnValue
this.returnValueHandlers.handleReturnValue
Spring确定HandlerMethodReturnValueHandler要处理该对象的位置。
HandlerMethodReturnValueHandler
public void handleReturnValue( Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); // returns the appropriate handler Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]"); handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); }
getReturnValueHandler(returnType);返回适当的处理程序。的HandlerMethodReturnValueHandler是具有一个接口supportsReturnType方法,该方法返回true,如果处理程序支持该类型(String,View,ResponseEntity,等。(外表支持的返回类型))。因此,该方法返回它找到的第一个处理程序,该处理程序支持该类型并运行它。
getReturnValueHandler(returnType);
supportsReturnType
true
View
ResponseEntity
Spring在初始化时会注册的完整实现HandlerMethodReturnValueHandler。基本上所有已知的实现类都在其javadoc中。
例如,如果您返回一个String,Spring将使用a ViewNameMethodReturnValueHandler来处理响应。
ViewNameMethodReturnValueHandler
现在,由您决定使用哪种返回类型。如果要返回a Model以便可以在jsp视图中使用请求属性,则可以让Spring将Model实例传递给方法,也可以Model自己创建对象并将其传递给ModelAndView返回的对象。在大多数情况下,这都是风格问题。
Model