Springboot中使用自定義參數注解獲取 token 中用戶數據


使用自定義參數注解獲取 token 中User數據

使用背景

在springboot項目開發中需要從token中獲取用戶信息時通常的方式要經歷幾個步驟

  1. 攔截器中截獲token
  2. TokenUtil工具類解析token中的用戶信息
  3. 把解析結果存入到成員變量中
  4. 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. 注解類 (CurrentUser.java)

@Target({ElementType.PARAMETER})//Annotation所修飾的對象范圍:方法參數
@Retention(RetentionPolicy.RUNTIME)//Annotation被保留時間:運行時保留(有效)
@Documented//標記注解:java工具文檔化
public @interface CurrentUser {
    
}

3. 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");
    }
}

4. 在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());
    }

    /**
    * 注冊攔截器
    * @param registry
    */
    @Override
    protected void addInterceptors(InterceptorRegistry registry {
        //注冊攔截器
        registry.addInterceptor(new GlobalInterceptor().addPathPatterns("/*/api/**");
        registry.addInterceptor(new TestInterceptor().addPathPatterns("/*/api/test/**");
        super.addInterceptors(registry);
    }
}

5. 在Controller中使用

@GetMapping(value="/demo/api/testget")
public Object getTest(@CurrentUser User currentUser){
    System.out.println(currentUser);
    return currentUser;
}

到此就實現了預期的結果,回頭看發現雖然多寫了不少代碼,但是在用的時候還是更加簡潔明了,美麗大方(給自己比個❤)

gitbook上預覽此文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM