当前位置:网站首页>Custom filters and interceptors implement ThreadLocal thread closure
Custom filters and interceptors implement ThreadLocal thread closure
2022-08-10 12:33:00 【Trouvailless】
线程封闭
线程封闭一般通过以下三个方法:
- Ad-hoc线程封闭:程序控制实现,最糟糕,忽略
- 堆栈封闭:局部变量,无并发问题
- 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();
}
}
复制代码请求访问验证
访问调用接口,控制台输出如下:

本文内容到此结束了,
边栏推荐
- So delicious!Since using this interface artifact, my team efficiency has increased by 60%!
- LeetCode 369. Plus One Linked List(链表加1)
- CLIP还能做分割任务?哥廷根大学提出一个使用文本和图像prompt,能同时作三个分割任务的模型CLIPSeg,榨干CLIP能力...
- Color map and depth map to point cloud
- Analysis of the implementation principle of UUID from the perspective of source code
- LeetCode 445. 两数相加 II
- LeetCode 92. Reverse Linked List II
- 【集合】HashSet和ArrayList的查找Contains()时间复杂度
- Threshold-based filtering buffer management scheme in a shared buffer packet switch论文核心部分
- Dining (web stream)
猜你喜欢
随机推荐
配置druid数据源「建议收藏」
你有一份斗破苍穹词库,请查收
StarRocks on AWS 回顾 | Data Everywhere 系列活动深圳站圆满结束
47Haproxy集群
第5章 虚拟存储器
中芯CIM国产化项目暂停?上扬软件:未停摆,改为远程开发!
Redis常用命令
HDU 4135: Co-prime (the principle of inclusion and exclusion)
LeetCode 25. K 个一组翻转链表
LeetCode 445. 两数相加 II
LeetCode 237. 删除链表中的节点
Samsung plans to start producing semiconductor components in Vietnam in 2023
The god-level Alibaba "high concurrency" tutorial - basic + actual combat + source code + interview + architecture is all-inclusive
吃透Chisel语言.36.Chisel实战之以FIFO为例(一)——FIFO Buffer和Bubble FIFO的Chisel实现
Analysis of the name matching process between the LCD driver and the device (Tiny4412)
An enhanced dynamic packet buffer management.论文核心部分
第六届”蓝帽杯“全国大学生网络安全技能大赛半决赛部分WriteUp
If someone asks you about distributed transactions again, throw this to him
Color map and depth map to point cloud
Does face attendance choose face comparison 1:1 or face search 1:N?









