使用ThreadLocal缓存当前登录用户的信息

250 阅读1分钟

一、ThreadLocal工具类

public class ThreadLocalUtil {

    private static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 设置线程局部变量的值。
     *
     * @param value 值
     */
    public static void set(Object value) {
        THREAD_LOCAL.set(value);
    }

    /**
     * 获取线程局部变量的值。
     */
    public static <T> T get() {
        return (T) THREAD_LOCAL.get();
    }

    /**
     * 清理当前线程的ThreadLocal变量,防止内存泄漏。
     */
    public static void remove() {
        THREAD_LOCAL.remove();
    }
}

二、创建拦截器

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.boot.util.JWTUtils;
import com.boot.util.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Map;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查用户是否已登录
        String token = request.getHeader("Authorization");
        try {
            // 将解析token得到的用户信息存到ThreadLocal中
            Map<String, Object> claims = JWTUtils.parseToken(token).getClaim("claims").asMap();
            ThreadLocalUtil.set(claims);
            return true; // 用户已登录,继续执行请求
        } catch (JWTVerificationException e) {
            // 解析token报错 拦截请求
            response.setStatus(401);
            return false;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清理当前线程的ThreadLocal变量,防止内存泄漏。
        ThreadLocalUtil.remove();
    }
}

三、创建Web配置类注册拦截器

import com.boot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                // 指定拦截的路径,可使用路径模式如"/**"或排除某些路径
                .addPathPatterns("/**")
                // 排除不需要拦截的路径,如登录、注册页面等
                .excludePathPatterns("/user/login", "/user/register");
    }
}

四、在需要获取当前登录用户信息的地方使用ThreadLocal工具类

@GetMapping("/info")
public Result<User> info() {
    Map<String, Object> claims = ThreadLocalUtil.get();
    String username = (String) claims.get("username");
    User user = userService.getByName(username);
    return Result.success(user);
}