使用自定義參數注解獲取 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. 注解類 (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;
}
到此就實現了預期的結果,回頭看發現雖然多寫了不少代碼,但是在用的時候還是更加簡潔明了,美麗大方(給自己比個❤)
