簡介
說明
本文介紹如何使用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();
}
}
儲存屬性
可以放到以下任意一個地方:
- 過濾器
- 攔截器
- ControllerAdvice
- 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";
}
}