zoukankan      html  css  js  c++  java
  • Spring Boot 使用 Filter、Servlet、Listener、Interceptor

    Filter

    1)SpringBoot 启动时默认加载四个 Filter

    characterEncodingFilter、hiddenHttpMethodFilter、httpPutFormContentFilter、requestContextFilter

    2)Filter 优先级

    Ordered.HIGHEST_PRECEDENCE 表示最高的优先级,对应最小的整数值;Ordered.LOWEST_PRECEDENCE 表示最低的优先级,对应最大的整数值。

    低位值意味着更高的优先级。自定义 Filter 避免和默认的 Filter 优先级一样,不然会冲突

    3)在 SpringBoot 中使用 Servlet3.0 配置自定义 Filter

    步骤1:使用 @WebFilter 注解来标记一个类为 Filter,当然这个类还需实现 Filter 接口

    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    @WebFilter(urlPatterns = "/api/*", filterName = "loginFilter")
    public class LoginFilter  implements Filter{
    
         /**
          * 容器加载的时候调用
          */
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("init loginFilter");
          }
    
          /**
           * 请求被拦截的时候进行调用
           */
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("doFilter loginFilter");
              
              HttpServletRequest req = (HttpServletRequest) servletRequest;
              HttpServletResponse resp = (HttpServletResponse) servletResponse;
              String username = req.getParameter("username");
              
              if ("xdclass".equals(username)) {
                  filterChain.doFilter(servletRequest,servletResponse);
              } else {
                  resp.sendRedirect("/index.html");
                  return;
              }
          }
    
          /**
           * 容器被销毁的时候被调用
           */
          @Override
          public void destroy() {
              System.out.println("destroy loginFilter");
          }
    }

    步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Filter。

    如果想要返回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();
            }
    }

    过滤器一般用于非前后分离场景(如:权限控制、用户登录),如果校验不通过,可以使用 resp.sendRedirect("/index.html"); 跳转到错误页面等。

    官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners

    Servlet

    1)在 SpringBoot 中使用 Servlet3.0 的注解自定义原生 Servlet

    步骤1:使用 @WebServlet 注解来标记一个类为 servlet,当然这个类还需实现 HttpServlet 接口

    @WebServlet(name = "userServlet",urlPatterns = "/test/customs")
    public class UserServlet extends HttpServlet{
    
         @Override
         public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             resp.getWriter().print("custom sevlet");
             resp.getWriter().flush();
             resp.getWriter().close();
         }
    
         @Override
         protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             this.doGet(req, resp);
         }
    }

    步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Servlet。

    Listener

    1)在 SpringBoot 中使用 Servlet3.0 的注解自定义原生 Listener

    步骤1:使用 @WebListener 注解来标记一个类为 Listener,当然这个类还需实现对应的 Listener 接口。常用的监听器 servletContextListener、httpSessionListener、servletRequestListener。

    @WebListener
    public class RequestListener implements ServletRequestListener {
      @Override
      public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("======requestDestroyed========");
      }
    
      @Override
      public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("======requestInitialized========");  
      }
    }

    步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Servlet。

    Interceptor

    1)在 SpringBoot 中使用 Interceptor

    步骤1:新建自定义的 Interceptor 类,实现 HandlerInterceptor 接口

    public class LoginIntercepter implements HandlerInterceptor{
    
        /**
         * 进入controller方法之前
         */
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
            System.out.println("LoginIntercepter------->preHandle");
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
    
        /**
         * 调用完controller之后,视图渲染之前
         */
        @Override
        public void postHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            
            System.out.println("LoginIntercepter------->postHandle");
            
            HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        }
    
        /**
         * 整个完成之后,通常用于资源清理
         */
        @Override
        public void afterCompletion(HttpServletRequest request,
                HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            System.out.println("LoginIntercepter------->afterCompletion");
            
            HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        }
    }

    步骤2:Spring Boot 2.0 的实现方式:新建一个配置类(实现 WebMvcConfigurer 接口),使用 @Configuration 注解

    @Configuration
    public class CustomWebMvcConfigurer implements WebMvcConfigurer  {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**");
            registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api2/*/**");
    
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }

    老的实现方式:新建一个配置类(继承 WebMvcConfigurerAdapter 父类),使用 @Configuration 注解

    @Configuration
    public class CustomOldWebMvcConfigurer extends WebMvcConfigurerAdapter {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/");
            
            super.addInterceptors(registry);
        }
    }

    拦截器几个方法的含义: https://www.cnblogs.com/jwen1994/p/11210901.html

    2)拦截器不生效常见问题:

    ① 是否有加@Configuration

    ② 拦截路径是否有问题 ** 和 *

    ③ 拦截器最后路径一定要 “/**”, 如果是目录的话则是 /*/

    3)过滤器(Filter)和拦截器(Interceptor)的区别

    ① Filter 是基于函数回调  doFilter(),而 Interceptor 则是基于 AOP 思想

    ② Filter 在只在 Servlet 前后起作用,而 Interceptor 够深入到方法前后、异常抛出前后等

    ③ 依赖于 Servlet 容器即 Web 应用中,而 Interceptor 不依赖于 Servlet 容器所以可以运行在多种环境。

    ④ 在接口调用的生命周期里,Interceptor 可以被多次调用,而 Filter 只能在容器初始化时调用一次。

    ⑤ Filter 和 Interceptor 的执行顺序:过滤前->拦截前->action执行->拦截后->过滤后

  • 相关阅读:
    剑指offer系列——41.和为S的连续正数序列
    剑指offer系列——40.数组中只出现一次的数字i-ii
    指针初始化
    剑指offer系列——39.平衡二叉树
    剑指offer系列——38.二叉树的深度
    剑指offer系列——37.数字在排序数组中出现的次数/在排序数组中查找元素的第一个和最后一个位置
    剑指offer系列——36.两个链表的第一个公共结点?
    剑指offer系列——35.数组中的逆序对**
    查看机器上GPU情况
    Linux下fork()、vfork()、clone()和exec()的区别
  • 原文地址:https://www.cnblogs.com/jwen1994/p/11222942.html
Copyright © 2011-2022 走看看