• springboot设置过滤器、监听器、拦截器


    其实这篇文章算不上是springboot的东西,我们在spring普通项目中也是可以直接使用的

    设置过滤器:

    以前在普通项目中我们要在web.xml中进行filter的配置,但是只从servlet 3.0后,我们就可以在直接在项目中进行filter的设置,因为她提供了一个注解@WebFilter(在javax.servlet.annotation包下),使用这个注解我们就可以进行filter的设置了,同时也解决了我们使用springboot项目没有web.xml的尴尬,使用方法如下所示

    @WebFilter(urlPatterns="/*",filterName="corsFilter", asyncSupported = true)
    public class CorsFilter implements Filter{
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse)servletResponse; 
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            chain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    
    }

    其实在WebFilter注解中有一些属性我们需要进行设置, 比如value、urlPatterns,这两个属性其实都是一样的作用,都是为了设置拦截路径,asyncSupported这个属性是设置配置的filter是否支持异步响应,默认是不支持的,如果我们的项目需要进行请求的异步响应,请求经过了filter,那么这个filter的asyncSupported属性必须设置为true不然请求的时候会报异常。

    设置拦截器:

    编写一个配置类,继承org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter或者org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport并重写addInterceptors(InterceptorRegistry registry)方法,其实父类的addInterceptors(InterceptorRegistry registry)方法就是个空方法。使用方法如下:

    @Configuration
    public class MvcConfig extends WebMvcConfigurationSupport {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            InterceptorRegistration registration = registry.addInterceptor(new HandlerInterceptor() {
                @Override
                public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                    return true;
                }
    
                @Override
                public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
                }
    
                @Override
                public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
                }
            });
            // 配置拦截路径
            registration.addPathPatterns("/**");
            // 配置不进行拦截的路径
            registration.excludePathPatterns("/static/**");
        }
    }

    配置监听器:

    一般我们常用的就是request级别的javax.servlet.ServletRequestListener和session级别的javax.servlet.http.HttpSessionListener,下面以ServletRequestListener为例,编写一个类实现ServletRequestListener接口并实现requestInitialized(ServletRequestEvent event)方法和requestDestroyed(ServletRequestEvent event)方法,在实现类上加上@WebListener(javax.servlet.annotation包下),如下所示

    @WebListener
    public class RequestListener implements ServletRequestListener {
    
        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
            System.out.println("请求结束");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent sre) {
            System.out.println("请求开始");
        }
    }

    这样每一个请求都会被监听到,在请求处理前equestInitialized(ServletRequestEvent event)方法,在请求结束后调用requestDestroyed(ServletRequestEvent event)方法,其实在spring中有一个非常好的例子,就是org.springframework.web.context.request.RequestContextListener类

    public class RequestContextListener implements ServletRequestListener {
    
        private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
                RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";
    
    
        @Override
        public void requestInitialized(ServletRequestEvent requestEvent) {
            if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
                throw new IllegalArgumentException(
                        "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
            }
            HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
            ServletRequestAttributes attributes = new ServletRequestAttributes(request);
            request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
            LocaleContextHolder.setLocale(request.getLocale());
            RequestContextHolder.setRequestAttributes(attributes);
        }
    
        @Override
        public void requestDestroyed(ServletRequestEvent requestEvent) {
            ServletRequestAttributes attributes = null;
            Object reqAttr = requestEvent.getServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
            if (reqAttr instanceof ServletRequestAttributes) {
                attributes = (ServletRequestAttributes) reqAttr;
            }
            RequestAttributes threadAttributes = RequestContextHolder.getRequestAttributes();
            if (threadAttributes != null) {
                // We're assumably within the original request thread...
                LocaleContextHolder.resetLocaleContext();
                RequestContextHolder.resetRequestAttributes();
                if (attributes == null && threadAttributes instanceof ServletRequestAttributes) {
                    attributes = (ServletRequestAttributes) threadAttributes;
                }
            }
            if (attributes != null) {
                attributes.requestCompleted();
            }
        }
    
    }

    在这个类中,spring将每一个请求开始前都将请求进行了一次封装并设置了一个threadLocal,这样我们在请求处理的任何地方都可以通过这个threadLocal获取到请求对象,好处当然是有的啦,比如我们在service层需要用到request的时候,可以不需要调用者传request对象给我们,我们可以通过一个工具类就可以获取,岂不美哉。

    扩充:在springboot的启动类中我们可以添加一些ApplicationListener监听器,例如:

    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(DemoApplication.class);
            application.addListeners(new ApplicationListener<ApplicationEvent>() {
                @Override
                public void onApplicationEvent(ApplicationEvent event) {
                    System.err.println(event.toString());
                }
            });
            application.run(args);
        }
    }
    ApplicationEvent是一个抽象类,她的子类有很多比如ServletRequestHandledEvent(发生请求事件的时候触发)、ApplicationStartedEvent(应用开始前触发,做一些启动准备工作)、ContextRefreshedEvent(容器初始化结束后触发),其他还有很多,这里不再多说,但是这些ApplicationListener只能在springboot项目以main方法启动的时候才会生效,也就是说项目要打jar包时才适用,如果打war包,放在Tomcat等web容器中是没有效果的。
  • 相关阅读:
    LeetCode数学系列(1)——第172解题思路
    python的匿名函数lambda解释及用法
    LeetCode位操作系列(2)——位运算的常用技巧:lowbit运算,包含lowbit公式、讲解、231题运用
    【零散】jupyter notebook快捷键 mac版
    【油猴插件】分享推荐
    【Mac】 Chromedriver 存放路径
    【全网首发】微信公众号常见垃圾文章广告软文关键词整理
    Mac Chrome浏览器取消自动升级(最新版)
    requests与selenium之前cookies传递
    [转]scrapy中的request.meta
  • 原文地址:https://www.cnblogs.com/zzw-blog/p/10656181.html
Copyright © 2020-2023  润新知