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

9,956次阅读
20条评论

前言

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

正文

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

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

    String value() default "uid";

}

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

supportsParameter

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

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

resolveArgument

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

@Override
public 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中,如:

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

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

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

总结

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

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

9
憧憬Licoy
版权声明:本站原创文章,由憧憬Licoy于2018年10月17日发表,共计3470字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(20条评论)
Loading...
新闻 评论达人LV.1
2018-12-03 23:08:40 回复

文章不错非常喜欢

姜辰 评论达人LV.1
2018-12-03 00:02:06 回复

这种干货有一个特点,可以治好我的失眠。

gellytech 评论达人LV.1
2018-11-16 19:50:20 回复

谢谢分享,学习一下

宏远博客 评论达人LV.1
2018-11-11 17:07:27 回复

不错哦

v2er-澳洲农场主 评论达人LV.1
2018-10-31 14:45:55 回复

你这个自定义的Resolver不需要注册到spring吗,配置类中类似addArgumentResolvers这样的操作,不然怎么生效的?

男装品牌 评论达人LV.1
2018-10-28 22:27:13 回复

文章不错非常喜欢

沙缸过滤器 评论达人LV.1
2018-10-27 10:23:30 回复

学程序好烦

广州网站建设 评论达人LV.2
2018-10-22 10:58:36 回复

写的不错

子午书屋 评论达人LV.1
2018-10-18 18:35:47 回复

这是微服务那一套吧