目的是为了 建一个工具类,让每个地方都可以用LongUtil去获取登录用户的id
在subject应用层的全局配置GlobalConfig中实现以下的方法 :
/**
* 添加拦截器到Spring MVC的拦截器注册表中。
*
* 本方法重写了Spring Boot默认的addInterceptors方法,目的是为了注册自定义的拦截器LoginInterceptor。
* 通过这个拦截器,可以对所有请求进行预处理,例如检查用户是否已登录。
*
* @param registry 拦截器注册表,用于添加新的拦截器和配置其对应的请求路径。
*/
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 添加LoginInterceptor拦截器,并配置其拦截所有请求的路径。
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**");
}
LoginInterceptor拦截器:
/**
* 登录拦截器类,用于在请求处理之前和处理之后进行相关逻辑处理。
* 实现了HandlerInterceptor接口,以拦截器的形式增强应用程序的功能。
*/
/**
* 登录拦截器
*
* @author: ChickenWing
* @date: 2023/11/26
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前执行的逻辑。
* 从请求头中获取登录ID,并将其设置到登录上下文中,以便后续使用。
*
* @param request HttpServletRequest对象,代表客户端的请求。
* @param response HttpServletResponse对象,用于向客户端发送响应。
* @param handler 将要处理请求的目标对象,可以是Controller等。
* @return boolean 返回值总是true,表示继续处理请求。
* @throws Exception 如果在处理过程中发生异常,可以抛出。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取登录ID
String loginId = request.getHeader("loginId");
// 将登录ID设置到登录上下文中
LoginContextHolder.set("loginId", loginId);
// 允许请求继续处理
return true;
}
/**
* 在请求处理完成后执行的逻辑。
* 从登录上下文中移除登录ID,进行资源清理。
*
* @param request HttpServletRequest对象,代表客户端的请求。
* @param response HttpServletResponse对象,用于向客户端发送响应。
* @param handler 将要处理请求的目标对象,可以是Controller等。
* @param ex 在处理过程中抛出的异常,如果有的话。
* @throws Exception 如果在处理过程中发生异常,可以抛出。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
// 从登录上下文中移除登录ID
LoginContextHolder.remove();
}
}
LoginContextHolder:
// 登录上下文持有器类,用于在多线程环境中存储和获取登录信息
public class LoginContextHolder {
// 静态线程局部变量,使用InheritableThreadLocal保证子线程可以访问父线程的数据
private static final InheritableThreadLocal<Map<String, Object>> THREAD_LOCAL
= new InheritableThreadLocal<>();
// 设置线程局部变量的键值对
public static void set(String key, Object val) {
// 获取或创建线程局部变量映射
Map<String, Object> map = getThreadLocalMap();
// 将键值对存入映射
map.put(key, val);
}
// 根据键获取线程局部变量的值
public static Object get(String key){
// 获取线程局部变量映射
Map<String, Object> threadLocalMap = getThreadLocalMap();
// 返回对应键的值
return threadLocalMap.get(key);
}
// 专门用于获取登录ID
public static String getLoginId(){
// 从线程局部变量映射中获取键为"loginId"的值并转换为String类型
return (String) getThreadLocalMap().get("loginId");
}
// 清除线程局部变量
public static void remove(){
// 移除线程局部变量
THREAD_LOCAL.remove();
}
// 获取或创建线程局部变量映射
public static Map<String, Object> getThreadLocalMap() {
// 尝试获取线程局部变量映射
Map<String, Object> map = THREAD_LOCAL.get();
// 如果映射为空,则创建一个新的ConcurrentHashMap
if (Objects.isNull(map)) {
map = new ConcurrentHashMap<>();
// 将新创建的映射设置为线程局部变量
THREAD_LOCAL.set(map);
}
// 返回线程局部变量映射
return map;
}
}
LoginUtil:
/**
* 登录工具类,提供获取当前登录用户ID的方法。
* 该类的设计目的是为了在系统中方便地获取当前登录用户的标识,以便进行权限检查或其他需要用户身份信息的操作。
*/
public class LoginUtil {
/**
* 获取当前登录用户的ID。
* 本方法通过调用LoginContextHolder中的getLoginId方法来实现,具体实现了如何从当前的上下文中获取登录用户ID的逻辑。
* 对于调用者来说,无需关心具体的实现细节,只需通过本方法即可获取到当前登录用户的ID。
*
* @return 当前登录用户的ID,以字符串形式返回。
*/
public static String getLoginId() {
return LoginContextHolder.getLoginId();
}
}