您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Java自定義過濾器和攔截器實現ThreadLocal線程封閉”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java自定義過濾器和攔截器實現ThreadLocal線程封閉”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
線程封閉一般通過以下三個方法:
Ad-hoc線程封閉:程序控制實現,最糟糕,忽略
堆棧封閉:局部變量,無并發問題
ThreadLocal線程封閉:特別好的封閉方法
方法2是最常用的,變量定義在接口內,本文主要講解方法三,SpringBoot項目通過自定義過濾器和攔截器實現ThreadLocal線程封閉。實現Filter接口自定義過濾器和繼承HandlerInterceptorAdapter自定義攔截器。
/** * <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; } }
/** * * @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自定義過濾器和攔截器實現ThreadLocal線程封閉”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。