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

2022-11-13 14:11:43 过滤器 线程 自定义

线程封闭

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

  • Ad-hoc线程封闭:程序控制实现,最糟糕,忽略
  • 堆栈封闭:局部变量,无并发问题
  • ThreadLocal线程封闭:特别好的封闭方法

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

ThreadLocal线程封闭实现步骤

封装ThredLocal的方法


public class RequestHolder {

    private final static ThreadLocal<Long> 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()方法


@Slf4j
public class HttpFilter implements Filter {

    
    @Override
    public void init(FilterConfig filterConfig) 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);
    }

    
    @Override
    public void destroy() {

    }
}

自定义拦截器

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


@Slf4j
public class HttpInterceptor extends HandlerInterceptorAdapter {

    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandle执行。。。");
        return true;
    }

    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RequestHolder.remove();
        log.info("afterCompletion执行。。。");
        return;
    }
}

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


@springBootApplication
public class Application extends WEBmvcConfigurationSupport {

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

    
    @Bean
    public FilterReGIStrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new HttpFilter());
        //设置自定义过滤器拦截的url
        filterRegistrationBean.addUrlPatterns("/threadLocal
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("
@Controller
@RequestMapping("/threadLocal")
public class ThreadLocalController {

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

请求访问验证

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

到此这篇关于Java自定义过滤器和拦截器实现ThreadLocal线程封闭的文章就介绍到这了,更多相关Java ThreadLocal线程封闭内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章