当前位置:首页 > 代码编程 > 正文

SpringBoot实现自定义注解与控制器参数注入

代码编程 · Sep 05, 2024

前言

有这样一个场景,在某个控制器中的参数中,需要从 Request 的 Header 中取到 Authorization 请求头,其中 Authorization 是 Jwt 的身份 Token,我们需要取到 Token 中的 uid 字段,以用来判断当前的用户身份,在没有使用任何的权限身份管理框架的前提下,那么我们只能在 Controller 层进行一步步的调取,如果是有多个控制器的话,这样会增加很多的冗余代码,于是我们可以考虑使用自定义注解来实现类似于 SpringBoot 的参数注入。

正文

首先,我们需要定义一个自定义注解,命名为JwtToken


@Target(ElementType.PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

public @interface JwtToken {String value() default "uid";



}

接下来我们需要一个解析器,其实在 SpringBoot 中已经为我们提供了相关的处理解析器 -HandlerMethodArgumentResolver,我们只需要实现接口完成业务逻辑处理即可。

supportsParameter

supportsParameter接口是用于判断是否需要对该参数进行解析,如果该接口的返回值为 true,则会继续执行 resolveArgument 接口方法,所以我们这里应为:

@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(JwtToken.class);}

resolveArgument

resolveArgument接口是处理参数的分解,只有 supportsParameter 为 true 时才会调用此方法:

@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);String authorization = request.getHeader("Authorization");String result = null;JwtToken token = null;if(authorization!=null){Annotation[] methodAnnotations = parameter.getParameterAnnotations();for (Annotation methodAnnotation : methodAnnotations) {if(methodAnnotation instanceof JwtToken){token = (JwtToken) methodAnnotation;break;}}if(token!=null){result = JwtUtil.get(authorization,token.value());}}return result;}

其中我的 JwtUtil 中取 Token 中的信息的方法为:

public static String get(String token,String key) {try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(key).asString();} catch (JWTDecodeException e) {return null;}}

然后将我们写好的 Resolver 注入到 SpringMVC 的 ArgumentResolvers 中,如:

@SpringBootConfigurationpublic class SpringMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {argumentResolvers.add(new JwtTokenArgumentResolver());}}

到这一步我们的所有步骤就已经完成了,于是我们可以给需要取值的参数加上 code>@JwtToken 即可,例如:

@GetMappingpublic ResponseResult list(@JwtToken String uid){return ResponseResult.okHasData(shopsService.list(uid));}

总结


在 Spring 中为我们提供了许多方便的接口,可以简单易化实现我们的功能,例如我前段时间做的 encrypt-body-spring-boot-starter 就基于其 RequestBodyAdvice 与ResponseBodyAdvice接口来进行实现响应与请求参数的加解密,与之对应,这篇文章也能够体现出 Spring 这样的设计的好处。

未来无限可能,请大家尽情探索吧!