作用
- 持有上下文的Request容器
- 通过静态方法可以获取当前的Request请求
实现原理
在进行ServletRequest请求的时候,触发ServletRequestListener监听事件的子类RequestContextListener监听事件,调用requestInitialized()方法进行初始化的时候,将当前请求的相关信息放入一个ThreadLocal当中
ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的变量值完成操作的场景。
在每个线程的内部存在一个数据结构为Map的ThreadLocals变量,以<ThreadLocal,Value>的形式保存着线程变量和其对应的值。
对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰。
使用
// 补充
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
// 获取请求体 request
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
// 获取响应体 response
HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();
// 获取请求头 headers
Enumeration<String> headerNames = request.getHeaderNames();
// 根据请求体参数从 request 中获取 header 请求头值
Map<String, String> headers = new HashMap<>();
if (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
headers.put(name, request.getHeader(name));
}
使用案例:获取当前用户
private static NativeWebRequest getWebRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
return new ServletWebRequest(servletRequestAttributes.getRequest());
}
return null;
}
public static CurrentUser getCurrentUser() {
NativeWebRequest webRequest = getWebRequest();
if (webRequest != null) {
String detailJsonText = webRequest.getHeader(ClassroomConstant.CONTEXT_KEY_USER);
if (StringUtil.isNotEmpty(detailJsonText)) {
detailJsonText = new String(detailJsonText.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
CurrentUser currentUser = JsonMapper.getInstance().fromJson(detailJsonText, CurrentUser.class);
if (Objects.nonNull(currentUser)) {
return currentUser;
} else {
throw new BizException(ResultCode.INVALID_USER);
}
}
}
throw new BizException(ResultCode.INVALID_USER);
}
参考链接:https://blog.csdn.net/Ep_Little_prince/article/details/119455704