SpringBoot中过滤器、监听器、拦截器

1.使用Servlet3.0的注解过滤器

  • 启动类添加@ServletComponentScan进行扫描

  • 新建一个Filter类,implements Filter,并实现对应的接口

    package com.gen.filter;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.gen.mo.User;
    import com.gen.service.impl.UserServiceImpl;
    import com.gen.util.JsonData;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * 登录过滤器
     * @WebFilter:标记一个类为filter,被Spring进行扫描 urlPatterns:拦截规则,支持正则
     */
    @WebFilter(urlPatterns = "/api/v1/pri/*", filterName = "loginFilter")
    public class LoginFilter implements Filter {
    
        private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            // 获取token
            String token = request.getHeader("token");
            if (!StringUtils.hasLength(token)) {
                token = request.getParameter("token");
            }
            if (StringUtils.hasLength(token)) {
                // 判断token是否合法
                User user = UserServiceImpl.sessionMap.get(token);
                if (user != null) {
                    // token合法,放行
                    filterChain.doFilter(request, response);
                } else {
                    // token失效
                    JsonData jsonData = JsonData.buildError(-2, "token失效");
                    String jsonStr = OBJECT_MAPPER.writeValueAsString(jsonData);
                    renderJson(response, jsonStr);
                }
            } else {
                // 未登录
                JsonData jsonData = JsonData.buildError(-3, "未登录");
                String jsonStr = OBJECT_MAPPER.writeValueAsString(jsonData);
                renderJson(response, jsonStr);
            }
        }
    
        /**
         * 工具类:返回json字符串
         */
        private void renderJson(HttpServletResponse response, String json) {
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json");
    
            try (PrintWriter writer = response.getWriter()) {
                writer.print(json);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    

2.使用Servlet3.0的注解原生Servlet

package com.gen.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "userServlet", urlPatterns = "/api/v1/test/servlet")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.print("this is my servlet");
        writer.flush();
        writer.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3.使用Servlet3.0的注解监听器

  • 什么是监听器

    监听器是一个实现了特定接口的普通Java类,用于监听其他对象的创建和销毁,监听其他对象的方法执行和属性改变

  • 监听器分类

    • ServletContextListener 应用启动监听
    • HttpSessionListener 会话监听
    • ServletRequestListener 请求监听
    package com.gen.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    /**
     * 应用上下文监听
     */
    @WebListener
    public class ApplicationListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("contextInitialized===========");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("contextDestroyed===========");
        }
    }
    

4.拦截器

  • SpringBoot2.x新版本配置拦截器 implements WebMvcConfigurer,代码如下:

    package com.gen.interceptor;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * 拦截器配置类
     */
    @Configuration
    public class CustomWebMvcConfigurer implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/v1/pri/**");
        }
    }
    
  • 自定义拦截器HandlerInterceptor

    • preHandle:调用Controller某个方法之前

    • postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法

    • afterCompletion:不管有没有异常,这个方法都会被调用,用于资源清理

    • 登录拦截器代码示例

      package com.gen.interceptor;
      
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.gen.mo.User;
      import com.gen.service.impl.UserServiceImpl;
      import com.gen.util.JsonData;
      import org.springframework.util.StringUtils;
      import org.springframework.web.servlet.HandlerInterceptor;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.PrintWriter;
      
      /**
       * 登录拦截器
       */
      public class LoginInterceptor implements HandlerInterceptor {
          private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
      
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              // 获取token
              String token = request.getHeader("token");
              if (!StringUtils.hasLength(token)) {
                  token = request.getParameter("token");
              }
              if (StringUtils.hasLength(token)) {
                  // 判断token是否合法
                  User user = UserServiceImpl.sessionMap.get(token);
                  if (user != null) {
                      // token合法,放行
                      return true;
                  } else {
                      // token失效
                      JsonData jsonData = JsonData.buildError(-2, "token失效");
                      String jsonStr = OBJECT_MAPPER.writeValueAsString(jsonData);
                      renderJson(response, jsonStr);
                      return false;
                  }
              } else {
                  // 未登录
                  JsonData jsonData = JsonData.buildError(-3, "未登录");
                  String jsonStr = OBJECT_MAPPER.writeValueAsString(jsonData);
                  renderJson(response, jsonStr);
                  return false;
              }
          }
      
          /**
           * 工具类:返回json字符串
           */
          private void renderJson(HttpServletResponse response, String json) {
              response.setCharacterEncoding("utf-8");
              response.setContentType("application/json");
      
              try (PrintWriter writer = response.getWriter()) {
                  writer.print(json);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
      }
      
  • 和Filter过滤器的区别

    • Filter和Interceptor二者都是AOP编程思想的体现,功能基本都可以实现,拦截器功能更强大,Filter能做的事情它都能做
    • Filter只在Servlet前后起作用,而Interceptor深入到方法前后、异常抛出前后等
    • Filter依赖于Servlet容器即web应用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境
    • 在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次
    • FIlter和Interceptor的执行顺序:过滤前-->拦截前-->action执行-->拦截后-->过滤后
posted @ 2021-03-04 17:23  Gen2021  阅读(183)  评论(0)    收藏  举报