y

yanghi

V1

2022/10/13阅读:33主题:全栈蓝

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 接口来实现自定义的参数解析。

  1. 首先我们在项目根目录下创建 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;
}
}
  1. resolver 包下创建 @CurrentUserId 注解,用于将解析后的 userId,放入到被标记该注解的形参上。
/**
* 该注解标注在方法参数上,且保留在运行时
*/

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserId {

}
  1. 重写HandlerMethodArgumentResolver接口的 supportsParameter方法,判断方法中的参数是否标注 @CurrentUserId 注解;如果标注,则可以被当前的参数解析器解析。
    @Override
public boolean supportsParameter(MethodParameter parameter) {
//方法中的参数:标注有 @CurrentUserId 的注解可以被该参数解析器解析
return parameter.hasParameterAnnotation(CurrentUserId.class);
}
  1. 重写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;
}
  1. 在我们创建的 UserIdArgumentResolver 参数解析器类上标注 @Component 注解将其注入到容器中。
  2. 创建 MyMvcConfiguration 类实现 WebMvcConfigurer ,配置我们的自定义参数解析器,将其加入到参数解析器链中。
@Configuration
public class MyMvcConfiguration implements WebMvcConfigurer{

@Autowired
UserIdArgumentResolver userIdArgumentResolver;

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

3. 测试

  1. 修改我们之前获取 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);
}
  1. 重新启动我们的 SpringBoot 项目,重新登录获取 token
  1. 在请求头中携带 token,发起 GET 请求进行测试:

就成功获取我们自定义参数解析器解析的 userId了。

分类:

后端

标签:

后端

作者介绍

y
yanghi
V1