Java自定義過濾器和攔截器實現(xiàn)ThreadLocal線程封閉
線程封閉
線程封閉一般通過以下三個方法:
- Ad-hoc線程封閉:程序控制實現(xiàn),最糟糕,忽略
- 堆棧封閉:局部變量,無并發(fā)問題
- ThreadLocal線程封閉:特別好的封閉方法
方法2是最常用的,變量定義在接口內,本文主要講解方法三,SpringBoot項目通過自定義過濾器和攔截器實現(xiàn)ThreadLocal線程封閉。實現(xiàn)Filter接口自定義過濾器和繼承HandlerInterceptorAdapter自定義攔截器。
ThreadLocal線程封閉實現(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();
}
}
自定義過濾器
自定義定義攔截器繼承Filter接口,實現(xiàn)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 {
}
/**
* 攔截到要執(zhí)行的請求時,doFilter就會執(zhí)行。這里我們可以寫對請求和響應的預處理。
* 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 {
/**
* 攔截處理程序的執(zhí)行。在 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執(zhí)行。。。");
return true;
}
/**
* 請求處理完成后(渲染視圖后)的回調。將在處理程序執(zhí)行的任何結果上調用,從而允許進行適當?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類啟動類中配置自定義過濾器和攔截器
/**
*
* @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();
}
}
請求訪問驗證
訪問調用接口http://localhost:8080/threadLocal/test,控制臺輸出如下:

到此這篇關于Java自定義過濾器和攔截器實現(xiàn)ThreadLocal線程封閉的文章就介紹到這了,更多相關Java ThreadLocal線程封閉內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用spring boot開發(fā)時java對象和Json對象轉換的問題
這篇文章主要介紹了使用spring boot開發(fā)時java對象和Json對象轉換的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
深入Java Robot實現(xiàn)控制鼠標和鍵盤的方法詳解
本篇文章是對Java中用Robot實現(xiàn)控制鼠標和鍵盤的方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05
SpringBoot?2.5.5整合輕量級的分布式日志標記追蹤神器TLog的詳細過程
分布式追蹤系統(tǒng)是一個最終的解決方案,如果您的公司已經(jīng)上了分布式追蹤系統(tǒng),這篇文章主要介紹了SpringBoot?2.5.5整合輕量級的分布式日志標記追蹤神器TLog,需要的朋友可以參考下2022-10-10
Spring的編程式事務TransactionTemplate的用法詳解
TransactionTemplate提供了一種在代碼中進行編程式事務管理的方式,使開發(fā)人員能夠在方法級別定義事務的開始和結束點,本文介紹了Spring框架中TransactionTemplate的用法,感興趣的朋友跟隨小編一起看看吧2023-07-07

