持续创造,加快生长!这是我参加「日新方案 10 月更文挑战」的第8天,点击检查活动概况
前言
本篇文章介绍怎么完成自定义参数解析,主要运用的是注解+ 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
了。