1.Springmvc拦截器
拦截器采用AOP的设计思想, 它跟过滤器类似, 用来拦截处理方法在之前和之后执行一些跟主业务没有关系的一些公共功能:
比如:可以实现:权限控制、日志、异常记录、记录方法执行时间…..
SpringMVC提供了拦截器机制,允许运行目标方法之前进行一些拦截工作或者目标方法运行之后进行一下其他相关的处理。自定义的拦截器必须实现HandlerInterceptor接口。
拦截器一个有3个回调方法,而一般的过滤器Filter才两个:
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器才会执行.
1.1 自定义拦截器
package com.xixi.interceptors;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(this.getClass().getName() + "------->preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(this.getClass().getName() + "------->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(this.getClass().getName() + "------->afterCompletion");
}
}
1.2 spring-mvc.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 包扫描 -->
<context:component-scan base-package="com.xixi"></context:component-scan>
<!-- 默认视图解析器, 配置前缀和后缀 简化我们的开发-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" name="viewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置访问静态资源 -->
<mvc:annotation-driven/>
<mvc:interceptors>
<bean class="com.xixi.interceptors.MyInterceptor"></bean>
</mvc:interceptors>
</beans>
2、定义多个拦截器
再添加另外一个拦截器
package com.xixi.interceptors;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MySecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MySecondInterceptor:"+this.getClass().getName() + "------->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MySecondInterceptor:"+this.getClass().getName() + "------->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MySecondInterceptor:"+this.getClass().getName() + "------->afterCompletion");
}
}
配置拦截器
<mvc:interceptors>
<bean class="com.xixi.interceptors.MyInterceptor"></bean>
<bean class="com.xixi.interceptors.MySecondInterceptor"></bean>
</mvc:interceptors>
大家可以看到对应的效果,谁先执行取决于配置的顺序。
拦截器的preHandle是按照顺序执行的
拦截器的postHandle是按照逆序执行的
拦截器的afterCompletion是按照逆序执行的
如果执行的时候核心的业务代码出问题了,那么已经通过的拦截器的afterCompletion会接着执行。
2、拦截器跟过滤器的区别
1、过滤器是基于函数回调的,而拦截器是基于java反射的
2、过滤器依赖于servlet容器,而拦截器不依赖与Servlet容器,拦截器依赖SpringMVC
3、过滤器几乎对所有的请求都可以起作用,而拦截器只能对SpringMVC请求起作用
4、拦截器可以访问处理方法的上下文,而过滤器不可以
3.拦截用户信息
3.1 新增用户拦截器
package com.xixi.interceptors;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class CheckLoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
HandlerMethod handlerMethod = (HandlerMethod) handler;
System.out.println(handlerMethod.getBean().getClass().getName()+" preHandle:"+handlerMethod.getMethod().getName() + "------->preHandle");
if(session.getAttribute("username")==null){
System.out.println("session中没有用户信息");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
3.2 spring-mvc.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 包扫描 -->
<context:component-scan base-package="com.xixi"></context:component-scan>
<!-- 默认视图解析器, 配置前缀和后缀 简化我们的开发-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" name="viewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置访问静态资源 -->
<mvc:annotation-driven/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="com.xixi.interceptors.CheckLoginInterceptor"></bean>
</mvc:interceptor>
<bean class="com.xixi.interceptors.MyInterceptor"></bean>
<bean class="com.xixi.interceptors.MySecondInterceptor"></bean>
</mvc:interceptors>
</beans>