SpringBoot Web开发使用注解+参数解析器实现自定义参数解析
前言
本篇文章介绍如何实现自定义参数解析,主要使用的是注解+ HandlerMethodArgumentResolver 方法参数处理器来实现这个功能。请观众老爷们多多支持,并在评论区批评指正!
1. 问题

在前一篇文章我们进行 jwt+token 登录校验时,token 中保留的信息是用户 ID。当我们在其他请求中需要当前登录的用户 ID 时,就需要解析 token,我们可以这样做:

但是出现了一个问题,当我们有许多接口都要获取用户 ID,那么都需要写一遍解析 token,获取用户 ID 的代码。难道我们在需要获取 token 的方法中都写一遍重复代码,没有一种像 SpringMVC 提供的形参自动注入功能呢?
比如说我们在方法上标注 String userId,他就会自动帮我们获取响应体中的 userId呢?这样不就避免了繁琐提高了代码的复用性以及更加优雅。
@RequestMapping(value="/hi")
@ResponseBody
public ResponseResult<List> hello(@ResponseBody String userId) throws Exception{
System.out.println(userId);
List<String> list = new ArrayList<>();
list.add("hi");
return ResponseResult.setCommonStatusAndData(ResultCode.SUCCESS, list);
}
想要实现以下的效果我们可以自定义参数解析。
2. 如何做
如果我们想实现在方法参数上标注@ResponseBody就能获取请求体中的数据那样的效果,我们可以使用 HandlerMethodArgumentResolver 接口来实现自定义的参数解析。
- 首先我们在项目根目录下创建
resolver包,创建UserIdArgumentResolver类实现HandlerMethodArgumentResolver接口中的方法。
public class UserIdArgumentResolver implements HandlerMethodArgumentResolver {
/**
* 判断请求处理方法参数能否使用当前的参数解析器解析
* 前端发起请求时,请求方法中的参数会被封装成 MethodParameter,
* 通过 MethodParameter 来判断参数是否满足我们设立的条件
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
return false;
}
/**
* 进行参数解析的方法,可以在方法中获取对应的方法中的参数,
* 对参数进行处理,处理后的结果作为返回值返回,
* 方法的返回值就会赋值给对应的方法参数
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return null;
}
}
- 在
resolver包下创建@CurrentUserId注解,用于将解析后的userId,放入到被标记该注解的形参上。
/**
* 该注解标注在方法参数上,且保留在运行时
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserId {
}
- 重写
HandlerMethodArgumentResolver接口的supportsParameter方法,判断方法中的参数是否标注@CurrentUserId注解;如果标注,则可以被当前的参数解析器解析。
@Override
public boolean supportsParameter(MethodParameter parameter) {
//方法中的参数:标注有 @CurrentUserId 的注解可以被该参数解析器解析
return parameter.hasParameterAnnotation(CurrentUserId.class);
}
- 重写
HandlerMethodArgumentResolver接口的resolveArgument方法,对参数解析并返回处理后的值,给标注@CurrentUserId注解对应的方法参数。
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// 1.获取请求头中的 token
String token = webRequest.getHeader("token");
// 2. 解析token,获取userId
if(StringUtils.hasText(token)){
Claims claims = JwtUtil.parseJWT(token);
return claims.getSubject();
}
return null;
}
- 在我们创建的
UserIdArgumentResolver参数解析器类上标注@Component注解将其注入到容器中。 - 创建
MyMvcConfiguration类实现WebMvcConfigurer,配置我们的自定义参数解析器,将其加入到参数解析器链中。
@Configuration
public class MyMvcConfiguration implements WebMvcConfigurer{
@Autowired
UserIdArgumentResolver userIdArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userIdArgumentResolver);
}
}
3. 测试

- 修改我们之前获取
userId的处理方法,使用@CurrentUserId注解获取,并返回userId到响应体中。
@RequestMapping(value="/hi")
@ResponseBody
public ResponseResult hello(@CurrentUserId String userId) throws Exception{
Map<String, String> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("userId", userId);
return ResponseResult.setCommonStatusAndData(ResultCode.SUCCESS, objectObjectHashMap);
}
- 重新启动我们的
SpringBoot项目,重新登录获取token:

- 在请求头中携带
token,发起GET请求进行测试:

就成功获取我们自定义参数解析器解析的 userId了。
转载自:https://juejin.cn/post/7153567607265132557