SpringBoot拦截器(Interceptor)与过滤器(Filter)的使用说明
拦截器与过滤器的区别
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用。而过滤器只需依赖servlet api,不需要依赖spring。
何时使用拦截器?何时使用过滤器?
- 如果是非spring项目,那么拦截器则不可使用,只能使用过滤器
- 如果是处理controller前后,则既可以使用拦截器也可以使用过滤器
- 如果是处理dipaterServlet前后,则只可以使用过滤器,像中文乱码问题通常都是使用过滤器实现的
拦截器与过滤器的一个关系图
整个执行流程如下所示:
过滤器的使用
过滤器的触发时机是容器后,servlet之前,所以过滤器的doFilter(ServletRequest request, ServletResponse response, FilterChain chain)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前
//过滤器处理乱码 @Component public class CharacterEncodingFilter implements Filter { //web服务器启动,就会初始化,因为它要随时等待监听 @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化"); } //当访问网页时,就会进行过滤,每访问一次,就会过滤一次 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/html;charset=UTF-8"); System.out.println("解码前"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("解码后"); } //只有当web服务器关闭时,才会销毁 @Override public void destroy() { System.out.println("销毁"); } }
拦截器的使用
在springboot项目中拦截器的定义和使用。springboot是依靠springMVC来完成的。springMVC提供了一个HandlerInterceptor接口,用于表示定义一个拦截器。受限制自定义个类,在这个类实现这个接口。
public class MyIntercepetor implements HandlerInterceptor { /** * return ture; 执行下一个拦截器,放行 * return false; 不执行下一个拦截器,不放行 * 通常也只使用第一行拦截就可以了 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--------处理前-----------"); return true; } //后面两行不使用可以删除掉 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
具体使用:拦截请求
//定义一个拦截器,检测session对象中是否有指定内容 public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //判断是否已登录 Object user = request.getSession().getAttribute("LoginUser"); //若无登录,跳转至登录页面 if (user == null) { request.setAttribute("key", "您没有权限,请先登录"); request.getRequestDispatcher("/login").forward(request, response); return false; } else { return true; } } }
借助WebMvcConfigure接口,可以将用户定义的拦截器进行注册,才可以保证拦截器能够生效和使用。定义一个类,然后让这个类实现WebMvcConfigure接口。
@Configuration public class MyMvcConfig implements WebMvcConfigurer { //拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor()) .addPathPatterns("/**") //拦截所有请求 //排除拦截的内容,登录页面和注册页面的相关请求都排除掉 .excludePathPatterns("/", "/login", "/register", "/regist", "/loginIn", "/css/**", "/js/**", "/img/**"); } }