SpringBoot自定义注解参数注入

场景

根据自定义注解拦截请求,利用header的token机制从缓存中获取信息,实现参数注入,控制器Controller层自动获取用户信息

流程图

在这里插入图片描述

核心代码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
    boolean required() default true;
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UnAuthToken {
    boolean required() default true;
}
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ApiIgnore
public @interface AuthUser {

    /**
     * 当前用户在request中的名字
     *
     * @return
     */
    boolean value() default true;

}
/**
 * 用户登录权限校验
 */
@Component
public class AuthUserInterceptor implements HandlerInterceptor {

    private static Logger log = LoggerFactory.getLogger(AuthUserInterceptor.class);

    @Autowired
    UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        if (response.getStatus() == 404) {
            throw new PathNotFoundException();
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(UnAuthToken.class)) {
            return true;
        }
        // 如果不是映射到方法查看controller层注解
        if (method.isAnnotationPresent(AuthToken.class) || handlerMethod.getBeanType().isAnnotationPresent(AuthToken.class)) {
            //登录验证
            AuthToken authToken = method.isAnnotationPresent(AuthToken.class) ? method.getAnnotation(AuthToken.class) : handlerMethod.getBeanType().getAnnotation(AuthToken.class);
            if (authToken.required()) {
                // 从 http 请求头中取出 token
                String token = request.getHeader("token");
                // token认证
                if (null == token) {
                    throw new JWTVerificationException("token为空");
                }
                if (JWT.decode(token).getExpiresAt().compareTo(new Date()) < 0) {
                    throw new JWTVerificationException("token过期");
                }
                User user = userService.cacheUser(token);
                TokenUtil.validateToken(user.getPassword(), token);
                if(null == user){
                    throw new JWTVerificationException("账户已失效,请重新登录!");
                }
                log.warn("tokenExpires:" + DateUtil.toDate(JWT.decode(token).getExpiresAt(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
        return true;
    }
}
/**
 * 请求参数注解 @AuthUser user
 */
@Component
public class AuthUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private UserService userService;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(AuthUser.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        if (parameter.hasParameterAnnotation(AuthUser.class)) {
            return userService.cacheUser(webRequest.getHeader("token"));
        } 
    }
}
@RestController
@RequestMapping("/api/area")
@Api(tags = "区域管理")
@AuthToken
public class AreaController {
    @Autowired
    private AreaService areaService;

    @GetMapping("/list")
    @ApiOperation("用户区域列表")
    public JsonResult<List<Area>> list(@AuthUser User user) {
        return JsonResult.success(areaService.getUserAreaList(user.getId()));
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java SpringBoot是一种使用了Spring框架的快速开发平台,它采用了自动配置和约定优于配置的原则,简化了Java应用程序的开发。自定义注解是在SpringBoot中扩展功能的一种方式,可以通过自定义注解来实现一些特定的业务逻辑,使得代码更加简洁和可读。 自定义注解可以用来标记某个方法、类或者字段,通过在注解中定义一些元数据,来改变注解所标记的元素的行为。在SpringBoot中,我们可以通过自定义注解来简化一些操作,比如对象自动注入。 在使用自定义注解时,我们还需要编写自定义解析器,通过解析器来读取和处理注解,完成对象的自动注入操作。自定义解析器需要实现Spring框架的BeanPostProcessor接口,该接口提供了对Bean对象进行处理的扩展点。 在自定义解析器中,我们需要重写接口中的两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。在这两个方法中,我们可以通过反射机制获取到标记了我们自定义注解的类或者字段,然后根据实际的业务需求进行处理。 例如,我们可以定义一个自定义注解@AutoInject,然后编写一个自定义解析器AutoInjectAnnotationBeanPostProcessor,用来实现对象的自动注入。在解析器中,我们可以通过反射机制获取到标记了@AutoInject注解的字段,然后使用Spring的依赖注入功能将依赖的对象注入到标记了@AutoInject注解的字段中。 总之,Java SpringBoot自定义注解和自定义解析器可以用来实现对象的自动注入操作。通过定义注解来标记需要注入的字段,然后通过自定义解析器来读取和处理注解,完成对象的自动注入。这样可以减少重复的代码,提高开发效率,并且使得代码更加清晰和可维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值