스레드 클로저는 일반적으로 다음 세 가지 방법을 채택합니다.
임시 스레드 클로저: 프로그램 제어 구현, 최악, 무시
스택 클로저: 지역 변수, 동시성 문제 없음
ThreadLocal 스레드 클로저: 특히 좋은 클로저 방법
방법 2가 가장 일반적으로 사용됩니다. 변수는 인터페이스에서 정의됩니다. 이 기사에서는 주로 방법 3을 설명합니다. SpringBoot 프로젝트는 사용자 정의 필터와 인터셉터를 통해 ThreadLocal 스레드 클로저를 구현합니다. 필터 인터페이스 사용자 정의 필터를 구현하고 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(); } }
Customized 인터셉터는 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() { } }
Customized 인터셉터는 컨트롤러가 해당 내용을 제거합니다. 메모리 오버플로를 방지하기 위해 스레드를 사용한 후의 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 스레드 클로저를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!