持续创造,加快生长!这是我参加「日新方案 10 月更文挑战」的第8天,点击检查活动概况

前言

本篇文章介绍怎么完成自定义参数解析,主要运用的是注解+ HandlerMethodArgumentResolver 办法参数处理器来完成这个功用。请观众老爷们多多支持,并在评论区批评指正!

1. 问题

SpringBoot Web开发使用注解+参数解析器实现自定义参数解析

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

SpringBoot Web开发使用注解+参数解析器实现自定义参数解析

但是出现了一个问题,当咱们有许多接口都要获取用户 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. 测验

SpringBoot Web开发使用注解+参数解析器实现自定义参数解析

  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

SpringBoot Web开发使用注解+参数解析器实现自定义参数解析

  1. 在恳求头中带着 token,建议 GET 恳求进行测验:

SpringBoot Web开发使用注解+参数解析器实现自定义参数解析

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