当前位置:网站首页>自定义过滤器和拦截器实现ThreadLocal线程封闭
自定义过滤器和拦截器实现ThreadLocal线程封闭
2022-08-05 10:47:00 【华为云】
线程封闭
线程封闭一般通过以下三个方法:
- 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 */@Slf4jpublic 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 */@Slf4jpublic 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 */@SpringBootApplicationpublic 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(); }}请求访问验证
访问调用接口,控制台输出如下:
边栏推荐
- This notebook of concurrent programming knowledge points strongly recommended by Ali will be a breakthrough for you to get an offer from a big factory
- 基于MindSpore高效完成图像分割,实现Dice!
- GPU-CUDA-图形渲染分析
- gradle尚硅谷笔记
- JS introduction to reverse the recycling business network of learning, simple encryption mobile phone number
- 《分布式云最佳实践》分论坛,8 月 11 日深圳见
- What are the standards for electrical engineering
- LeetCode 216. Combined Sum III (2022.08.04)
- MySQL 中 auto_increment 自动插入主键值
- E-sports, convenience, efficiency, security, key words for OriginOS functions
猜你喜欢

Meteorological data processing example - matlab string cutting matching and R language date matching (data splicing)

Login function and logout function (St. Regis Takeaway)

今天告诉你界面控件DevExpress WinForms为何弃用经典视觉样式

Getting started with Polkadot parachain development, this article is enough

【加密解密】明文加密解密-已实现【已应用】

登录功能和退出功能(瑞吉外卖)

API 网关简述

【MindSpore Easy-Diantong Robot-01】You may have seen many knowledge quiz robots, but this one is a bit different

FPGA:开发环境Vivado的使用

【综合类型第 35 篇】程序员的七夕浪漫时刻
随机推荐
PCB布局必知必会:教你正确地布设运算放大器的电路板
【C语言指针】用指针提升数组的运算效率
The century-old Nordic luxury home appliance brand ASKO smart wine cabinet in the three-temperature area presents the Chinese Valentine’s Day, and tastes the love of the delicacy
2022华数杯数学建模思路分析交流
这份阿里强推的并发编程知识点笔记,将是你拿大厂offer的突破口
Header file search rules when compiling with GCC
L2-042 老板的作息表
static linking and dynamic linking
负载均衡应用场景
【MySQL基础】-【数据处理之增删改】
SQL外连接之交集、并集、差集查询
第五章:redis持久化,包括rdb和aof两种方式[通俗易懂]
Common operations of oracle under linux and daily accumulation of knowledge points (functions, timed tasks)
High-quality DeFi application building guide to help developers enjoy DeFi Summer
Oracle 19.3 restart 环境
gradle尚硅谷笔记
R语言使用yardstick包的pr_curve函数评估多分类(Multiclass)模型的性能、查看模型在多分类每个分类上的ROC曲线(precision(精准率),R代表的是recall(召回率)
2022技能大赛训练题:交换机snmp配置
【综合类型第 35 篇】程序员的七夕浪漫时刻
poj2935 Basic Wall Maze (2016xynu暑期集训检测 -----D题)