SpringMVC的拦截器,类似于Servlet中的过滤器Filter,都是用来对处理器进行预处理和后处理。开发者可以通过拦截器自定义一些功能。区别在于过滤器可以过滤所有请求(动态请求,静态请求),但是拦截器只能拦截动态请求(用于控制层)
拦截器跟AOP一样,底层都是动态代理模式
org.springframework.web.servlet.HandlerInterceptor
实现HandlerInterceptor接口
public class ImpInterceptor implements HandlerInterceptor{
/**
* 收到请求后,在执行controller方法之前
* return:true代表放行,fasle代表不需要放行
* arg2:被拦截的控制器对象(当前的controller对象)
*/
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("执行controller方法前执行,下一个责任链对象是:" + arg2);
return true;
}
/**
* controller方法执行完毕,响应之前
* arg2:当前的控制器对象(controller对象)
* arg3:当前执行的controller方法中的ModelAndView对象,可以获得要转发的地址和传递的参数
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {
System.out.println("执行完controller方法后,响应之前执行,当前责任链对象是:" + arg2);
}
/**
* 响应之后
* arg2:当前的控制器对象(controller对象)
* arg3:当前controller方法中发生的异常对象
*/
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {
System.out.println("执行完controller方法后,响应之后执行,当前责任链对象是:" + arg2 + ",当前的异常对象是:" + arg3);
}
}
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
是HandlerInterceptor的实现类,所以,此方式,可以按照也无需求进行选择方法,不需要三个方法都写
继承HandlerInterceptorAdapter
public class ExetInterceptor extends HandlerInterceptorAdapter{
/**
* 收到请求后,在执行controller方法前执行该方法
* return:true代表放行,执行下一个责任链对象的方法(controller方法),fasle代表不需要放行
* arg2:下一个责任链对象(当前的controller对象)
*/
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("执行controller方法前执行,下一个责任链对象是:" + arg2);
return true;
}
/**
* arg2:当前的责任链对象(controller对象)
* arg3:当前执行的controller方法中的ModelAndView对象,可以获得要转发的地址和传递的参数
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {
System.out.println("执行完controller方法后,响应之前执行,当前责任链对象是:" + arg2);
}
/**
* arg2:当前的责任链对象(controller对象)
* arg3:当前controller方法中发生的异常对象
*/
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {
System.out.println("执行完controller方法后,响应之后执行,当前责任链对象是:" + arg2 + ",当前的异常对象是:" + arg3);
}
}
基于Spring核心配置文件,对拦截器进行配置
<!--配置拦截器-->
<mvc:interceptors>
<!--拦截所有的请求-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="top.ygang.interceptor.ExetInterceptor1"/>
</mvc:interceptor>
<!--拦截sys下的所有请求-->
<mvc:interceptor>
<mvc:mapping path="/sys/*"/>
<bean class="top.ygang.interceptor.ExetInterceptor2"/>
</mvc:interceptor>
<!--拦截sys/login单个请求-->
<mvc:interceptor>
<mvc:mapping path="/sys/login"/>
<bean class="top.ygang.interceptor.ExetInterceptor3"/>
</mvc:interceptor>
</mvc:interceptors>
当多个拦截器拦截同一个路径的时候,拦截顺序与配置文件中拦截器声明顺序保持一致
在不使用Spring配置文件的情况下,基于实现WebMvcConfigurer
接口的addInterceptors
方法对拦截器进行配置
@Configuration
@ComponentScan("top.ygang.sm_demo")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ExetInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login")
.order(1);
}
}
当多个拦截器拦截同一个路径的时候,拦截顺序与按照order()
参数从小到大的允许进行排序拦截,order默认值为0
拦截器和过滤器同时使用的执行顺序:过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后
拦截器 | 过滤器 |
---|---|
只能拦截动态请求(控制层的方法) | 能过滤所有的请求 |
由Spring MVC框架提供 | 由servlet api提供 |
原理是动态代理模式,AOP的思想 | 原理是回调的机制 |
运行在Spring容器中 | 运行在Tomcat容器中 |
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object o) throws Exception {
HttpSession session = req.getSession();
Object ob = session.getAttribute("nowLogin");
String uri = req.getRequestURI();
if(uri.endsWith("/login.do")){
return true;
}else{
if(ob == null){
return false;
}else{
return true;
}
}
}