登录
首页 >  文章 >  java教程

使用Java自定义过滤器和拦截器实现线程封闭的ThreadLocal功能

来源:亿速云

时间:2024-03-27 17:12:28 448浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《使用Java自定义过滤器和拦截器实现线程封闭的ThreadLocal功能》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

线程封闭

线程封闭一般通过以下三个方法:

  • Ad-hoc线程封闭:程序控制实现,最糟糕,忽略

  • 堆栈封闭:局部变量,无并发问题

  • ThreadLocal线程封闭:特别好的封闭方法

方法2是最常用的,变量定义在接口内,本文主要讲解方法三,SpringBoot项目通过自定义过滤器和拦截器实现ThreadLocal线程封闭。实现Filter接口自定义过滤器和继承HandlerInterceptorAdapter自定义拦截器。

ThreadLocal线程封闭实现步骤

封装ThredLocal的方法

/**
 * 

自定义RequestHolder

 *  * @Author zjq  * @Date 2021/12  */ public class RequestHolder {     private final static ThreadLocal requestHolder = new ThreadLocal<>();     public static void set(Long id) {         requestHolder.set(id);     }     public static Long get() {         return requestHolder.get();     }     public static void remove() {         requestHolder.remove();     } }

自定义过滤器

自定义定义拦截器继承Filter接口,实现ThredLocal.add()方法

/**
 * 

自定义过滤器

 *  * @Author zjq  * @Date 2021/12/7  */ @Slf4j public class HttpFilter implements Filter {     /**      * 为Filter初始化 提供支持      *      * @param filterConfig      * @throws ServletException      */     @Override     public void init(FilterConfig filterConfig) throws ServletException {     }     /**      * 拦截到要执行的请求时,doFilter就会执行。这里我们可以写对请求和响应的预处理。      * FilterChain把请求和响应传递给下一个 Filter处理      *      * @param servletRequest      * @param servletResponse      * @param filterChain      * @throws IOException      * @throws ServletException      */     @Override     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {         //把普通servlet强转成httpServlet         HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;         Long threadId = Thread.currentThread().getId();         log.info("do filter,threadId:{} servletPath:{}", threadId, httpServletRequest.getServletPath());         //把当前线程id放入requestHolder         RequestHolder.set(threadId);         //放行         filterChain.doFilter(httpServletRequest, servletResponse);     }     /**      * Filter 实例销毁前的准备工作      */     @Override     public void destroy() {     } }

自定义拦截器

自定义拦截器在线程使用完毕后移除ThredLocal中内容,避免内存溢出

/**
 * 

自定义拦截器

 *  * @Author zjq  * @Date 2021/12/7  */ @Slf4j public class HttpInterceptor extends HandlerInterceptorAdapter {     /**      * 拦截处理程序的执行。在 HandlerMapping 确定合适的处理程序对象之后,在 HandlerAdapter 调用处理程序之前调用。      * @param request      * @param response      * @param handler      * @return      * @throws Exception      */     @Override     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {         log.info("preHandle执行。。。");         return true;     }     /**      * 请求处理完成后(渲染视图后)的回调。将在处理程序执行的任何结果上调用,从而允许进行适当的资源清理。      * @param request      * @param response      * @param handler      * @param ex      * @throws Exception      */     @Override     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {         RequestHolder.remove();         log.info("afterCompletion执行。。。");         return;     } }

Application类启动类中配置自定义过滤器和拦截器

/**
 * 
 * @author zjq
 */
@SpringBootApplication
public class Application extends WebMvcConfigurationSupport {

    public static void main(String[] args) {
        SpringApplication.run(ConcurrencyApplication.class, args);
    }

    /**
     * 自定义过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new HttpFilter());
        //设置自定义过滤器拦截的url
        filterRegistrationBean.addUrlPatterns("/threadLocal/*");
        return filterRegistrationBean;
    }

    /**
     * 定义自定义拦截器原先需要继承WebMvcConfigurerAdapter
     * SpringBoot2.0后WebMvcConfigurerAdapter被定义成过时了,推荐使用继承WebMvcConfigurationSupport
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
    }
}

定义调用接口

/**
 * ThreadLocal测试controller
 * @author zjq
 */
@Controller
@RequestMapping("/threadLocal")
public class ThreadLocalController {

    @RequestMapping("/test")
    @ResponseBody
    public Long test() {
        return RequestHolder.get();
    }
}

请求访问验证

访问调用接口http://localhost:8080/threadLocal/test,控制台输出如下:

Java自定义过滤器和拦截器实现ThreadLocal线程封闭

今天关于《使用Java自定义过滤器和拦截器实现线程封闭的ThreadLocal功能》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于java,threadlocal的内容请关注golang学习网公众号!

声明:本文转载于:亿速云 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>