十、springMVC之自定义拦截器
一、概述
springMVC也可以使用拦截器对请求拦截处理,用户可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HanderInterceptor接口;
HanderInterceptor接口方法有:preHandle、postHandle、afterCompletion;
preHandle:
这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false;
postHandle:
这个方法在业务处理器处理完请求后,但是DispatcherServlet向客户端返回响应前被调用;在该方法中对用户请求request进行处理;
afterCompletion:
这个方法在DispatcherServlet完全处理完请求后被调用;可以在该方法中进行一些资源清理的操作;
二、拦截器配置和实例验证
目录结构:

1.配置:
web.xml配置:只配置了DispatcherServlet
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 5 id="WebApp_ID" version="3.1"> 6 <servlet> 7 <servlet-name>springDispatcherServletservlet-name> 8 <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> 9 10 12 <init-param> 13 <param-name>contextConfigLocationparam-name> 14 <param-value>classpath:spring.xmlparam-value> 15 init-param> 16 17 <load-on-startup>1load-on-startup> 18 servlet> 19 20 21 <servlet-mapping> 22 <servlet-name>springDispatcherServletservlet-name> 23 <url-pattern>/url-pattern> 24 servlet-mapping> 25 web-app>
spring.xml配置:基础配置+拦截器配置;
基础配置包括:包扫描的配置、视图解析器配置、<mvc:annotation-driven>mvc:annotation-driven>;
拦截器配置:
<mvc:interceptors> <bean class="interceptors.FirstInterceptor">bean> mvc:interceptors>
完整文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:mvc="http://www.springframework.org/schema/mvc" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <context:component-scan base-package="handler">context:component-scan> 11 12 <bean 13 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 14 <property name="prefix" value="/WEB-INF/views/">property> 15 <property name="suffix" value=".jsp">property> 16 bean> 17 18 <mvc:annotation-driven>mvc:annotation-driven> 19 20 <mvc:interceptors> 21 22 <bean class="interceptors.FirstInterceptor">bean> 23 mvc:interceptors> 24 25 beans>
2.拦截器FirstInterceptor.java:
必须实现HanderInterceptor接口
1 package interceptors; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.springframework.web.servlet.HandlerInterceptor; 7 import org.springframework.web.servlet.ModelAndView; 8 9 /** 10 * 拦截器
11 * 多个拦截器的情况:preHandle 顺序执行;postHandle倒叙执行;afterCompletion倒叙执行 12 * 13 * @author lixiuming 14 * 15 */ 16 public class FirstInterceptor implements HandlerInterceptor { 17 /** 18 * 该方法在目标方法之前被调用
19 * 若返回值为true,则继续调用后续的拦截器和目标方法
20 * 若返回值为false,则不会再执行后续的拦截器和目标方法;
21 * 使用场景可以考虑做权限,日志、事务等 22 */ 23 @Override 24 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 25 throws Exception { 26 System.out.println("preHandle"); 27 // TODO Auto-generated method stub 28 return HandlerInterceptor.super.preHandle(request, response, handler); 29 } 30 31 /** 32 * 调用目标方法之后,但渲染视图之前被调用;使用场景 可以对请求域中的属性或者视图做出修改 33 */ 34 @Override 35 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 36 ModelAndView modelAndView) throws Exception { 37 System.out.println("postHandle"); 38 // TODO Auto-generated method stub 39 HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); 40 } 41 42 /** 43 * 渲染视图之后被调用; 使用场景:释放资源 44 */ 45 @Override 46 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 47 throws Exception { 48 System.out.println("afterCompletion"); 49 // TODO Auto-generated method stub 50 HandlerInterceptor.super.afterCompletion(request, response, handler, ex); 51 } 52 53 }
3.EmployeeController.java
1 package handler; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 6 @RequestMapping("/emp") 7 @Controller 8 public class EmployeeController { 9 10 @RequestMapping("/testInteceptors") 11 public String testFileUpload() { 12 System.out.println("testInteceptors"); 13 return "success"; 14 } 15 }
4.success.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>Insert title heretitle> 8 head> 9 <body> 10 success 11 body> 12 html>
5.运行结果&流程:
访问http://localhost:8080/DataOperate/emp/testInteceptors时,页面跳转到success页面;且控制台台打印了:
preHandle
testInteceptors
postHandle
afterCompletion
运行流程:

三、多个拦截器:
spring.xml配置特定路径的拦截器:
这里的路径是访问路径是/emp/testIndex,也就是说,访问/emp/testIndex时,调用第二个拦截器;
1 <mvc:interceptors> 2 3 <bean class="interceptors.FirstInterceptor">bean> 4 5 <mvc:interceptor> 6 <mvc:mapping path="/emp/testIndex"/> 7 <bean class="interceptors.SecondInterceptor">bean> 8 mvc:interceptor> 9 mvc:interceptors>
拦截器:SecondInterceptor.java:
1 package interceptors; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.springframework.web.servlet.HandlerInterceptor; 7 import org.springframework.web.servlet.ModelAndView; 8 9 /** 10 * 拦截器 11 * 12 * @author lixiuming 13 * 14 */ 15 public class SecondInterceptor implements HandlerInterceptor { 16 /** 17 * 该方法在目标方法之前被调用
18 * 若返回值为true,则继续调用后续的拦截器和目标方法
19 * 若返回值为false,则不会再执行后续的拦截器和目标方法;
20 * 使用场景可以考虑做权限,日志、事务等 21 */ 22 @Override 23 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 24 throws Exception { 25 System.out.println("SecondInterceptor preHandle"); 26 // TODO Auto-generated method stub 27 return HandlerInterceptor.super.preHandle(request, response, handler); 28 } 29 30 /** 31 * 调用目标方法之后,但渲染视图之前被调用;使用场景 可以对请求域中的属性或者视图做出修改 32 */ 33 @Override 34 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 35 ModelAndView modelAndView) throws Exception { 36 System.out.println(" SecondInterceptor postHandle"); 37 // TODO Auto-generated method stub 38 HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); 39 } 40 41 /** 42 * 渲染视图之后被调用; 使用场景:释放资源 43 */ 44 @Override 45 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 46 throws Exception { 47 System.out.println(" SecondInterceptor afterCompletion"); 48 // TODO Auto-generated method stub 49 HandlerInterceptor.super.afterCompletion(request, response, handler, ex); 50 } 51 52 }
EmployeeController.java添加方法:
1 package handler; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 6 @RequestMapping("/emp") 7 @Controller 8 public class EmployeeController { 9 10 @RequestMapping("/testInteceptors") 11 public String testFileUpload() { 12 System.out.println("testInteceptors"); 13 return "success"; 14 } 15 16 @RequestMapping("/testIndex") 17 public String testIndex() { 18 System.out.println("testInteceptors"); 19 return "forward:/index.jsp"; 20 } 21 }
index.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@page import="java.util.*"%> 4 DOCTYPE html> 5 <html> 6 <head> 7 <meta charset="UTF-8"> 8 <title>Insert title heretitle> 9 head> 10 <body> 11 <h3>welcom to lean interceptor !h3> 12 13 14 body> 15 html>
运行结果:
访问:http://localhost:8080/DataOperate/emp/testInteceptors时,页面跳转到success页面;且控制台台打印了:
preHandle
testInteceptors
postHandle
afterCompletion
访问:http://localhost:8080/DataOperate/emp/testIndex时,页面跳转到index.jsp页面;且控制台台打印了:
preHandle
SecondInterceptor preHandle
testInteceptors
SecondInterceptor postHandle
postHandle
SecondInterceptor afterCompletion
afterCompletion
多个拦截器运行流程:多个拦截器的情况:preHandle 顺序执行;postHandle倒叙执行;afterCompletion倒叙执行
