使用自定义参数注解获取 token 中 User 数据
使用背景
在 springboot 项目开发中需要从 token 中获取用户信息时通常的方式要经历几个步骤
拦截器中截获 token
TokenUtil 工具类解析 token 中的用户信息
把解析结果存入到成员变量中
controller 中通过 TokenUtil 工具类提供的静态方法获取用户信息
下面是过程示例代码
- /*--------1. 拦截器中获取 ---------*/
- String token =request.getHeader("token")
- /*--------2. 解析 ---------*/
- // 如果没过期且有效
- if(!TokenUtil.isExpire(token)){
- // 解析 token 把结果存入成员变量
- TokenUtil.decode(token);
- }
- /*--------3.controller 中获取 ---------*/
- User currentUser=TokenUtil.getUser();
看上去也没什么复杂指处, 但是如果在每个 Controller 中都加上一句
User currentUser=TokenUtil.getUser(); 感觉有些多余 (潜意识知道肯定有更简洁的方法能减少这里所写代码)
下面介绍一种使用自定义参数注解的方法简化获取结果
最后预期达到的效果
- @{RequestMethod}Mapping(value="path")
- public Object methodName(@CurrentUser User user){
- //...code
- }
正文开始
1. 拦截器中的代码 (GlobalInterceptor.java)
- public class GlobalInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- String token=request.getHeader("token");
- // 判断路径需要拦截
- //....code
- // 如果 token 有效
- if(!TokenUtil.isExpire(token)){
- User user = TokenUtil.getUser(token);
- // 我们将解析的用户结果先放入 session 中
- request.getSession().setAttribut("currentUser",user);
- }
- return true;
- }
- }
2. 注册拦截器 (CustomwebMvcConfigurer.java)
- @Configuration
- public class CustomWebMvcConfigurer implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- // 注册拦截器
- // 拦截规则根据实际情况, 请做更改 /** 指所有 /* 指 1 级目录
- registry.addInterceptor(new GlobalInterceptor()).addPathPatterns("/*/api/**");
- WebMvcConfigurer.super.addInterceptors(registry);
- }
- }
3. 注解类 (CurrentUser.java)
- @Target({
- ElementType.PARAMETER
- })//Annotation 所修饰的对象范围: 方法参数
- @Retention(RetentionPolicy.RUNTIME)//Annotation 被保留时间: 运行时保留 (有效)
- @Documented// 标记注解: java 工具文档化
- public @interface CurrentUser {
- }
4. CurrentUser 注解实现类 (CurrentUserHandlerMethodArgReslover.java)
- public class CurrentUserHandlerMethodArgReslover implements HandlerMethodArgumentResolver {
- /**
- * 判断是否支持使用 @CurrentUser 注解的参数
- */
- @Override
- public boolean supportsParameter(MethodParameter methodParameter) {
- // 如果该参数注解有 @CurrentUser 且参数类型是 User
- return methodParameter.getParameterAnnotation(CurrentUser.class) != null &&methodParameter.getParameterType() == User.class;
- }
- /**
- * 注入参数值
- */
- @Override
- public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
- // 取得 HttpServletRequest
- HttpServletRequest request= (HttpServletRequest) nativeWebRequest.getNativeRequest();
- // 取出 session 中的 User
- return (User)request.getSession().getAttribute("currentUser");
- }
- }
5. 在 SpringBoot 启动类中注册 注解的实现类 (ServerApplication.java)
- @SpringBootApplication
- public class ServerApplication extends WebMvcConfigurationSupport {
- /**
- * 启动入口
- * @param args
- */
- public static void main(String[] args) {
- SpringApplication.run(ServerApplication.class,args);
- }
- @Override
- protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers){
- // 注册 @CurrentUser 注解的实现类
- argumentResolvers.add(new CurrentUserHandlerMethodArgReslover());
- }
- }
6. 在 Controller 中使用
- @GetMapping(value="/demo/api/testget")
- public Object getTest(@CurrentUser User currentUser){
- System.out.println(currentUser);
- return currentUser;
- }
到此就实现了预期的结果, 回头看发现虽然多写了不少代码, 但是在用的时候还是更加简洁明了, 美丽大方 (给自己比个?)
gitbook 上预览此文章
来源: http://www.bubuko.com/infodetail-3280477.html