背景:在后台开发中,相关的接口需要获取用户登录的手机号识别用户的身份,目前用户的手机号存储在前端上送的cookie中,想要获取用户手机号,目前存在两种思路:
思路一:每个接口中前端都上送手机号,但是这种方法,前端开发者不喜欢这样做,每个接口都存在该字段,前端的想法会是将该字段放在header中,每次请求中header中都存在手机号字段。
思路二:后端从cookie中获取手机号。
以上两种方法,后端都需要封装一个统一的方法来获取用户手机号,如果一个接口写一个获取登录手机号的方法,代码冗余量很大。因此结合ThreadLocal+拦截器获取用户登录手机号。
代码实现如下:
所需要获取的信息对象:
@Data
public class LoginUserInfo {
/**
* 手机号
*/
private String mobileNo;
}
上下文信息类:
public class AuthLoginUserContext {
private static final ThreadLocal<LoginUserInfo> LOGIN_USER_INFO_THREAD_LOCAL = new ThreadLocal<>();
/**
* 设置登录用户信息
* @param loginUserInfo
*/
public static void setLoginUser(LoginUserInfo loginUserInfo) {
if (loginUserInfo != null) {
LOGIN_USER_INFO_THREAD_LOCAL.set(loginUserInfo);
} else {
LOGIN_USER_INFO_THREAD_LOCAL.remove();
}
}
/**
* 获取用户登录信息
* @return
*/
public static LoginUserInfo getLoginUserInfo() {
return LOGIN_USER_INFO_THREAD_LOCAL.get();
}
/**
* 获取登录用户手机号
* @return
*/
public static String getLoginUserMobile() {
return Optional.ofNullable(LOGIN_USER_INFO_THREAD_LOCAL.get()).map(LoginUserInfo::getMobileNo)
.orElseThrow(() -> UnLoginException.of(ErrorCode.UNAUTHORIZED));
}
}
我们在拦截器中调用上述的set方法:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//省略从cookie中获取数据的代码 AuthLoginUserContext.setLoginUser(LoginUserInfo.builder().mobileNo(object.getMobileNo()).build());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
AuthLoginUserContext.setLoginUser(null);
}