1 SpringMVC执行流程
简单流程:
1 前端发起web请求
2 dispatchServlet收到请求,转发到对应的controller
3 controller处理业务逻辑,将处理结果或页面返回给dispatchServlet
4 dispatchServlet再将结果转发到视图解析器view
5 视图解析器解析结果返回到web端
详细流程:
1 前端发起web请求
2 dispatchServlet收到请求,基于handlerMapping地址映射,找到对应的handler(控制器,即controller)
3 基于handler找对应的handlerAdapter,调用handler方法返回ModelaAndView
4 利用viewResolver,通过返回的ModelAndView找到对应的view视图解析器
5 解析视图,response返回结果到web端
2 springmvc组件
2.1 HandlerMapping
HandlerMapping即url映射,根据web端的地址找到处理该请求的控制器,就是HandlerMapping做的事。通过HandlerMapping继承树,可以发现有三个子类。
- SimpleUrlHandlerMapping:需手动配置映射关系。
<bean name="simpleControl" class="com.control.SimpleControl"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<props>
<prop key="/hello.do">simpleControl</prop>
</props>
</property>
</bean>
BeanNameUrlHandlerMapping:根据配置的beanname自动从映射关系中找到controller。
<bean name="simpleControl" class="com.control.SimpleControl"/>
RequestMappingHandlerMapping:我们工作中最常用的,通过@RequestMapping映射。这里不做举例。
springmvc中默认配置的是BeanNameUrlHandlerMapping。前两个是类映射,RequestMappingHandlerMapping是方法映射。
注意:
1 如果自己配置了HandlerMapping,那么默认的就不生效了
2 可以配置多个HandlerMapping。如果配置了多个HandlerMapping,且urlname一样,那么会根据HandlerMapping的order排序值选择HandlerMapping
2.2 HandlerAdapter
HandlerAdapter即适配器,每个Handler都对应一个适配器来调用handler。
springmvc默认配置了SimpleControllerHandlerAdapter和HttpRequestHandlerAdapter
2.3 Handler
Handler可以理解为controller,即控制器,用于处理业务逻辑,返回ModelAndView。Handler具体实现有以下四种。
- Controller
public class TestController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView("userView");
modelAndView.addObject("name","小明");
return modelAndView;
}
}
- HttpRequestHandler
public class TestHttpRequestHandler implements HttpRequestHandler {
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("666");
}
}
- HttpServlet
public class TestHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("666");
}
}
在使用HttpServlet时,必须配置一个对应的适配器。因为springmvc默认配置的适配器是上面两个handler对应的适配器。
<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>
- @RequestMapping注解(常用的,此处不举例了)
2.4 ViewResolver
ViewResolver是用来管理视图解析器view的。ViewResolver中只有一个方法。根据viewName找到view。
View resolveViewName(String viewName, Locale locale) throws Exception;
ViewResolver有三个常用的实现类:
- BeanNameViewResolver 根据名称找到对应的View
<bean name="myView" class="com.control.MyView"/>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
public class TestController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView("myView");
modelAndView.addObject("name","小明");
return modelAndView;
}
}
public class MyView implements View {
public String getContentType() {
return null;
}
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
//model.get("name")就是controller中设置的属性
response.getWriter().println(model.get("name"));
}
}
- InternalResourceViewResolver
这是springmvc默认配置的ViewResolver,也可手动修改配置,添加前后缀。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"/>
<property name="suffix" value=".jsp"/>
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
</bean>
- AbstractTemplateViewResolver
包括FreeMarkerViewResolver和GroovyMarkupViewResolver。没怎么用过,这里不做举例了。
2.5 View
View就是视图解析器,作用是对ModelAndView中的数据解析,通过Response返回到web端。实现View接口,重写render方法,就能自定义一个视图解析器
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
2.6 HandlerExceptionResolver
HandlerExceptionResolver即异常处理器,用于处理整个springmvc执行流程中出现的异常。
2.6.1 常用的有三个异常处理器:
springmvc默认配置的是DefaultHandlerExceptionResolver和ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
根据传入的Exception异常参数判断是哪种具体的异常来进行相应的处理返回。‘ResponseStatusExceptionResolver
根据异常类型上面的@ResponseStatus注解的code和reason参数,
返回对应的错误信息
@ResponseStatus(code = HttpStatus.GATEWAY_TIMEOUT, reason = "访问超时")
public class ResponseStatusException extends RuntimeException {
public ResponseStatusException() {
}
public ResponseStatusException(String message) {
super(message);
}
}
public class TestController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView("myView");
//这边强制抛出一个ResponseStatusException,测试用
if(true){
throw new ResponseStatusException();
}
modelAndView.addObject("name","小明");
return modelAndView;
}
}
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"/>
虽然springmvc默认配置了这个ResponseStatusExceptionResolver,但还是要自己配置一下,因为这里自定义了一个异常,所以默认的配置无法生效。
这时,web端访问这个TestController对应的url,就会出现504异常GATEWAY_TIMEOUT
- SimpleMappingExceptionResolver
将异常和异常处理页面绑定,如果出现异常就跳转到绑定页面
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--默认的异常处理页面-->
<property name="defaultErrorView" value="error"/>
<!--默认的异常状态码-->
<property name="defaultStatusCode" value="500"/>
<!--异常与页面对应关系配置-->
<property name="exceptionMappings">
<map>
<entry key="java.lang.RuntimeException" value="error"/>
<entry key="java.lang.IllegalArgumentException" value="argumentError"/>
</map>
</property>
</bean>
2.6.2 自定义异常处理器
实现HandlerExceptionResolver接口,并重写resolveException方法。
public class SimpleExceptionHandle implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("message", ex.getMessage());
ByteArrayOutputStream out = new ByteArrayOutputStream();
//将异常信息通过打印流打印到输出流out中
ex.printStackTrace(new PrintStream(out, true));
modelAndView.addObject("stack", out.toString());
return modelAndView;
}
}
意思就是获取异常信息,打印到输出流中,并放入ModelAndView,通过视图解析器返回到error.jsp页面显示错误信息。
<bean class="com.study.control.MyExceptionResolver"/>
配置自定义异常处理器。
2.7 HandlerInterceptor
HandlerInterceptor即拦截器。有以下三个方法
- preHandle 在调用handler方法之前调用。
- postHandle 在成功调用handler方法后调用。
- afterCompletion 在调用handler方法之后调用。即使在调用handler方法时出现异常,也会调用afterCompletion。如果没有异常,则顺序在postHandle之后。
自定义拦截器示例:
public class SimpleHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
配置拦截器:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.control.SimpleHandlerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
可以定义多个拦截器,形成一个拦截器链,比如在handler方法之前会依此遍历拦截器链,依此调用所有拦截器的preHandle方法。
注:异常处理器不是所有配置的都执行。如果在异常处理器的resolveException中返回ModelAndView,表示异常已经被这个异常处理器处理了;如果返回null,表示没有处理,会去找下一个异常处理器处理。
而拦截器则是所有配置的拦截器都会执行。
3 springmvc执行流程源码解析
springmvc执行流程的核心就是DispatcherServlet的doDispatch方法。
下面就拿@RequestMapping方式来解析。
1 注册handler
HandlerMapping可以根据url来找到对应的handler,那么这些对应关系是怎么注册的呢?
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
//校验
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// 如果是懒加载的,就存handler的名字
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
if (getApplicationContext().isSingleton(handlerName)) {
// 从spring容器中根据beanname获取bean
resolvedHandler = getApplicationContext().getBean(handlerName);
}
}
// url跟handler对应关系保存在handerMap中
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
// 如果url是/,那么设置这个handler是根handler
if (urlPath.equals("/")) {
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
//如果url是/*,那么设置这个handler为默认的handler,所有找不到对应关系的都找这个handler
else if (urlPath.equals("/*")) {
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
// 将url作为key,handler作为value,存在handlerMap中
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}
2 doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 获取handler
mappedHandler = getHandler(processedRequest);
//如果没有获取到,抛错
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 获取处理这个handler的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 通过适配器调用handle方法处理业务逻辑
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果没指定viewName,设置一个默认的viewName
applyDefaultViewName(processedRequest, mv);
//执行拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
//上面所有的异常都只是抛出,没处理,这里才是捕获异常
dispatchException = ex;
}
catch (Throwable err) {
// err错误
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 视图解析器处理modelAndView,通过response返回数据给web端
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// 不管是否出错,都会最后执行拦截器的afterCompletion方法
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
执行过程:
1 根据HandlerMapping获取handler链
2 根据handler获取对应的适配器
3 执行拦截器的preHandle方法
4 通过适配器,调用handle方法处理业务逻辑
5 如果没有异常,执行拦截器的postHandle方法
6 不管有没有异常,执行拦截器的afterCompletion方法
7 视图解析器处理modelAndView,通过response返回数据给web端
3.2.1 getHandler
获取handler链
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历1中的handlerMapping,找handler
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//获取HandlerExecutionChain,并不是返回Handler,因为里面还包含拦截器链
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取handler,因为是@RequestMaping,所以这里获取HandlerMethod
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// 如果是懒加载,那么根据之前注册时存的handlerName获取handler
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
// 将handler和所有拦截器封装成一个handler链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取url路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
// 获取执行业务逻辑的方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
3.2.2 getHandlerAdapter
获取handler对应的适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
// 遍历所有适配器
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
// 如果支持,就返回适配器
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
3.2.3 applyPreHandle
调用所有拦截器的preHandle方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
// 如果前置拦截返回false,就调用后置拦截,然后直接返回到web端,不执行业务逻辑了
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
3.2.4 handle
通过适配器调用handle方法,执行业务逻辑
因为这里是@RequestMapping,所以进入RequestMappingHandlerAdapter的invokeHandlerMethod方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 设置一个方法执行器
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
//设置参数处理器 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
//设置返回值处理器 invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
// 设置参数名字处理器,可以根据请求参数中名字,自动对应到handler的目标方法的参数名字 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 通过方法执行器调用方法,处理业务逻辑
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 执行目标方法
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
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;
}
}
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 获取方法中的参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"' with arguments " + Arrays.toString(args));
}
// 通过反射调用目标方法,获取返回结果ModelAndView
Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"] returned [" + returnValue + "]");
}
return returnValue;
}
3.2.5 applyPostHandle
执行拦截器的中间方法,由于在执行业务方法之后,如果出现异常,拦截器中间方法并不会执行
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
3.2.6 applyAfterConcurrentHandlingStarted
此方法在finally中,所以不管有没有异常,都会执行这个拦截器的后置方法
3.2.7 processDispatchResult
捕获业务逻辑执行中的异常并在此统一处理,然后视图解析器处理ModelAndView,封装数据,返回给web端
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
//处理异常,封装到ModelAndView中
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// 视图解析器处理ModelAndView
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
// 根据viewName从ViewResolver中获取视图解析器
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
// 调用view的render方法,处理数据,通过response返回
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
至此SpringMVC的执行流程解析完毕。