您的位置:首页 > 娱乐 > 八卦 > ThreadLocal的使用

ThreadLocal的使用

2024/12/23 13:14:28 来源:https://blog.csdn.net/m0_56356631/article/details/139856266  浏览:    关键词:ThreadLocal的使用

ThreadLocal 一般不会单独使用,基本上都是 放在一个工具类中,然后在拦截器中去使用(至少存储 Token 的时候是这样的)

这里为了更加还原真实的线上环境,直接就用了 拦截器+统一返回+全局异常捕获+ThreadLocal,项目还是比较完整的

首先创建一个项目 启动后看项目是否能跑通 这个就很简单了,直接略过

创建 ThreadlLocal 的工具类

public class TokenUtils {// 通过 ThreadLocal 存储 tokenprivate static final ThreadLocal<String> tokenThreadLocal = new ThreadLocal<>();// 设置 tokenpublic static void setToken(String token) {tokenThreadLocal.set(token);}// 获取 tokenpublic static String getToken() {return tokenThreadLocal.get();}// 清除 tokenpublic static void clearToken() {tokenThreadLocal.remove();}
}

编写拦截器 并注册到 容器中

//一个拦截器,拦截请求,把请求的时间记录下来,并将请求头中的 token 拿出来
public class MyInterceptor implements HandlerInterceptor {@Override//在请求处理之前进行调用(Controller方法调用之前)public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//记录请求时间long startTime = System.currentTimeMillis();request.setAttribute("startTime", startTime);//将请求头中的 token 拿出来
//        String token = request.getHeader("token");//从 Authorization 中获取 token 并去除 Bearer 字符串String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7);}//将 token 放入 ThreadLocal 中TokenUtils.setToken(token);return true;}@Override//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {//获取请求时间long startTime = (long) request.getAttribute("startTime");//计算请求处理时间long endTime = System.currentTimeMillis();System.out.println("本次请求处理时间为:" + (endTime - startTime) + "ms");}@Override//在整个请求结束之后被调用,也就是在 DispatcherServlet 渲染了对应的视图之后执行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//移除 ThreadLocal 中的 tokenSystem.out.println("清除 token" );TokenUtils.clearToken();}
}

注意,HandlerInterceptor 并不能让你 对返回值进行一些处理和修改,如果你想对返回值做处理和修改,你需要去了解的是 ResponseBodyAdvice

@Configuration
public class MyWebConfig implements WebMvcConfigurer {//注册 MyInterceptor 拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/public/**"); // 排除"/public"下的所有请求}
}

创建一个类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyStudent
{private String name;private int age;
}

统一的返回值

@Data
// 统一返回类
public class UnifiedReturn<T> {private int code;// 状态码  200正常  各种异常 需要在 枚举里面定义private String msg;// 返回信息private T data;// 返回数据public UnifiedReturn(T data) {this.data = data;}//successpublic static <T> UnifiedReturn<T> success(T data) {UnifiedReturn<T> aReturn = new UnifiedReturn<>(data);aReturn.setCode(UnifiedReturnEnum.SUCCESS.getCode());aReturn.setMsg(UnifiedReturnEnum.SUCCESS.getMsg());return aReturn;}//errorpublic static <T> UnifiedReturn<T> error(int code, String msg) {UnifiedReturn<T> aReturn = new UnifiedReturn<>(null);aReturn.setCode(code);aReturn.setMsg(msg);return aReturn;}
}

返回值的枚举

// 统一返回 枚举
public enum UnifiedReturnEnum {SUCCESS(200, "成功"),FAIL(500, "失败"),NO_PERMISSION(403, "无权限"),NOT_FOUND(404, "未找到"),PARAM_ERROR(400, "参数错误");private int code;private String msg;UnifiedReturnEnum(int code, String msg) {this.code = code;this.msg = msg;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

统一的 异常捕获

@ControllerAdvice//全局异常处理
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBody  //返回json  这边是一定要加的public UnifiedReturn<String> exceptionHandler(Exception e) {return UnifiedReturn.error(UnifiedReturnEnum.FAIL.getCode(), e.getMessage());}
}

控制器

@RestController
@RequestMapping("/basic")
public class BasicController {@GetMapping("/hello")public UnifiedReturn<MyStudent> hello() {String token = TokenUtils.getToken();//该方法想在哪里用都可以,只要在同一个线程中 都能获取到 tokenSystem.out.println("token: " + token);return UnifiedReturn.success(new MyStudent("theonefx", 18));}//测试异常处理--这里测试的是 运行时异常@GetMapping("/exception")public UnifiedReturn<String> exception() {int i = 1/0;return UnifiedReturn.success("success");//不会执行到这里}@GetMapping("/exception2")//这里测试的是 主动抛出的异常public UnifiedReturn<String> test() {throw new RuntimeException("test exception");}}

请求看一下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com