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