跳至主要內容

SpringBoot 自定义参数解析器

Zenghr大约 2 分钟SpringSpringBootSpringSpringBoot

自定义参数解析器

在项目开发中,经常会遇到很多地方都需要获取当前的登录用户对象,根据请求的 session 或者 token 去获取用户信息,于是经常会在很多地方出现获取用户信息的代码

//根据token获取用户信息
String token = request.getHeader("token");
// 查询用户
User user = userService.getCurrentUser(token);

每次都需要写相同的代码,当然我们也可以把这些重复代码封装到单独的方法中,但是这样还是不够优雅。

如果用过 SpringMvc 框架,就会知道该框架获取参数太方便了,参数自动封装到 JavaBean 、各种参数注解:RequestParamPathVariable

那么 SpringMvc 到底是怎么从 request 中把参数提取出来直接给我们的呢,这就用到今天说的一个参数解析器接口:HandlerMethodArgumentResolver

HandlerMethodArgumentResolver

自定义参数解析器需要实现 HandlerMethodArgumentResolver 接口,我们先来实现该接口,如下:

/**
 * 将请求映射方法列表中 UserInfo 类型参数进行解析
 * 解析成当前登录用户对象
 */
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {

    // 如果参数类型是 UserInfo,并且参数上有 @CurrentUser 注解,则使用该参数解析器
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType() == UserInfo.class
                && methodParameter.hasParameterAnnotation(CurrentUser.class);
    }

    //解析器解析规则:
    //此处将 UserInfo 类型参数, 解析成当前登录用户对象。
    //当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");
        return (UserInfo) userService.getCurrentUser(token);
    }
}
  • supportsParameter: 该方法表示是否启用这个参数解析器,返回 true 表示启用,返回 false 表示不启用
  • resolveArgument: 这是具体的解析过程,就是从 request 中取出参数的过程,方法的返回值就对应了接口中参数的值

使用自定义的注解来区分

/**
 * 用户参数注入注解
 * 贴有该注解用户参数使用自定义的参数解析器
 */
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}

通过自定义注解来区分是用框架自带的解析器还是自定义的

将自定义参数解析器添加到Spring容器中

最后,我们再将自定义的参数解析器配置到 HandlerAdapter 中,配置方式如下:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    // 自定义的用户解析器
    @Bean
    public CurrentUserArgumentResolver currentUserArgumentResolver(){
        return new CurrentUserArgumentResolver();
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(currentUserArgumentResolver());
    }
}

使用案例

@RequestMapping("/hello")
public void hello(@CurrentUser UserInfo userInfo) {
    System.out.println(userInfo);
}

至此,就算配置完成了,接下来启动项目,用户登录成功后,访问接口,就可以看到返回当前登录用户数据了