跟踪SpringMVC请求过程
source link: https://zofun.github.io/2020/05/20/%E8%B7%9F%E8%B8%AASpringMVC%E8%AF%B7%E6%B1%82%E8%BF%87%E7%A8%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
跟踪SpringMVC请求过程
- 所有的请求都被拦截到
DispatcherServlet
,它也是一个Servlet
,执行doService
- 快照请求中的所有的参数,将框架中的一些对象设置到
request
对象中。 - 调用
doDispatch(request,response)
方法 - 调用
getHandler
方法获取对应的Handler
- 调用
getHandlerAdapter
拿到对应的HandlerAdapter
- 应用拦截器的
PreHandler
,如果拦截器的PreHandeler
返回false,则直接返回 - 调用
HandlerAdapter
对象的handler
得到ModelAndView
对象 - 应用拦截器的
postHandle
方法 - 调用
processDispatchResult
对结果进行处理,其内部调用了拦截器的afterCompletion
方法
如何拿到对应的Handler?
获取Handler
是通过getHandler
方法来获取的。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
这段代码看起来非常的简单,遍历handlerMappings
,从HandlerMapping
从获取HandlerExecutionChain
即我们的handler
.
这个HandlerExecutionChain
中包含了handler
和HandlerInterceptor
数组。也就是我们拿到handler
实际上是一个处理链。
为什么需要HandlerAdapter,它的如何获取到的?
SpringMVC的handler
的实现方式比较的多,比如通过继承Controller
的,基于注解控制器方式,HttpRequestHandler
的方式。因为handler
的实现方式不同,因此调用的方式也就不确定了。因此引入了HandlerAdapter
来进行适配。HandlerAdapter
接口有三个方法:
//判断当前的HandlerAdapter是否支持HandlerMethod
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
获取HandlerAdapter
是通过getHandlerAdapter
方法来获取的。通过对HandlerAdapter
使用原因的分析,我们可以直到所谓获取对应的HandlerAdapter
实际上从HandlerAdapter
列表中找出一个支持当前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");
}
该方法就是简单的遍历HandlerAdapter
列表,从中找出一个支持当前handler
的,并返回。
handler方法的执行过程
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//最终拿到了我们的Controller类
Class<?> clazz = ClassUtils.getUserClass(handler);
//判断是否使用了@SessionAttributes
Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
if (annotatedWithSessionAttributes == null) {
annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
}
if (annotatedWithSessionAttributes) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
// Prepare cached set of session attributes names.
}
else {
// 禁用缓存
checkAndPrepare(request, response, true);
}
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandlerMethod(request, response, handler);
}
}
}
return invokeHandlerMethod(request, response, handler);
}
最终来到了invokerhandlerMethod
方法了:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
//获取处理请求的方法
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
//创建各种组件
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ExtendedModelMap implicitModel = new BindingAwareModelMap();
//调用方法拿到结果
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
//获取ModelAndView
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
//更新view中的属性
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}
最后调用mappedHandler.applyPostHandle(processedRequest, response, mv);
进行后处理。后处理的过程就是调用所有的后置拦截器进行处理。
Filter与Interceptor
Filter的实现方式
实现
Filter
接口@WebFilter(filterName = "filterOne", urlPatterns = {"/*"})
public class FilterOne implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("===========before doFilter");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("===========after doFilter");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
Interceptor的实现方式
实现
HandlerInterceptor
接口public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Controller调用之前的拦截器。。。");
return true;
}
/**
* 该方法controller调用之后,页面渲染之前执行,要preHandler返回ture才会执行该方法
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("controller调用之后,页面渲染之前执行");
}
/**请求完成之后执行的拦截器,要preHandler返回ture才会执行该方法
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求完成之后执行的拦截器");
}
}在
springmvc
的配置文件中进行配置<mvc:interceptors>
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
<bean class="com.host.app.web.interceptor.AllInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- 都可以拦截请求,过滤请求
- 都是应用了过滤器(责任链)设计模式
Filter
过滤器访问较大,配置在web.xml
Interceptor
范围比较小,配置在springmvc
- 在进入
springmvc
处理之前,首先要处理web.xml
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK