什么是拦截器
拦截器(Interceptor): 用于在某个方法被访问以前进行拦截,而后在方法执行以前或以后加入某些操做,其实就是AOP的一种实现策略。它经过动态拦截Action调用的对象,容许开发者定义在一个action执行的先后执行的代码,也能够在一个action执行前阻止其执行。同时也是提供了一种能够提取action中可重用的部分的方式。java
拦截器做用
拦截用户的请求并进行相应的处理,好比:判断用户是否登录,是否在可购买时间内,记录日志信息等。web
Spring中两种实现方式
实现HandlerInterceptor接口
经过实现HandlerInterceptor接口, 通常经过继承HandlerInterceptorAdapter抽象类实现。spring
DispatcherServlet处理流程:DispatcherServlet处理请求时会构造一个Excecution Chain,即(可能多个)拦截器和真正处理请求的Handler
即Interceptor是链式调用的。
preHandle: 在执行Handler以前进行,即Controller方法调用以前执行,主要进行初始化操做。app
postHandle: 在执行Handler以后进行,即Controller 方法调用以后执行,主要对ModelAndView对象进行操做。框架
afterCompletion: 在整个请求结束以后,即渲染对应的视图以后执行, 主要进行资源清理工做。async
注意事项: 每一个Interceptor的调用会依据它在xml文件中声明顺序依次执行。ide
DispatcherServlet中拦截器相关
实现WebRequestInterceptor接口
------------------------------------------------post
SpringMVC的拦截器Interceptor和过滤器Filter功能很是类似,使用场景也差很少,看起来难以区分。好比二者都能在代码先后插入执行片断,均可以用来实现一些公共组件的功能复用(权限检查、日志记录等),其实它们并不同,首先了解一下Interceptor和Filter。this
一.Interceptor
Interceptor是Spring拦截器,要实现一个拦截器功能能够继承Spring的HandlerInterceptor接口:lua
package com.hpx.xiyou.wuKong.aop; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class sanZangInterceptor implements HandlerInterceptor{ static public final Logger logger = LoggerFactory.getLogger(sanZangInterceptor.class); @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //System.out.println("interceptortest pre"); logger.info("interceptortest pre"); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { //System.out.println("interceptortest post"); logger.info("interceptortest post"); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { //System.out.println("interceptortest after"); logger.info("interceptortest after"); } }
HandlerInterceptor接口有三个须要实现的方法:preHandle(),postHandle()和afterCompletion()。
preHandle方法将在请求处理以前调用,SpringMVC中的Interceptor是链式调用的,每一个Interceptor的调用都根据它的声明顺序依次执行,且最早执行其preHandle方法,因此能够在该方法中进行一些前置初始化操做或是预处理。该方法的返回值是布尔类型,若是返回false,表示请求结束,后续的Interceptor和Controller都不会再执行了,若是返回true就执行下一个拦截器的preHandle方法,一直到最后一个拦截器preHandle方法执行完成后调用当前请求的Controller方法。
postHandle方法是在当前请求进行处理以后,也就是Controller方法调用结束以后执行,可是它会在DispatcherServlet进行视图渲染以前被调用,因此能够在这个方法中能够对Controller处理以后的ModelAndView对象进行操做。postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明的Interceptor的postHandle方法反然后执行。
afterCompletion方法须要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法会在整个请求结束以后,也就是在DispatcherServlet渲染了对应的视图以后执行,这个方法的主要做用是用于资源清理工做。
实现一个interceptor拦截器类后,须要在配置中配置使它生效:实现 WebMvcConfigurerAdapter并重写 addInterceptors,同时在这个方法里设置要过滤的URL。
package com.hpx.xiyou.wuKong.Adapter; import com.hpx.xiyou.wuKong.aop.sanZangInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebConfigurerAdapter extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new sanZangInterceptor()).addPathPatterns("/wukong/**"); } }
以上配置生效后,当访问/wukong/**类型url时,控制台输出以下,其中controller为controller方法中的打印信息:
interceptortest pre
controller
interceptortest post
interceptortest after
二.Filter
Filter是Spring过滤器,要定义一个Filter类有如下步骤:
首先定义一个Filter类,继承javax.servlet.Filter类,重写其init、doFilter、destroy方法。init()方法会在Filter初始化后进行调用,在init()方法里面咱们能够经过FilterConfig访问到初始化参数( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和当前Filter部署的名称( getFilterName() )等信息。destroy()方法将在Filter被销毁以前调用。而doFilter()方法则是真正进行过滤处理的方法,在doFilter()方法内部,咱们能够过滤请求的request和返回的response,同时咱们还能够利用FilterChain把当前的request和response传递给下一个过滤器或Servlet进行处理。
public
class
FilterTest
implements
Filter {
@Autowired
private
PointService pointService;
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
System.out.println(
"init yes"
);
}
@Override
public
void
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws
IOException, ServletException {
System.out.println(
"filter test"
);
filterChain.doFilter(servletRequest, servletResponse);
// 传递给下一个Filter进行处理
return
;
}
@Override
public
void
destroy() {
System.out.println(
"destroy yes"
);
}
}
|
而后在配置中使该Filter生效:
<filter>
<filter-name>filtertest</filter-name>
<filter-
class
>FilterTest</filter-
class
>
</filter>
<filter-mapping>
<filter-name>filtertest</filter-name>
<url-pattern>/point/*</url-pattern>
</filter-mapping>
|
这样,当咱们访问/point/*类型的url,控制台输出以下:
init yes
filter test
controller
三.比较
同时配置过滤器和拦截器而后请求,结果以下:
init yes
filter test
interceptortest pre
controller
interceptortest post
interceptortest after
能够看到filter优先于interceptor被调用。
过滤器和拦截器主要区别以下:
1.两者适用范围不一样。Filter是Servlet规范规定的,只能用于Web程序中,而拦截器既能够用于Web程序,也能够用于Application、Swing程序中。
2.规范不一样。Filter是在Servlet规范定义的,是Servlet容器支持的,而拦截器是在Spring容器内的,是Spring框架支持的。
3.使用的资源不一样。同其余代码块同样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,所以能使用Spring里的任何资源、对象(各类bean),而Filter不行。
4.深度不一样。Filter只在Servlet先后起做用,而拦截器可以深刻到方法先后、异常跑出先后等,拦截器的使用有更大的弹性。