一、三種方式
1、Ad-hoc 線程封閉: 程序控制實現,最糟糕
2、堆棧封閉:局部變量、無併發問題
3、ThreadLocal線程封閉:特別好的封閉方法
二、代碼
1、ThreadLocal
package com.current.flame.filter;
/**
* @author haoxiansheng
* ThreadLocal 代碼事例
*/
public class RequestHolder {
private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>();
public static void add(Long id) {
requestHolder.set(id);
}
public static Long getId() {
return requestHolder.get();
}
public static void remove() {
requestHolder.remove();
}
}
2、controller
package com.current.flame.controller;
import com.current.flame.filter.RequestHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author haoxiansheng
*/
@RestController
@RequestMapping("/threadLocal")
public class ThreadLocalController {
@GetMapping("/thread")
public Long threadLoca() {
return RequestHolder.getId();
}
}
3、Filter
package com.current.flame.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author haoxiansheng
*/
@Slf4j
public class HttpFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
log.info("do filter threatId=>{}, path=>{} ",Thread.currentThread().getId(), request.getServletPath());
RequestHolder.add(Thread.currentThread().getId()); // 添加數據
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
4、Interceptor
package com.current.flame.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author haoxiansheng
*/
@Slf4j
public class HttpInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle=>{}",request);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
RequestHolder.remove(); // 移除數據避免內存泄漏
log.info("afterCompletion=>");
return;
}
}