1 分析问题
对token的解析当初在拦截器中已经写过。期待的是在拦截器里写了,在其他地方就不写了,应该去复用拦截器里面得到的结果
2 解决方式-ThreadLocal
2.1提供线程局部变量
- 用来存取数据: set()/get()
- 使用ThreadLocal存储的数据, 线程安全
2.2过程图解
2.3代码实现
工具类
package com.aaa.utils;import java.util.HashMap; import java.util.Map;/*** ThreadLocal 工具类*/ @SuppressWarnings("all") public class ThreadLocalUtil {//提供ThreadLocal对象,private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();//根据键获取值public static <T> T get(){return (T) THREAD_LOCAL.get();}//存储键值对public static void set(Object value){THREAD_LOCAL.set(value);}//清除ThreadLocal 防止内存泄漏public static void remove(){THREAD_LOCAL.remove();} }
拦截器
package com.aaa.interceptors;import com.aaa.pojo.Result; //统一返回结果 import com.aaa.utils.JwtUtil;//token令牌 import com.aaa.utils.ThreadLocalUtil;//线程 import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component public class LoginInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//令牌验证String token = request.getHeader("Authorization");//验证tokentry {Map<String, Object> claims = JwtUtil.parseToken(token);//把业务数据存储到ThreadLocal中ThreadLocalUtil.set(claims);//放行return true;} catch (Exception e) {//http响应状态码为401response.setStatus(401);//不放行return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//清空ThreadLocal中的数据ThreadLocalUtil.remove();} }
控制器
@GetMapping("/userInfo")public Result<User> userInfo(/*@RequestHeader(name = "Authorization") String token*/) {//根据用户名查询用户/* Map<String, Object> map = JwtUtil.parseToken(token);String username = (String) map.get("username");*/Map<String, Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");User user = userService.findByUserName(username);return Result.success(user);}
3 小结
- 用来存取数据: set()/get()
- 使用ThreadLocal存储的数据, 线程安全
- 用完记得调用remove方法释放