SpringBoot 自定义参数解析器
大约 2 分钟
自定义参数解析器
在项目开发中,经常会遇到很多地方都需要获取当前的登录用户对象,根据请求的 session 或者 token 去获取用户信息,于是经常会在很多地方出现获取用户信息的代码
//根据token获取用户信息
String token = request.getHeader("token");
// 查询用户
User user = userService.getCurrentUser(token);
每次都需要写相同的代码,当然我们也可以把这些重复代码封装到单独的方法中,但是这样还是不够优雅。
如果用过 SpringMvc 框架,就会知道该框架获取参数太方便了,参数自动封装到 JavaBean 、各种参数注解:RequestParam
、PathVariable
等
那么 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);
}
至此,就算配置完成了,接下来启动项目,用户登录成功后,访问接口,就可以看到返回当前登录用户数据了