整体流程
- 所有的请求都被拦截到
DispatcherServlet,它也是一个Servlet,执行doService - 快照请求中的所有的参数,将框架中的一些对象设置到
request对象中。 - 调用
doDispatch(request,response)方法 - 调用
getHandler方法获取对应的Handler - 调用
getHandlerAdapter拿到对应的HandlerAdapter - 应用拦截器的
PreHandler,如果拦截器的PreHandeler返回false,则直接返回 - 调用
HandlerAdapter对象的handler得到ModelAndView对象 - 应用拦截器的
postHandle方法 - 调用
processDispatchResult对结果进行处理,其内部调用了拦截器的afterCompletion方法
源码细节
如何拿到对应的Handler?
获取Handler是通过getHandler方法来获取的。
1 | protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
这段代码看起来非常的简单,遍历handlerMappings,从HandlerMapping从获取HandlerExecutionChain即我们的handler.
这个HandlerExecutionChain中包含了handler和HandlerInterceptor数组。也就是我们拿到handler实际上是一个处理链。
为什么需要HandlerAdapter,它的如何获取到的?
SpringMVC的handler的实现方式比较的多,比如通过继承Controller的,基于注解控制器方式,HttpRequestHandler的方式。因为handler的实现方式不同,因此调用的方式也就不确定了。因此引入了HandlerAdapter来进行适配。HandlerAdapter接口有三个方法:
1 | //判断当前的HandlerAdapter是否支持HandlerMethod |
获取HandlerAdapter是通过getHandlerAdapter方法来获取的。通过对HandlerAdapter使用原因的分析,我们可以直到所谓获取对应的HandlerAdapter实际上从HandlerAdapter列表中找出一个支持当前handler的。
1 | protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { |
该方法就是简单的遍历HandlerAdapter列表,从中找出一个支持当前handler的,并返回。
handler方法的执行过程
1 | public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) |
最终来到了invokerhandlerMethod方法了:
1 | protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) |
最后调用mappedHandler.applyPostHandle(processedRequest, response, mv);进行后处理。后处理的过程就是调用所有的后置拦截器进行处理。
Filter与Interceptor
Filter的实现方式
实现
Filter接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19@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接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public 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的配置文件中进行配置1
2
3
4
5
6
7
8
9<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.xmlInterceptor范围比较小,配置在springmvc- 在进入
springmvc处理之前,首先要处理web.xml