后台管理系统经常需要在Handler中获取已登录的用户信息,登录用户的存储可能是存于session或redis,那么如何让Handler快速获取用户信息且无需关心用户数据存放于何处,甚至后续登录用户数据存放的迁移也无需变动Handler。期望达到的效果如下:
@PostMapping("/user/getUserInfo")
@ResponseBody
public ResponseVO<UserInfo> getUserInfo(@Login UserInfo userInfo) {
ResponseVO<UserInfo> responseVO = new ResponseVO<>();
responseVO.setBizObj(userInfo);
return responseVO;
}
那么如何实现上述效果呢?
1、定义自己的注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author katasea
* 2020/5/18 17:43
*/
@Target(ElementType.PARAMETER)//表示此注解用于参数
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}
2、编写解析自定义ArgumentResolver
本文使用的用户对象UserInfo读者无需关心,具体替换为自己的用户类即可
import com.health.bean.po.Login;
import com.health.bean.po.UserInfo;
import com.health.util.Global;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* @author katasea
* 2020/6/5 10:38
*/
@Configuration
public class LoginHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
//这里用户对象放于redis,根据实际场景自行调整
@Resource
private RedisTemplate<String,Object> redisTemplate;
private Logger logger = LoggerFactory.getLogger(this.getClass());
//判断当注解为Login时且用户对象为UserInfo【可替换为自己的对象】,才进行解析
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return (null != methodParameter.getParameterAnnotation(Login.class) && UserInfo.class == methodParameter.getParameterType());
}
//如何获取当前登录用户的具体实现
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
try{
UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(request.getAttribute(Global.TOKEN));
return userInfo;
}catch (Exception e) {
return null;
}
}
}
3、增加拦截器配置
以下提供SpringBoot拦截器配置项
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import javax.annotation.Resource;
import java.util.List;
/**
* @author katasea
* 2020/5/12 13:48
*/
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Resource
LoginHandlerMethodArgumentResolver userArgumentResolver;
//若已经存在拦截器配置,则只需增加以下方法即可。
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
}
}
4、Handler尝试获取登录用户对象
//页面请求入参为空
@PostMapping("/user/getUserInfo")
@ResponseBody
public UserInfo getUserInfo(@Login UserInfo userInfo) {
return userInfo;
}