近况

现在都是4月17日了,一年已经过了三分之一,我也没啥收获,教资考试3月份考完了
报名三科,考了两科,过了一科,最难的科二没过,考完当时就知道自己过不了,考的都是不会的内容
心态上已经炸了,没办法,下半年再学吧,现在的目标放在5月底的软考,9月下半年教资,11月下半年软考
上半年的系统分析师老实说不抱太大希望,没什么动力学习,公司项目上也忙的很,之前学的很多都忘记了
但该学还是得学,起码为下半年架构师打好基础,总之想成长总是要一步一步走,要尽力利用自己的优势
要尽力做自己能做的,一切都是为提升自己的能力而努力,加油!

回归正题,我们公司项目存在一个问题,就是前端和后端都不能很轻松拿到用户的角色信息
前端根本拿不到用户角色信息,后端想获取用户角色信息得去连数据库查才行
我想到之前学习过ThreadLocal的知识点,也看到过很多人利用ThreadLocal实现获取当前用户的角色信息
所以赶紧学习一下是怎么实现的,下面是具体实现步骤

  • 为User实体类新增一个字段,但不映射到数据库表中

    public class SysUser{
      ...
      /**
       * 标识用户角色
       */
      @TableField(exist = false)
      private String userRole;
    
      /**
       * 判断是否是平台管理员,true代表是,false代表不是
       */
      @TableField(exist = false)
      private Boolean isPlatformManager;
    }
  • 创建一个ThreadLocal工具类

    public class UserContextUtil {
        /**
         * 构造方法私有化
         */
        private UserContextUtil(){};
    
        private static final ThreadLocal<SysUser> CONTEXT = new ThreadLocal<>();
    
        /**
         * 存放用户信息
         * @param sysUser
         */
        public static void set(SysUser sysUser){
            CONTEXT.set(sysUser);
        }
    
        /**
         * 获取用户信息
         * @return
         */
        public static SysUser get(){
            return CONTEXT.get();
        }
    
        /**
         * 清除当前线程内引用,防止内存泄漏
         */
        public static void remove(){
            CONTEXT.remove();
        }
    }
  • 配置一个请求拦截器,拦截所有请求
    这里写的并不规范,应该要检验一下token的有效性的,或者拦截所有已经登录的请求
    考虑到使用ThreadLocal可能会有内存泄漏的情况,所以在接口执行后,再删除ThreadLocal中的内容
    不知道有没有必要,就是怕内存泄漏,写上总归好点。

    @Component
    @Slf4j
    public class UserInfoInterceptor  implements HandlerInterceptor {
    
        @Autowired
        private ISysUserService userService;
    
        @Value("${oea.platform-manager}")
        private String platformManager;
    
        @Autowired
        private ISysUserRoleService sysUserRoleService;
    
        @Autowired
        private ISysRoleService sysRoleService;
    
        @Autowired
        private CommonAPI commonAPI;
      
        @Autowired
        @Lazy
        private RedisUtil redisUtil;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
            boolean verifyToken = TokenUtils.verifyToken(request, commonAPI, redisUtil);
            if (verifyToken){
                String userName = JwtUtil.getUserNameByToken(request);
                SysUser currentUser = userService.getUserByName(userName);
                if (ObjectUtil.isNotEmpty(currentUser)){
                    //设置该用户的角色
                    // 平台管理员的权限,有此权限的用户是平台管理员,可查询所有部门数据
                    List<String> roles = userService.getRole(currentUser.getUsername());
                    boolean flag = false;
                    for (String role : roles) {
                        if (ObjectUtil.equals(role,platformManager)){
                            flag=true;
                        }
                    }
                    currentUser.setIsPlatformManager(flag);
                    currentUser.setUserRole(String.join(",",roles));
                    UserContextUtil.set(currentUser);
                }
            }
            return true;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            SysUser sysUser = UserContextUtil.get();
            if (ObjectUtil.isNotEmpty(sysUser)){
                UserContextUtil.remove();
          }
        }
    }
  • 创建一个配置类,将拦截器注入Spring容器中

    @Configuration
    public class MyAppConfigurer extends WebMvcConfigurationSupport {
        @Autowired
        private UserInfoInterceptor userInfoInterceptor;
    
        /**
         * 拦截器,将用户信息放入threadLocal
         * @param registry
         */
        @Override
        protected void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(this.userInfoInterceptor).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
    }
  • 实际使用

    SysUser sysUser = UserContextUtil.get()
    System.out.println(sysUser.getUserRole)
    System.out.println(sysUser.getIsPlatformManager)