springmvc拦截器是偶尔会用到的一个功能,本案例来演示一个较简单的springmvc拦截器的使用,并通过源码来分析拦截器的执行顺序的控制。
具体操作步骤为:
1、maven项目引入spring依赖
2、配置web.xml中的DispatcherServlet
3、准备两个拦截器,并在springmvc配置文件中进行配置管理
4、准备业务类,该类转发到一个JSP页面,并在页面做后台打印
5、测试发送请求到业务类,查看执行顺序
6、源码分析
7、总结以及代码附件
————————————————————————————————————————————————————————————
下面开始开发!
1、maven项目引入spring依赖
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
< dependencies > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-context</ artifactId > < version >5.0.2.RELEASE</ version > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-web</ artifactId > < version >5.0.2.RELEASE</ version > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-webmvc</ artifactId > < version >5.0.2.RELEASE</ version > </ dependency > < dependency > < groupId >javax.servlet</ groupId > < artifactId >servlet-api</ artifactId > < version >2.5</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >javax.servlet.jsp</ groupId > < artifactId >jsp-api</ artifactId > < version >2.0</ version > < scope >provided</ scope > </ dependency > </ dependencies > |
2、配置web.xml中的DispatcherServlet
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<!-- 前端控制器(加载classpath:springmvc.xml 服务器启动创建servlet) --> < servlet > < servlet-name >dispatcherServlet</ servlet-name > < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class > <!-- 配置初始化参数,创建完DispatcherServlet对象,加载springmvc.xml配置文件 --> < init-param > < param-name >contextConfigLocation</ param-name > < param-value >classpath:springmvc.xml</ param-value > </ init-param > < load-on-startup >1</ load-on-startup > </ servlet > < servlet-mapping > < servlet-name >dispatcherServlet</ servlet-name > < url-pattern >/</ url-pattern > </ servlet-mapping > |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class MyInterceptor1 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println( "==1-1====前置拦截器1 执行======" ); return true ; //ture表示放行 } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println( "==1-2=====后置拦截器1 执行======" ); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println( "==1-3======最终拦截器1 执行======" ); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class MyInterceptor2 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println( "==2-1====前置拦截器2 执行======" ); return true ; //ture表示放行 } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println( "==2-2=====后置拦截器2 执行======" ); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println( "==2-3======最终拦截器2 执行======" ); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<!--配置拦截器--> < mvc:interceptors > <!--配置拦截器--> < mvc:interceptor > < mvc:mapping path = "/**" /> < bean class = "com.itheima.interceptor.MyInterceptor1" /> </ mvc:interceptor > < mvc:interceptor > < mvc:mapping path = "/**" /> < bean class = "com.itheima.interceptor.MyInterceptor2" /> </ mvc:interceptor > </ mvc:interceptors > |
01
02
03
04
05
06
07
08
09
10
11
|
@Controller public class BizController { @RequestMapping ( "testBiz" ) public String showUserInfo(Integer userId, Model model){ System.out.println( ">>>>>业务代码执行-查询用户ID为:" + userId); User user = new User(userId); user.setName( "宙斯" ); model.addAttribute( "userInfo" ,user); return "user_detail" ; } } |
01
02
03
04
05
06
07
08
09
10
11
12
|
< html > < head > < title >detail</ title > </ head > < body > 用户详情: ${userInfo.id}:${userInfo.name} <%System.out.print(">>>>>jsp页面的输出为:");%> <%System.out.println(((User)request.getAttribute("userInfo")).getName());%> </ body > </ html > |
1
2
3
4
5
6
7
8
|
== 1 - 1 ====前置拦截器 1 执行====== == 2 - 1 ====前置拦截器 2 执行====== >>>>>业务代码执行-查询用户ID为: 1 == 2 - 2 =====后置拦截器 2 执行====== == 1 - 2 =====后置拦截器 1 执行====== >>>>>jsp页面的输出为:宙斯 == 2 - 3 ======最终拦截器 2 执行====== == 1 - 3 ======最终拦截器 1 执行====== |
01
02
03
04
05
06
07
08
09
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { //... try { try { ModelAndView mv = null ; Object dispatchException = null ; try { processedRequest = this .checkMultipart(request); multipartRequestParsed = processedRequest != request; //1.获取执行链 mappedHandler = this .getHandler(processedRequest); if (mappedHandler == null ) { this .noHandlerFound(processedRequest, response); return ; } //2.获取处理器适配器 HandlerAdapter ha = this .getHandlerAdapter(mappedHandler.getHandler()); //... //3.执行前置拦截器 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return ; } //4.执行业务handler mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return ; } this .applyDefaultViewName(processedRequest, mv); //5.执行后置拦截器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException( "Handler dispatch failed" , var21); } //6.处理页面响应,并执行最终拦截器 this .processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { this .triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { this .triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException( "Handler processing failed" , var23)); } } finally { //... } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
//3.执行前置拦截器中的详细代码 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { //获得本次请求对应的所有拦截器 HandlerInterceptor[] interceptors = this .getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { //按照拦截器顺序依次执行每个拦截器的preHandle方法. //并且,interceptorIndex值会一次 + 1 (该值是给后面的最终拦截器使用的) for ( int i = 0 ; i < interceptors.length; this .interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[/color][i][color=black]; //只要每个拦截器不返回false,则继续执行,否则执行最终拦截器 if (!interceptor.preHandle(request, response, this .handler)) { this .triggerAfterCompletion(request, response, (Exception) null ); return false ; } } } //最终返回true return true ; } |
01
02
03
04
05
06
07
08
09
10
11
12
|
//5.执行后置拦截器 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { //获得本次请求对应的所有拦截器 HandlerInterceptor[] interceptors = this .getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { //按倒叙执行每个拦截器的postHandle方法——所以我们看到先执行的拦截器2的postHandle,再执行拦截器1的postHandle for ( int i = interceptors.length - 1 ; i >= 0 ; --i) { HandlerInterceptor interceptor = interceptors[/color][color=black]; interceptor.postHandle(request, response, this .handler, mv); } } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { //... if (mv != null && !mv.wasCleared()) { //处理响应 this .render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else if ( this .logger.isDebugEnabled()) { this .logger.debug( "Null ModelAndView returned to DispatcherServlet with name ‘" + this .getServletName() + "‘: assuming HandlerAdapter completed request handling" ); } if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (mappedHandler != null ) { //6、执行拦截器的最终方法们 mappedHandler.triggerAfterCompletion(request, response, (Exception) null ); } } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
//6、执行拦截器的[align=left][color=#b00000]最终[/color][/align]方法 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception { HandlerInterceptor[] interceptors = this .getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { //倒叙执行每个拦截器(interceptorIndex为前置拦截器动态计算)的afterCompletion方法 for ( int i = this .interceptorIndex; i >= 0 ; --i) { HandlerInterceptor interceptor = interceptors[/color][/i][color=black][i]; try { interceptor.afterCompletion(request, response, this .handler, ex); } catch (Throwable var8) { logger.error( "HandlerInterceptor.afterCompletion threw exception" , var8); } } } } |
原文:https://www.cnblogs.com/zhuxiaopijingjing/p/12289885.html