找回密码
 立即注册
查看: 240|回复: 0

JavaWeb(SpringBoot3+vue3)教学管理系统项目实战之获取当前登录员工ThreadLocal

[复制链接]

156

主题

5

精华

160

金币

技术维护QQ:515138

积分
345
发表于 2025-12-3 10:29:35 | 显示全部楼层 |阅读模式
JavaWeb(SpringBoot3+vue3)教学管理系统项目实战之获取当前登录员工ThreadLocal
  • ThreadLocal并不是一个Thread,而是Thread的局部变量。
  • ThreadLocal为每个线程提供一份单独的存储空间,具有线程隔离的效果,不同的线程之间不会相互干扰。
  • 常见方法:
    • public void set(T value)   设置当前线程的线程局部变量的值
  •       public T get()                     返回当前线程所对应的线程局部变量的值
    • public void remove()          移除当前线程的线程局部变量
    具体操作步骤:
    • 定义ThreadLocal操作的工具类,用于操作当前登录员工ID。
    com.zidiu.utils 引入工具类 CurrentHolder
  1. package com.zidiu.utils;
  2. public class CurrentHolder {
  3.     private static final ThreadLocal<Integer> CURRENT_LOCAL = new ThreadLocal<>();
  4.     public static void setCurrentId(Integer employeeId) {
  5.         CURRENT_LOCAL.set(employeeId);
  6.     }
  7.     public static Integer getCurrentId() {
  8.         return CURRENT_LOCAL.get();
  9.     }
  10.     public static void remove() {
  11.         CURRENT_LOCAL.remove();
  12.     }
  13. }
复制代码
  • 在TokenFilter中,解析完当前登录员工ID,将其存入ThreadLocal(用完之后需将其删除)。
  1. package com.zidiu.filter;
  2. import com.zidiu.utils.CurrentHolder;
  3. import com.zidiu.utils.JwtUtils;
  4. import io.jsonwebtoken.Claims;
  5. import jakarta.servlet.*;
  6. import jakarta.servlet.annotation.WebFilter;
  7. import jakarta.servlet.http.HttpServletRequest;
  8. import jakarta.servlet.http.HttpServletResponse;
  9. import lombok.extern.slf4j.Slf4j;
  10. import java.io.IOException;
  11. @Slf4j
  12. @WebFilter(urlPatterns = "/*")
  13. public class TokenFilter implements Filter {
  14.     @Override
  15.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  16.         HttpServletRequest request = (HttpServletRequest) servletRequest;
  17.         HttpServletResponse response = (HttpServletResponse) servletResponse;
  18.         //1. 获取请求的url地址
  19.         String uri = request.getRequestURI(); // /employee/login
  20.         //String url = request.getRequestURL().toString(); // http://localhost:8080/employee/login
  21.         //2. 判断是否是登录请求, 如果url地址中包含 login, 则说明是登录请求, 放行
  22.         if (uri.contains("login")) {
  23.             log.info("登录请求, 放行");
  24.             filterChain.doFilter(request, response);
  25.             return;
  26.         }
  27.         //3. 获取请求中的token
  28.         String token = request.getHeader("token");
  29.         //4. 判断token是否为空, 如果为空, 响应401状态码
  30.         if (token == null || token.isEmpty()) {
  31.             log.info("token为空, 响应401状态码");
  32.             response.setStatus(401); // 响应401状态码
  33.             return;
  34.         }
  35.         //5. 如果token不为空, 调用JWtUtils工具类的方法解析token, 如果解析失败, 响应401状态码
  36.         try {
  37.             Claims claims = JwtUtils.parseJWT(token);
  38.             Integer empId = Integer.valueOf(claims.get("id").toString());
  39.             CurrentHolder.setCurrentId(empId);
  40.             log.info("token解析成功, 放行");
  41.         } catch (Exception e) {
  42.             log.info("token解析失败, 响应401状态码");
  43.             response.setStatus(401);
  44.             return;
  45.         }
  46.         //6. 放行
  47.         filterChain.doFilter(request, response);
  48.         //7. 清空当前线程绑定的id
  49.         CurrentHolder.remove();
  50.     }
  51. }
复制代码
  • 在AOP程序中,从ThreadLocal中获取当前登录员工的ID。
  1. package com.zidiu.aop;
  2. import com.zidiu.anno.LogOperation;
  3. import com.zidiu.mapper.OperateLogMapper;
  4. import com.zidiu.pojo.OperateLog;
  5. import com.zidiu.utils.CurrentHolder;
  6. import org.aspectj.lang.ProceedingJoinPoint;
  7. import org.aspectj.lang.annotation.Around;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Component;
  11. import java.time.LocalDateTime;
  12. import java.util.Arrays;
  13. @Aspect
  14. @Component
  15. public class OperationLogAspect {
  16.     @Autowired
  17.     private OperateLogMapper operateLogMapper;
  18.     // 环绕通知
  19.     @Around("@annotation(log)")
  20.     public Object around(ProceedingJoinPoint joinPoint, LogOperation log) throws Throwable {
  21.         // 记录开始时间
  22.         long startTime = System.currentTimeMillis();
  23.         // 执行方法
  24.         Object result = joinPoint.proceed();
  25.         // 当前时间
  26.         long endTime = System.currentTimeMillis();
  27.         // 耗时
  28.         long costTime = endTime - startTime;
  29.         // 构建日志对象
  30.         OperateLog operateLog = new OperateLog();
  31.         operateLog.setOperateEmpId(getCurrentUserId()); // 需要实现 getCurrentUserId 方法
  32.         operateLog.setOperateTime(LocalDateTime.now());
  33.         operateLog.setClassName(joinPoint.getTarget().getClass().getName());
  34.         operateLog.setMethodName(joinPoint.getSignature().getName());
  35.         operateLog.setMethodParams(Arrays.toString(joinPoint.getArgs()));
  36.         operateLog.setReturnValue(result.toString());
  37.         operateLog.setCostTime(costTime);
  38.         // 插入日志
  39.         operateLogMapper.insert(operateLog);
  40.         return result;
  41.     }
  42.     // 示例方法,获取当前用户ID
  43.     private int getCurrentUserId() {
  44.         return CurrentHolder.getCurrentId();
  45.     }
  46. }
复制代码
在同一个线程/同一个请求中,进行数据共享就可以使用 ThreadLocal。

SpringBoot3+Vue3开发综合实战项目:
JavaWeb(SpringBoot3+vue3)开发+教学管理系统项目实战


上一篇:JavaWeb(SpringBoot3+vue3)开发+教学管理系统项目实战之AOP切面
下一篇:JavaWeb(SpringBoot3+vue3)开发+教学管理系统项目实战之分模块设计与开发
网站建设,公众号小程序开发,系统定制,软件App开发,技术维护【联系我们】手机/微信:17817817816 QQ:515138

QQ|Archiver|自丢网 ( 粤ICP备2024252464号-1 )

GMT+8, 2026-1-19 13:08

专注于网站建设,公众号小程序制作,商城小程序,系统定制,软件App开发

【联系我们】手机/微信:17817817816 QQ:515138

快速回复 返回顶部 返回列表