目录
一.SpringMVC执行流程解析
- 根据request请求URL,循环遍历HandlerMapping列表获取包含Handler和HandlerInterceptor的HandlerExecutionChain对象;
- 然后通过HandlerExecutionChain对象内部Handler实例循环遍历HandlerAdapter列表获取适配器对象;
- 执行HandlerExecutionChain内部的所有拦截器HandlerInterceptor的preHandle方法,成功返回true,返回false直接return;
- 如果拦截器preHandle执行成功,再使用HandlerAdapter适配器去执行Handler的业务逻辑并返回一个ModelAndView对象;
- 执行所有拦截器postHandle方法;
- 通过ModelAndView对象的view属性的值(实际上就是viewName)从ViewResolver集合中获取View对象;
- 将ModelAndView中model数据渲染到View返回HTML基于response输出到终端;
- 执行所有拦截器的afterCompletion方法;
- 上述执行过程中如果出现未主动try catch的异常,都将被HandlerExceptionResolver捕获处理。
二.体系结构UML
三.关键对象介绍
(一)DispatcherServlet
继承自HttpServlet实现了对HTTP请求的捕获处理
1. 关键成员属性:
handlerMappings、handlerAdapters、handlerExceptionResolvers和viewResolvers。
/** List of HandlerMappings used by this servlet */
private List<HandlerMapping> handlerMappings;
/** List of HandlerAdapters used by this servlet */
private List<HandlerAdapter> handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet */
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** RequestToViewNameTranslator used by this servlet */
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMapManager used by this servlet */
private FlashMapManager flashMapManager;
/** List of ViewResolvers used by this servlet */
private List<ViewResolver> viewResolvers;
2. 关键成员方法:
- doDispatch请求调度处理方法:
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception
- getHandler:返回匹配当前request请求的HandlerExecutionChain执行链对象。
/**
* Return the HandlerExecutionChain for this request.
* <p>Tries all handler mappings in order.
* @param request current HTTP request
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception
- getHandlerAdapter:返回适配当前request请求对应Handler的适配器。
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException
- processDispatchResult:处理Handler执行结果。
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception
- triggerAfterCompletion:触发执行当前request请求拦截器链的afterCompletion方法。
private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, Exception ex) throws Exception
(二)Handler
具体业务逻辑的处理器handler
1. 实现方式:
- 实现Controller接口
public interface Controller {
/**
* Process the request and return a ModelAndView object which the DispatcherServlet
* will render. A {@code null} return value is not an error: it indicates that
* this object completed request processing itself and that there is therefore no
* ModelAndView to render.
* @param request current HTTP request
* @param response current HTTP response
* @return a ModelAndView to render, or {@code null} if handled directly
* @throws Exception in case of errors
*/
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
- 实现HttpRequestHandler接口
public interface HttpRequestHandler {
/**
* Process the given request, generating a response.
* @param request current HTTP request
* @param response current HTTP response
* @throws ServletException in case of general errors
* @throws IOException in case of I/O errors
*/
void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
- 实现Servlet类
- 采用@requestMapping注解实现
(三)HandlerMapping
存储请求URL与处理器Handler对象的映射。
1. 关键成员方法:
- getHandler:返回一个handler执行链对象,对象包含有Handler和HandlerInterceptor拦截器。
/**
* Return a handler and any interceptors for this request. The choice may be made
* on request URL, session state, or any factor the implementing class chooses.
* <p>The returned HandlerExecutionChain contains a handler Object, rather than
* even a tag interface, so that handlers are not constrained in any way.
* For example, a HandlerAdapter could be written to allow another framework's
* handler objects to be used.
* <p>Returns {@code null} if no match was found. This is not an error.
* The DispatcherServlet will query all registered HandlerMapping beans to find
* a match, and only decide there is an error if none can find a handler.
* @param request current HTTP request
* @return a HandlerExecutionChain instance containing handler object and
* any interceptors, or {@code null} if no mapping found
* @throws Exception if there is an internal error
*/
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
2. 接口的实现类
- BeanNameUrlHandlerMapping:基于Spring IoC容器配置的name属性以“/”开头的Bean实例class属性指定的handler注册到映射。
- SimpleUrlHandlerMapping:基于手动配置url与handler映射关系的Bean实例注册到映射。
- RequestMappingHandlerMapping:基于@RequestMapping注解方式实现的handler注册到映射。
(四)HandlerAdapter
执行handler的适配器,SpringMVC采用适配器模式来适配调用指定Handler,根据Handler的不同种类采用不同的Adapter,其Handler与 HandlerAdapter 对应关系如下:
Handler类型 | 对应的Adapter适配器 | 说明 |
Controller | SimpleControllerHandlerAdapter | 标准控制器,返回ModelAndView |
HttpRequestHandler | HttpRequestHandlerAdapter | 业务自行处理请求,不需要通过ModelAndView转到视图 |
Servlet | SimpleServletHandlerAdapter | 基于标准的servlet 处理 |
HandlerMethod | RequestMappingHandlerAdapter | 基于@requestMapping注解方法处理 |
1. 接口实现类:
2. 关键成员方法:
- supports:判断当前类型的适配器是否支持传入的Handler对象。
/**
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);
- handler:适配器执行Handler业务逻辑,返回ModelAndView对象或抛出异常。
/**
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the {@code supports} method of this interface, which must have
* returned {@code true}.
* @throws Exception in case of errors
* @return ModelAndView object with the name of the view and the required
* model data, or {@code null} if the request has been handled directly
*/
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
(五)ViewResolver
视图仓库,存储viewName视图名称与View对象映射关系。
1. 关键成员方法:
- resolveViewName:匹配viewName,返回对应的View对象。
public interface ViewResolver {
/**
* Resolve the given view by name.
* <p>Note: To allow for ViewResolver chaining, a ViewResolver should
* return {@code null} if a view with the given name is not defined in it.
* However, this is not required: Some ViewResolvers will always attempt
* to build View objects with the given name, unable to return {@code null}
* (rather throwing an exception when View creation failed).
* @param viewName name of the view to resolve
* @param locale Locale in which to resolve the view.
* ViewResolvers that support internationalization should respect this.
* @return the View object, or {@code null} if not found
* (optional, to allow for ViewResolver chaining)
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
*/
View resolveViewName(String viewName, Locale locale) throws Exception;
}
(六)View
具体的视图对象,
1. 关键成员方法:
- render:渲染Model数据,替换View视图中的表达式。
/**
* Render the view given the specified model.
* <p>The first step will be preparing the request: In the JSP case, this would mean
* setting model objects as request attributes. The second step will be the actual
* rendering of the view, for example including the JSP via a RequestDispatcher.
* @param model Map with name Strings as keys and corresponding model
* objects as values (Map can also be {@code null} in case of empty model)
* @param request current HTTP request
* @param response HTTP response we are building
* @throws Exception if rendering failed
*/
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
2. 接口实现类:
(七)HandlerExceptionResolver
异常捕捉器,可以自定义实现自己的全局异常捕捉器。
1. 关键成员方法:
- resolveException:异常处理方法,返回一个ModelAndView对象。
public interface HandlerExceptionResolver {
/**
* Try to resolve the given exception that got thrown during handler execution,
* returning a {@link ModelAndView} that represents a specific error page if appropriate.
* <p>The returned {@code ModelAndView} may be {@linkplain ModelAndView#isEmpty() empty}
* to indicate that the exception has been resolved successfully but that no view
* should be rendered, for instance by setting a status code.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler, or {@code null} if none chosen at the
* time of the exception (for example, if multipart resolution failed)
* @param ex the exception that got thrown during handler execution
* @return a corresponding {@code ModelAndView} to forward to,
* or {@code null} for default processing in the resolution chain
*/
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
(八)HandlerInterceptor
Handler拦截器,一个Handler对象可以配置多个拦截器组成拦截器链,拦截器的按照springIoC注册顺序执行。
1. 关键成员方法:
- preHandle:在Handler处理前执行。
/**
* Intercept the execution of a handler. Called after HandlerMapping determined
* an appropriate handler object, but before HandlerAdapter invokes the handler.
* <p>DispatcherServlet processes a handler in an execution chain, consisting
* of any number of interceptors, with the handler itself at the end.
* With this method, each interceptor can decide to abort the execution chain,
* typically sending a HTTP error or writing a custom response.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler chosen handler to execute, for type and/or instance evaluation
* @return {@code true} if the execution chain should proceed with the
* next interceptor or the handler itself. Else, DispatcherServlet assumes
* that this interceptor has already dealt with the response itself.
* @throws Exception in case of errors
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
- postHandle:在Handler处理后执行,只有preHandle方法返回true才会执行本方法。
/**
* Intercept the execution of a handler. Called after HandlerAdapter actually
* invoked the handler, but before the DispatcherServlet renders the view.
* Can expose additional model objects to the view via the given ModelAndView.
* <p>DispatcherServlet processes a handler in an execution chain, consisting
* of any number of interceptors, with the handler itself at the end.
* With this method, each interceptor can post-process an execution,
* getting applied in inverse order of the execution chain.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler (or {@link HandlerMethod}) that started asynchronous
* execution, for type and/or instance examination
* @param modelAndView the {@code ModelAndView} that the handler returned
* (can also be {@code null})
* @throws Exception in case of errors
*/
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
- afterCompletion:在处理完request后执行。
/**
* Callback after completion of request processing, that is, after rendering
* the view. Will be called on any outcome of handler execution, thus allows
* for proper resource cleanup.
* <p>Note: Will only be called if this interceptor's {@code preHandle}
* method has successfully completed and returned {@code true}!
* <p>As with the {@code postHandle} method, the method will be invoked on each
* interceptor in the chain in reverse order, so the first interceptor will be
* the last to be invoked.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler (or {@link HandlerMethod}) that started asynchronous
* execution, for type and/or instance examination
* @param ex exception thrown on handler execution, if any
* @throws Exception in case of errors
*/
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;