SpringMVC拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。发送请求时被拦截器拦截,在控制器的前后添加额外功能。
跟AOP的区别:
AOP 在特定方法前后扩充(对 ServiceImpl),请求的拦截.针对点是控制器方法.(对 Controller)
跟Filter的区别:
拦截器只能拦截器 Controller,Filter 可以拦截任何请求.
自定义拦截器的实现步骤(下示案例源码):
1.环境jar包:
2 环境搭建:
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <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>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" default-autowire="byName"> <!-- 注解扫描 --> <context:component-scan base-package="com.tao.service.impl"></context:component-scan> <!-- 加载属性配置文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- SqlSessionFactory --> <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="typeAliasesPackage" value="com.tao.pojo"></property> </bean> <!-- 扫描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tao.mapper"></property> <property name="sqlSessionFactoryBeanName" value="factory"></property> </bean> <!-- 事务管理器 --> <bean id="txManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 声明式事务 --> <tx:advice id="txAdvice" transaction-manager="txManage"> <tx:attributes> <tx:method name="ins*"/> <tx:method name="del*"/> <tx:method name="upd*"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 配置aop --> <aop:config> <aop:pointcut expression="execution(* com.tao.service.impl.*.*(..))" id="mypoint"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/> </aop:config> </beans>
springmvc.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 扫描注解 --> <context:component-scan base-package="com.tao.controller"></context:component-scan> <!-- 注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 静态资源 --> <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> <mvc:resources location="/images/" mapping="/images/**"></mvc:resources> <mvc:resources location="/files/" mapping="/files/**"></mvc:resources> <!-- 视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 拦截器 --> <mvc:interceptors> <!-- 第一种配置方法 所有控制器都拦截 只要进控制器都被此拦截器拦截 <bean class="com.tao.interceptor.DemoInterceptor"></bean> --> <!-- 第二种配置方法 使用指定拦截器 只拦截 特定url的控制器 --> <mvc:interceptor> <mvc:mapping path="/demo"/> <!-- 拦截多个时 <mvc:mapping path="/demo1"/> <mvc:mapping path="/demo1"/> --> <bean class="com.tao.interceptor.DemoInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> </beans>
db.properties:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/ssm jdbc.username = root jdbc.password = root
DemoInterceptor:
package com.tao.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class DemoInterceptor implements HandlerInterceptor{ /** * 在进入控制器之前执行 如果返回值为false,阻止进入控制器 * 主要写控制代码 上面情况可以访问控制器 什么情况不可以访问 */ @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("arg2:"+arg2); System.out.println("preHandle"); return true; } /** * 控制器执行完成,进入到jsp之前执行 * 日志记录 敏感词语过滤 * */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("控制器要跳到的页面:"+arg3.getViewName()); System.out.println("控制器里面model的值:"+arg3.getModel().get("model")); arg3.getModel().put("model", "控制器里想改一下model的值"); System.out.println("postHandle"); } //jsp执行完成之后操作 记录执行过程中出现的异常 可以把异常记录记录到日志中 @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("afterCompletion"); System.out.println(arg3.getMessage()); } }
DemoController:
package com.tao.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class DemoController { @RequestMapping("/demo") public String demo(Model model){ System.out.println("执行demo"); model.addAttribute("model", "model的值"); return "index"; } }
拦截器的执行顺序:
preHandle =====》controller =====》postHandle =====》jsp页面=====》afterCompletion
拦截器主要有三个方法:
preHandle:在进入控制器之前执行 如果返回值为false,阻止进入控制器 主要写控制代码 上面情况可以访问控制器 什么情况不可以访问
应用场景:
权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
postHandle:控制器执行完成,进入到jsp之前执行
应用场景: 日志记录 敏感词语过滤
afterCompletion:jsp执行完成之后操作
应用场景:记录执行过程中出现的异常 可以把异常记录记录到日志中
如何配置拦截器?
拦截器时springmvc的东西,所以我们在springmvc的核心配置文件中进行配置。有两种配置方法:
1:如有控制器的方法都拦截,均走自定义的拦截器类:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 扫描注解 --> <context:component-scan base-package="com.tao.controller"></context:component-scan> <!-- 注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 静态资源 --> <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> <mvc:resources location="/images/" mapping="/images/**"></mvc:resources> <mvc:resources location="/files/" mapping="/files/**"></mvc:resources> <!-- 视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 拦截器 --> <mvc:interceptors> <!-- 第一种配置方法 所有控制器都拦截 只要进控制器都被此拦截器拦截 --> <bean class="com.tao.interceptor.DemoInterceptor"></bean> </mvc:interceptors> </beans>
2:使用指定的自定义拦截器类,拦截指定url的控制器方法:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 扫描注解 --> <context:component-scan base-package="com.tao.controller"></context:component-scan> <!-- 注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 静态资源 --> <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> <mvc:resources location="/images/" mapping="/images/**"></mvc:resources> <mvc:resources location="/files/" mapping="/files/**"></mvc:resources> <!-- 视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 拦截器 --> <mvc:interceptors> <!-- 第二种配置方法 使用指定拦截器 只拦截 特定url的控制器 --> <mvc:interceptor> <mvc:mapping path="/demo"/> <!-- 拦截多个时 <mvc:mapping path="/demo1"/> <mvc:mapping path="/demo1"/> --> <bean class="com.tao.interceptor.DemoInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> </beans>
拦截器栈:多个拦截器同时生效时,组成了拦截器栈
顺序:栈是先进后出. 但执行顺序和在 springmvc.xml 中配置顺序有关
设置先配置拦截器 A 在配置拦截器 B 执行顺序为:
preHandle(A) --> preHandle(B) --> 控制器方法 --> postHandle(B) --> postHanle(A) --> JSP --> afterCompletion(B) --> afterCompletion(A)