天天看點

SpringBoot--使用ThreadLocal儲存每次請求的使用者資訊

簡介

說明

        本文介紹如何使用ThreadLocal儲存每次請求的使用者資訊。

        儲存之後,後邊的業務操作就可以擷取(Controller或者Service都可以,隻要在一個請求中)。

相關網址

也可以使用request的attribute儲存每次請求的使用者資訊,見 :SpringBoot--使用attribute儲存每次請求的使用者資訊_IT利刃出鞘的部落格

代碼

使用者實體類

package com.knife.common.entity;

import lombok.Data;

@Data
public class UserDTO {
    private Long userId;

    private String userName;
}      

定義ThreadLocal 

package com.knife.common.util;

import com.knife.common.entity.UserDTO;

public class UserThreadLocal {
    /**
     * 構造函數私有
     */
    private UserThreadLocal() {
    }

    private static final ThreadLocal<UserDTO> USER_INFO_THREAD_LOCAL = 
            new ThreadLocal<>();

    /**
     * 清除使用者資訊
     */
    public static void clear() {
        USER_INFO_THREAD_LOCAL.remove();
    }

    /**
     * 存儲使用者資訊
     */
    public static void set(UserDTO userDTO) {
        USER_INFO_THREAD_LOCAL.set(userDTO);
    }

    /**
     * 擷取目前使用者資訊
     */
    public static UserDTO getCurrentUser() {
        return USER_INFO_THREAD_LOCAL.get();
    }
}      

儲存屬性

可以放到以下任意一個地方:

  1. 過濾器
  2. 攔截器
  3. ControllerAdvice
  4. AOP

本處我使用攔截器。

攔截器類

package com.knife.common.interceptor;

import com.knife.common.entity.UserDTO;
import com.knife.common.util.UserThreadLocal;
import lombok.NonNull;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request,
                             @NonNull HttpServletResponse response,
                             @NonNull Object handler) {

        // 此處實際應該根據header的token解析出使用者
        // 本處為了簡單,直接虛構一個使用者
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(3L);
        userDTO.setUserName("Tony");
        UserThreadLocal.set(userDTO);
        return true;
    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest request,
                                @NonNull HttpServletResponse response,
                                @NonNull Object handler,
                                Exception e) {
        UserThreadLocal.clear();
    }
}      

注冊攔截器

package com.knife.common.config;
 
import com.knife.common.interceptor.UserInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new UserInterceptor());
    }
}      

擷取屬性

package com.knife.controller;

import com.knife.common.entity.UserDTO;
import com.knife.common.util.UserThreadLocal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@RestController
public class HelloController {

    @GetMapping("/test")
    public String test() {
        UserDTO currentUser = UserThreadLocal.getCurrentUser();
        System.out.println(currentUser.toString());
        return "test success";
    }
}      

測試