springboot(16)自定义注解

1. 前置知识

Java中的注解(Annotation)是一种引入元数据(metadata) 的机制,它提供了一种在代码中添加标记和信息的方式,可以帮助我们更好地理解代码的含义和作用。在Java注解中,有三个比较重要的元注解(meta-annotation),分别是@Target、@Retention、@Documented。

  • @Target

    @Target 用于指定注解的作用目标,也就是注解可以作用在哪些程序元素上。常用的值包括:

    • ElementType.TYPE:可以作用在类、接口、枚举类型上。
    • ElementType.FIELD:可以作用在字段上。
    • ElementType.METHOD:可以作用在方法上。
    • ElementType.PARAMETER:可以作用在方法的参数上。
    • ElementType.CONSTRUCTOR:可以作用在构造器上。
    • ElementType.LOCAL_VARIABLE:可以作用在局部变量上。
    • ElementType.ANNOTATION_TYPE:可以作用在注解类型上。
    • ElementType.PACKAGE:可以作用在包上。
  • @Retention

    @Retention 用于指定注解的生命周期,也就是注解在什么范围内有效。常用的值包括:

    • RetentionPolicy.SOURCE:注解只在源码中有效,编译时会被忽略。
    • RetentionPolicy.CLASS:注解在编译时会被保留,但在运行时会被忽略。
    • RetentionPolicy.RUNTIME:注解在运行时也有效,可以通过反射机制获取注解信息。
  • @Documented @Documented 用于指定注解是否包含在JavaDoc文档中,默认情况下注解是不包含在文档中的。

通过使用这些元注解,我们可以更加灵活地定义和使用注解,从而提高代码的可读性和可维护性。

2. 自定义注解案例

本文以案例验证token为目的开发注解

2.1 案例(一)

1. pom依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

2. 注解类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenRequired {
}

在Spring Boot中,可以使用自定义注解和切面类的方式来实现token的验证。首先,在自定义注解上添加元注解@Target和@Retention,用于指定注解作用在方法上和运行时有效。然后,在切面类中,使用@Around注解,指定切点为使用了@TokenRequired注解的方法。在切面方法中,通过反射机制获取方法上的@TokenRequired注解,判断是否需要验证token。如果需要验证,则获取请求头中的token信息,并进行验证。如果验证通过,则继续执行方法,否则抛出异常。

3. 切面类

@Aspect
@Component
public class TokenAspect {
    
    

    // 使用@Around注解,指定切点为使用了@TokenRequired注解的方法
    @Around("@annotation(com.example.demo.TokenRequired)")
    public Object checkToken(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        TokenRequired tokenRequired = method.getAnnotation(TokenRequired.class);
        if (tokenRequired != null) {
    
    
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = request.getHeader("token");
            if (StringUtils.isBlank(token)) {
    
    
                // 如果token为空,抛出TokenException
                throw new TokenException("Token is missing");
            }
            // 进行Token验证的逻辑
        }
        // 如果验证通过,继续执行方法
        return joinPoint.proceed();
    }

}

2.2 案例(二)

1、pom依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2、注解类

@Target({
    
    ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckToken {
    
    
 
    String value() default "";
 
}

3、切面类

package com.buba.config;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
@Aspect
@Component
@SuppressWarnings({
    
    "unused"})
public class CheckTokenAspect {
    
    
 
    public static final Logger logger = LoggerFactory.getLogger(CheckTokenAspect.class);
 
 
    @Pointcut("@annotation(com.buba.annotation.CheckToken)")
    public void annotationPointcut() {
    
    
 
    }
 
    @Before("annotationPointcut()")
    public void beforePointcut(JoinPoint joinPoint) throws Exception {
    
    
        // 请求开始时间
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String token  = sra.getRequest().getHeader("token");
 
        logger.info(token);
        if (token == null || "".equals(token)) {
    
    
            throw new Exception("token为空");
        }
        //校验token
    }
 
    @Around("annotationPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        return joinPoint.proceed();
    }
 
    /**
     * 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
     * @param joinPoint
     */
    @AfterReturning("annotationPointcut()")
    public void doAfterReturning(JoinPoint joinPoint) {
    
    
    }
 
}

4、应用

    @PostMapping("/testPost")
    @CheckToken
    public String postTest(){
    
    
        return "aaaaaaaaaaaa";
    }

3,总结

本文介绍了Java中的注解以及如何自定义注解。在自定义注解的案例中,我们通过使用切面编程来实现token的验证。我们可以通过自定义注解和切面编程来提高代码的可读性和可维护性。

猜你喜欢

转载自blog.csdn.net/Bilal_0/article/details/129986418