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

java并发---线程封闭-基于SpringBoot的ThreadLocal的实现  线程封闭一般通过以下三个方法:    1.Ad-hoc线程封闭:程序控制实现,最糟糕,忽略    2.堆栈封闭:局部变量,无并发问题    3.ThreadLocal线程封闭:特别好的封闭方法方法2是最常用的,变量定义在接口内,本文主要讲解方法三。本例程是基于SpringBoot框架,并使用两个拦截器,分别为Filter和HandlerInterceptorAdapter     第一步,先定义... 阅读详情

线程封闭

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

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

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

ThreadLocal线程封闭实现步骤

封装ThredLocal的方法

/**
 * <p>自定义RequestHolder</p></p>
 *
 * @Author zjq
 * @Date 2021/12
 */
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()方法

/**
 * <p>自定义过滤器</p>
 *
 * @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中内容,避免内存溢出

/**
 * <p>自定义拦截器</p>
 *
 * @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();
    }
}

请求访问验证

访问调用接口,控制台输出如下: 

 

本次内容就到这了,下次见! 

求助:有没有基于pscad的锂电池仿真模型 求助:有没有基于pscad的锂电池仿真模型 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变没有 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写... 阅读详情

相关推荐

SpringBoot 指标监控——Actuator

1、 访问:localhost:8000/actuator 设置健康监控显示具体情况 metrics http://localhost:8000/actuator/metrics/jvm.gc.live.data.size 定制化health信息 //利用构造器,在注册中心中添加cityService.saveCity.count指标 public CityServiceImpl(MeterRegistry meter...

weixin_44302046的博客 4632

SpringBoot配置拦截器和设置静态资源映射

SpringBoot配置拦截器和设置静态资源映射

做点有意思的事情 450

在Windows 11上用VirtualBox搞定WRF-Hydro 5.2.0:一个水文模型小白的Ubuntu 22.04虚拟机避坑实录

本文详细记录了在Windows 11上使用VirtualBox和Ubuntu 22.04虚拟机成功编译安装WRF-Hydro 5.2.0水文模型的全过程。从虚拟环境配置、依赖库安装到环境变量设置,作者分享了针对Linux新手的实用避坑技巧和关键命令,帮助科研人员高效完成水文模型的环境搭建。

weixin_30733003的博客 354

获取用户登录信息和request对象的工具类RequestHolder

package com.kang.common; import com.kang.model.SysUser; import javax.servlet.http.HttpServletRequest; /** * 处理高并发的对象 * 1. 每个线程是独立的 * 2. 登陆的时候会把每个用户的信息和请求的信息放入线程里面 * 3. 而在以后取用户信息可以直接取这里取 */ publ...

desperado0726的博客 2524

使用单片机和电流互感器对非正弦周期电流有效值测定

使用单片机和电流互感器,利用一种高速采样的方法来进行有效值测定

月光绿叶滴水音乐 3946

狗都能看懂的Proximal Policy Optimization(PPO)PPO算法详解

李宏毅老师的PPO算法讲解笔记

个人学习笔记 2万+

RequestHolder工具类

