Springboot中的拦截器以及ThreadLocal使用

项目要存在用户信息,由于这种关键信息不适合传参的方式,前端将用户信息封装到header里,后台通过拦截器获取,考虑项目没有使用多线程的情况,就用户信息存储在ThreadLocal里,方便拿去,也可以通过全局变量的方式。

1.创建一个userUtils
public class UserUtils {

    private UserUtils(){}
	// 这里是ThreadLocal,需要有user实体
    private static final ThreadLocal<User> USER_INFO = new ThreadLocal<User>();

    public static void set(User userInfo) {
        USER_INFO.set(userInfo);
    }

    public static User get() {
        return USER_INFO.get();
    }
	// 方便使用后移除ThreadLocal
    public static void remove() {
        USER_INFO.remove();
    }

    public static String getUserName() {
        return USER_INFO.get().getUserName();
    }

    public static String getUserId() {
        return USER_INFO.get().getUserId();
    }

    public static int getUserType() {
        return USER_INFO.get().getType();
    }
}
2.拦截器

定义好拦截器,有需要service要写,没有用到就不用。preHandle里处理,记得最后要返回true,不然请求就断了。

@Slf4j
@Configuration
public class OpsRequestInterceptor implements HandlerInterceptor {
	
	// 用来保存用户信息的,不需要的话,就不用设置service
	OpsUserService opsUserService;

    public OpsRequestInterceptor(OpsUserService opsUserService) {
        this.opsUserService = opsUserService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

         springboot跨域请求  放行OPTIONS请求
        //if(request.getMethod().toUpperCase().equals("OPTIONS")){
        //    return true;//通过所有OPTION请求
        //}
        // 前端URL编码,这里要解码,注意中文编码设置utf-8
        LOGGER.info("用户信息:{"+request.getHeader("userId")+URLDecoder.decode(request.getHeader("userName"), StandardCharsets.UTF_8.name())+request.getHeader("userType")+"}");
        if(StringUtils.isBlank(request.getHeader("userId"))
                || request.getHeader("userId").equalsIgnoreCase("null")){
            return false;
        }
        User User = new User();
        // 获取请求头中的参数   参数要跟前端的设置一样
        String userName = URLDecoder.decode(request.getHeader("userName"), StandardCharsets.UTF_8.name());
        String userId = URLDecoder.decode(request.getHeader("userId"), StandardCharsets.UTF_8.name());
        String userType = request.getHeader("userType");
        String mobile = request.getHeader("mobile");
        userId = userType+"_"+userId;
        User.setUserId(userId);
        User.setUserName(userName);
        User.setType(Integer.parseInt(userType));
        User.setMobile(mobile);
        UserUtils.set(User);
        LOGGER.info("拦截请求并将用户{"+User.getUserName()+"}的相关信息存入ThreadLocal");
        return true;
    }

    /**
     * 目录方法执行后
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    /**
     * 最后清理
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        LOGGER.info("移除用户信息的ThreadLocal");
        UserUtils.remove();
    }
}

注册拦截器,可以多个都写进来,填写要拦截的路径。

@Configuration
public class HandlerWebConfig implements WebMvcConfigurer {

    // 通过addInterceptor,addPathPatterns拦截类和路径,excludePathPatterns允许路径
    @Autowired
    OpsUserService opsUserService;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getVerifySignInterceptor()).order(2).addPathPatterns("/anno/ops/rest/**");
		// 没有用相关的service要删掉
        registry.addInterceptor(new OpsRequestInterceptor(opsUserService)).order(3)
                .addPathPatterns("/anno/ops/rest/**"); //要拦截的路径
                //.excludePathPatterns("/","/login","/css/**","fonts/**","/images/**","/js/**"); //避免拦截的路径
    }
}

具体使用的话,例如UserUtils.getUserId()就可以拿到用户ID了

你可能感兴趣的:(Spring,spring,boot,java,spring)