1. 首先我们应该明确用户登录参数应该是在请求头里被携带到后端接口的,那么我们首先应该有一个类用于拦截请求,获取信息,如下:通过实现 Filter 重写 doFilter 方法来获取请求头中信息并放行
java
@RequiredArgsConstructor
public class UserTransmitFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String username = httpServletRequest.getHeader("username");
if(StringUtils.isNotBlank(username)){
String userId = httpServletRequest.getHeader("id");
UserInfoDTO userInfoDTO = new UserInfoDTO(username,userId);
UserContext.setUser(userInfoDTO);
}
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
UserContext.removeUser();
}
}
}
2.将这个过滤器注册为 Spring 的一个 Bean
java
@Configuration
public class UserConfiguration {
/**
* 用户信息传递过滤器
*/
@Bean
public FilterRegistrationBean<UserTransmitFilter> globalUserTransmitFilter() {
FilterRegistrationBean<UserTransmitFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new UserTransmitFilter());
registration.addUrlPatterns("/*");
registration.setOrder(0);
return registration;
}
}
3. 通过 ThreadLocal 保存当前线程的用户信息
java
public final class UserContext {
private static final ThreadLocal<UserInfoDTO> USER_THREAD_LOCAL = new TransmittableThreadLocal<>();
/**
* 设置用户至上下文
*
* @param user 用户详情信息
*/
public static void setUser(UserInfoDTO user) {
USER_THREAD_LOCAL.set(user);
}
/**
* 获取上下文中用户 ID
*
* @return 用户 ID
*/
public static String getUserId() {
UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get();
return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getId).orElse(null);
}
/**
* 获取上下文中用户名称
*
* @return 用户名称
*/
public static String getUsername() {
UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get();
return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getUsername).orElse(null);
}
/**
* 清理用户上下文
*/
public static void removeUser() {
USER_THREAD_LOCAL.remove();
}
}
主要的逻辑代码如上,大家可以根据自己的项目进行修改