package com.inspire.ssm.common; import com.inspire.ssm.model.SysUser; import javax.servlet.http.HttpServletRequest; public class RequestHolder { /** * 处理高并发的对象 * 1. 每个线程是...

weixin_34072458的博客 1031

面经-2023-联发科MTK-数字芯片设计

面经-2023-联发科MTK-数字芯片设计

w0shishabi的博客 2945

x64内核HOOK技术之拦截进程.拦截线程.拦截模块

            x64内核HOOK技术之拦截进程.拦截线程.拦截模块 一丶为什么讲解HOOK技术. 在32系统下,例如我们要HOOK SSDT表,那么直接讲CR0的内存保护属性去掉.直接讲表的地址修改即可. 但是在64位系统下,不可以这样操作了. 第一是因为 SSDT表加密了. 第二是 SSDT表你就算解密了.那么你的API的地址也会很远. SSDT表放不下4G以...

weixin_30399155的博客 866

《QT+PCL》点云配准进阶——GROR配准

GROR点云配准

阁楼 1318

17、高通8155座舱平台--QNX开发基础

我个人习惯,拿到一个新板子,第一件事就是打开IDE,建一个空的QNX项目,然后跑一遍Hello World。比如,当触摸屏被按下时,驱动发一个脉冲给UI进程,告诉它“嘿,有人摸屏幕了”。我在8155上调试时,就遇到过因为脉冲优先级太低,导致触摸响应延迟的问题。IDE自带的编译器是qcc,它其实是gcc的封装。QNX的IPC机制,可以说是它最牛的地方。嗯,这套流程走下来,你对QNX开发的基本功就差不多了。QNX默认的消息缓冲区大小是64KB,如果你要传大块数据,比如音频流,那就得用共享内存了。

woailuojp的博客 54

Java创建拦截器+通过ThreadLocal获取拦截器中产生的数据

拦截器的使用

MR_T3的博客 504

YOLO26魔改:ICIP2026 SDTA|单深度转置注意力注入C2PSA,长程依赖与局部细节双增强,mAP提升显著

多尺度适配:SDTA的深度卷积与C2PSA的空间注意力结合,增强对多尺度目标的结构感知,改善遮挡与密集场景下的检测鲁棒性。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 293

SpringBoot2.x结合ThreadLocal自定义简单的RequestHolder实现线程封闭

开篇:ThreadLocal就不多说了,想必这个大家都很熟悉了,实现单线程共享和安全的有效途径,下面是我在GitHub上的一篇浅析ThreadLocal! ThreadLocal的简单剖析 目标:通过SpringBoot2.x的过滤器,拦截器和ThreadLocal实现简单的线程封闭。并且促进理解RequestContextHolder(持有上下文的Request容器,也是一个很好用的工具类...

qq_42605968的博客 3308

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

并发编程-11线程安全策略之线程封闭

文章目录脑图概述线程封闭的三种方式示例堆栈封闭ThreadLocalStep1. ThreadLocal操作类Step2. 自定义过滤器Step3. 注册拦截器,配置拦截规则Step4. Controller层调用Step5. 测试代码 脑图 概述 在上篇博文并发编程-10线程安全策略之不可变对象 ,我们通过介绍使用线程安全的不可变对象可以保证线程安全。 除了上述方法,还有一种办法就是:线程封...

小工匠 2万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

[6]线程封闭技术

避免并发方法1:不可变对象 通过将不可以被修改的对象设计成不可变对象,实现在多线程下线程安全,躲避开并发问题 避免并发方法2:线程封闭 将一个对象封装到一个线程里,只有一个线程可以看到访问, 从而安全,以下是实现线程封闭的四种方法: 通过ThreadLocal + filter 实现一个类在接口处理前已经取好,随用随取,而不是把一个用户信息从request中取出再从controller一直传下去...

kk的博客 456

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

线程封闭示例 将Request中的信息封闭在ThreadLocal中

ThreadLocal工具类 线程通过该工具类,将线程私有的数据存入ThreadLocal中; public class RequestHolder { private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>(); /*...

乌鲁木齐001号程序员 541

java并发和高并发之线程封闭

一、线程封闭: 1、概述;线程安全策略,除了不可变对象,还有一个简单的方法就是线程封闭。线程封闭其实就是把对象封装到一个线程里,只有这一个线程能看到这个对象,那么这个对象本身就算不是线程安全的,也不会出现任何线程安全问题,因为它只能出现在一个线程里。 2、实现线程封闭的几个方法: 》Ad-hoc 线程封闭:完全靠程序控制实现,非常脆弱,最糟糕,忽略; 》堆栈封闭:局部变量,无并发问题。被使...

智欣约的博客 374

并发编程-线程安全策略之线程封闭

脑图 概述 我们通过介绍使用线程安全的不可变对象可以保证线程安全。 除了上述方法,还有一种办法就是:线程封闭。 线程封闭的三种方式 Ad-hoc 线程封闭,完全由程序控制实现,不可控,不要使用 堆栈封闭方法中定义局部变量。不存在并发问题 堆栈封闭其实就是方法中定义局部变量。不存在并发问题。 多个线程访问一个方法的时候,方法中的局部变量都会被拷贝一份到线程的栈中(Java内存模型),所以局部变量是不会被多个线程所共享的。 局部变量的固有属性之一就是封闭在线程中。它们位于...

花&败 348

java高并发6.2 线程封闭

不可变对象相当于躲避开了并发的问题, 避免并发除了不可变对象 , 还有线程封闭的方法 1、什么是线程封闭? 它其实就是把对象封装到一个线程里,只有一个线程能看到这个对象,那么这个对象就算不是线程安全的,也不会出现任何线程安全方面的问题。 线程封闭技术有一个常见的应用: 数据库连接对应jdbc的Connection对象,Connection对象在实现的时候并没有对线程安全做太多...

Linias的博客 461

java高并发(九)线程封闭

上一节介绍了不可变对象,通过在某些情况下将不会修改的类对象设计成不可变对象,来让对象在多个线程间保证对象是线程安全的。归根到底,相当于躲避开了并发问题,实现好的并发是一件很困难的事情,所以很多时候都想躲避并发,避免并发除了设计成不可变对象其实还有一个简单的方法就是线程封闭。 什么是线程封闭...

chikoucha6215的博客 154

ThreadLocal+Filter+SpringBoot

ThreadLocal+Filter+SpringBoot 保存用户等信息 package com.icmc.icao.util; import com.icmc.icao.entity.sys.IcaoUser; import javax.servlet.http.HttpServletRequest; /** * @author * @title: RequestHolder * ...

STRANGE-P 的博客 1023

自定义拦截器与一次请求的执行顺序

一、自定义拦截器 1. 继承HandlerInterceptorAdapter类 public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { public HandlerInterceptorAdapter() { } public boolean preHandle(HttpServletRequest request, HttpServletResponse r

weixin_43361158的博客 822

java闭合数据,java高并发(九)线程封闭

上一节介绍了不可变对象,通过在某些情况下将不会修改的类对象设计成不可变对象,来让对象在多个线程间保证对象是线程安全的。归根到底,相当于躲避开了并发问题,实现好的并发是一件很困难的事情,所以很多时候都想躲避并发,避免并发除了设计成不可变对象其实还有一个简单的方法就是线程封闭。什么是线程封闭?其实就是把对象封装到一个线程里,只有这一个线程能看到这个对象。那么这个对象就算不是线程安全的,也不会出现线程安...

weixin_30199989的博客 141
上一篇: 深入剖析Spring Boot 的SPI机制
下一篇: Spring5源码5-Bean生命周期后置处理器
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值