Java自定義過(guò)濾器和攔截器實(shí)現(xiàn)ThreadLocal線程封閉
線程封閉
線程封閉一般通過(guò)以下三個(gè)方法:
- Ad-hoc線程封閉:程序控制實(shí)現(xiàn),最糟糕,忽略
- 堆棧封閉:局部變量,無(wú)并發(fā)問(wèn)題
- ThreadLocal線程封閉:特別好的封閉方法
方法2是最常用的,變量定義在接口內(nèi),本文主要講解方法三,SpringBoot項(xiàng)目通過(guò)自定義過(guò)濾器和攔截器實(shí)現(xiàn)ThreadLocal線程封閉。實(shí)現(xiàn)Filter接口自定義過(guò)濾器和繼承HandlerInterceptorAdapter自定義攔截器。
ThreadLocal線程封閉實(shí)現(xiàn)步驟
封裝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(); } }
自定義過(guò)濾器
自定義定義攔截器繼承Filter接口,實(shí)現(xiàn)ThredLocal.add()方法
/** * <p>自定義過(guò)濾器</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 { } /** * 攔截到要執(zhí)行的請(qǐng)求時(shí),doFilter就會(huì)執(zhí)行。這里我們可以寫對(duì)請(qǐng)求和響應(yīng)的預(yù)處理。 * FilterChain把請(qǐng)求和響應(yīng)傳遞給下一個(gè) 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強(qiáng)轉(zhuǎn)成httpServlet HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; Long threadId = Thread.currentThread().getId(); log.info("do filter,threadId:{} servletPath:{}", threadId, httpServletRequest.getServletPath()); //把當(dāng)前線程id放入requestHolder RequestHolder.set(threadId); //放行 filterChain.doFilter(httpServletRequest, servletResponse); } /** * Filter 實(shí)例銷毀前的準(zhǔn)備工作 */ @Override public void destroy() { } }
自定義攔截器
自定義攔截器在線程使用完畢后移除ThredLocal中內(nèi)容,避免內(nèi)存溢出
/** * <p>自定義攔截器</p> * * @Author zjq * @Date 2021/12/7 */ @Slf4j public class HttpInterceptor extends HandlerInterceptorAdapter { /** * 攔截處理程序的執(zhí)行。在 HandlerMapping 確定合適的處理程序?qū)ο笾?,?HandlerAdapter 調(diào)用處理程序之前調(diào)用。 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("preHandle執(zhí)行。。。"); return true; } /** * 請(qǐng)求處理完成后(渲染視圖后)的回調(diào)。將在處理程序執(zhí)行的任何結(jié)果上調(diào)用,從而允許進(jìn)行適當(dāng)?shù)馁Y源清理。 * @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執(zhí)行。。。"); return; } }
Application類啟動(dòng)類中配置自定義過(guò)濾器和攔截器
/** * * @author zjq */ @SpringBootApplication public class Application extends WebMvcConfigurationSupport { public static void main(String[] args) { SpringApplication.run(ConcurrencyApplication.class, args); } /** * 自定義過(guò)濾器 * @return */ @Bean public FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new HttpFilter()); //設(shè)置自定義過(guò)濾器攔截的url filterRegistrationBean.addUrlPatterns("/threadLocal/*"); return filterRegistrationBean; } /** * 定義自定義攔截器原先需要繼承WebMvcConfigurerAdapter * SpringBoot2.0后WebMvcConfigurerAdapter被定義成過(guò)時(shí)了,推薦使用繼承WebMvcConfigurationSupport * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**"); } }
定義調(diào)用接口
/** * ThreadLocal測(cè)試controller * @author zjq */ @Controller @RequestMapping("/threadLocal") public class ThreadLocalController { @RequestMapping("/test") @ResponseBody public Long test() { return RequestHolder.get(); } }
請(qǐng)求訪問(wèn)驗(yàn)證
訪問(wèn)調(diào)用接口http://localhost:8080/threadLocal/test,控制臺(tái)輸出如下:
到此這篇關(guān)于Java自定義過(guò)濾器和攔截器實(shí)現(xiàn)ThreadLocal線程封閉的文章就介紹到這了,更多相關(guān)Java ThreadLocal線程封閉內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java比較兩個(gè)json文件的差異及說(shuō)明
這篇文章主要介紹了java比較兩個(gè)json文件的差異及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10使用spring boot開(kāi)發(fā)時(shí)java對(duì)象和Json對(duì)象轉(zhuǎn)換的問(wèn)題
這篇文章主要介紹了使用spring boot開(kāi)發(fā)時(shí)java對(duì)象和Json對(duì)象轉(zhuǎn)換的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03深入Java Robot實(shí)現(xiàn)控制鼠標(biāo)和鍵盤的方法詳解
本篇文章是對(duì)Java中用Robot實(shí)現(xiàn)控制鼠標(biāo)和鍵盤的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Java?延時(shí)隊(duì)列及簡(jiǎn)單使用方式詳解
這篇文章主要介紹了Java延時(shí)隊(duì)列簡(jiǎn)單使用方式,通過(guò)本文學(xué)習(xí)知道延時(shí)隊(duì)列是什么可以用來(lái)干什么,本文通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08SpringBoot?2.5.5整合輕量級(jí)的分布式日志標(biāo)記追蹤神器TLog的詳細(xì)過(guò)程
分布式追蹤系統(tǒng)是一個(gè)最終的解決方案,如果您的公司已經(jīng)上了分布式追蹤系統(tǒng),這篇文章主要介紹了SpringBoot?2.5.5整合輕量級(jí)的分布式日志標(biāo)記追蹤神器TLog,需要的朋友可以參考下2022-10-10帶你重新認(rèn)識(shí)Java動(dòng)態(tài)代理
這篇文章主要為大家介紹了Java的動(dòng)態(tài)代理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-11-11Spring的編程式事務(wù)TransactionTemplate的用法詳解
TransactionTemplate提供了一種在代碼中進(jìn)行編程式事務(wù)管理的方式,使開(kāi)發(fā)人員能夠在方法級(jí)別定義事務(wù)的開(kāi)始和結(jié)束點(diǎn),本文介紹了Spring框架中TransactionTemplate的用法,感興趣的朋友跟隨小編一起看看吧2023-07-07javaWeb實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了javaWeb實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01