1. 程式人生 > 其它 >SpringMVC自定義引數解析器

SpringMVC自定義引數解析器

一、問題描述

前端把 token 存放在請求頭裡面,後端介面如果需要獲取當前登入使用者資訊,我們是使用 HttpServletRequest 來獲取請求頭的 token,但是如果後續很多介面都需要獲取當前登入使用者資訊,此時就出現程式碼重複問題。

二、假設分析

我們能不能做出一個介面引數,讓所有訪問這個具備指定引數的介面都能獲取當前登入使用者物件,該怎麼實現?

三、應用技術

使用技術:SpringMVC 引數解析器
解析器有兩種:

  • SpringMVC 預設解析器
  • 自定義引數解析器
    作用:將介面(請求對映方法)UserInfo 型別的引數解析成當前登入使用者物件

這兩種,選哪個呢?不難看出,因為預設引數解析器是無法實現當前登入使用者物件注入,此時選擇第二種。

四、程式碼實現

業務需要區分場景的時候(比如登入與未登入),可以編寫一個自定義註解
編寫一個自定義註解,放於 annotation 包下

@Target(ElementType.PARAMETER) // 引數
@Retention(RetentionPolicy.RUNTIME)
public @interface UserParam {

}

新建一個 resolver 包,編寫自定義解析器

/**
 * 自定義引數解析器
 * 作用:
 * 將介面中宣告 UserInfo 型別的引數,解析成當前登入使用者物件,並注入
 */

public class UserInfoArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private IUserInfoRedisService userInfoRedisService;

    //用於識別介面引數型別
    //指定當前解析器能解析介面引數的型別: 此處是UserInfo.class型別
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType() == UserInfo.class
                && methodParameter.hasParameterAnnotation(UserParam.class);
    }


    //用於解析介面引數,並注入引數值
    //前提: supportsParameter 方法返回true之後執行
    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) throws Exception {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        String token = request.getHeader("token");
        UserInfo userInfo = userInfoRedisService.getUserByToken(token);
        return userInfo;
    }
}

配置類

@Configuration
public class WebsiteConfig implements WebMvcConfigurer {
    // 引數解析器
    @Bean
    public UserInfoArgumentResolver userInfoArgumentResolver(){
        return new UserInfoArgumentResolver();
    }

    // 加進 HandlerMethodArgumentResolver 裡面作為它的實現類
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(userInfoArgumentResolver());
    }
}

controller層

    @GetMapping("/userInfo")
    @ResponseBody
    public Object user(@UserParam UserInfo user){
        return JsonResult.success(user);
    }

以上,程式碼已實現功能
那麼,SpringMVC 的自定義引數解析器究竟是如何實現功能的呢?看流程圖