zoukankan      html  css  js  c++  java
  • springboot自定义注解

    springboot自定义注解

    注解(Annotation)对做java开发的小伙伴肯定不陌生,不能说熟悉,但一定在学习或者做项目的过程中有所耳闻,特别是随着springboot框架的大火,“约定大于配置”的开发理念被越来越多的人所喜爱。当然使用注解的最重要的好处就是减少代码的侵入,降低系统耦合性,当然就这一个理由就足够了。

    在没有详细了解注解,没有自己定义注解,没有应用自定义注解之前,我对注解的认知仅仅停留在它是一种标记,特别是在springboot中,通过注解我们可以免去繁琐的配置过程,简化开发流程,但现在我发现自定义注解如果真的用的好,可以解决很多实际开发过程中的痛点、难点,让我们可以提出更多更合理的非侵入式解决方案,比如方法的鉴权、多数据源的数据源选择。好了,这里我们先不多说了,开始正文。

    什么是注解

    这里要多说些,介绍下注解的一些情况。注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记。标记可以加在包、类、属性、方法、方法的参数以及局部变量上。通过反射可以拿到类、方法、变量上的注解。我们随便打开一个注解,比如springboot里面的Configuration注解:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Configuration {
        @AliasFor(
            annotation = Component.class
        )
        String value() default "";
    
        boolean proxyBeanMethods() default true;
    }
    

    根据上面的代码,我们可以得出以下结论:

    • 创建注解的关键字是@interface
    • 注解上也可以加注解
    • 注解可以有属性

    但注解上加的都是什么注解,都有什么含义呢?这里要引入注解的一个概念——元注解。所谓元注解就是声明在注解上的注解,元注解是注解的一种声明,元注解分别有以下五种:

    • @Retention:保留期,声明注解的存活时间
      • RetentionPolicy.SOURCE:仅源代码时保留,在编译时会被丢弃忽略
      • RetentionPolicy.CLASS:编译为class时保留,但不会被加载到jvm中
      • RetentionPolicy.RUNTIME:运行环境保留,会被加载到jvm中
    • @Documented:保留本类中的注解并能够被javadoc识别
    • @Target:指定注解的添加位置(类/方法/变量等)
      • ElementType.TYPE:类注解
      • ElementType.FIELD:字段注解
      • ElementType.METHOD:方法注解
      • ElementType.PARAMETER:方法内的参数注解
      • ElementType.CONSTRUCTOR:构造方法注解
      • ElementType.LOCAL_VARIABLE:局部变量注解
      • ElementType.ANNOTATION_TYPE:注解注解
      • ElementType.PACKAGE:包注解
      • ElementType.TYPE_PARAMETER
      • ElementType.TYPE_USE
    • @Inherited:注解是否能够被子类继承

    注解的介绍就到这里,我们继续往下看。

    创建springboot项目

    这里其实我不想介绍太多,因为我觉得这些都是很基础的东西,应该是每个小伙伴都会的,但考虑到还有一些小伙伴处在初学阶段,所以我还是会贴出我的项目结构,方便这些小伙伴参考:

    首先是项目结构

    pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>io.github.syske</groupId>
        <artifactId>custom-annotation-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>custom-annotation-demo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.61</version>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    自定义注解

    根据我们注解的介绍,我们在声明注解的时候必须用到元注解,否则这个注解是没有任何意义的。开始定义我们的第一个注解:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CheckAuth {
    }
    

    这样我们的第一个注解就定义好了,包含了两个元注解,一个指明注解的类型,一个指明注解的生存时间,是不是很简单,接下来,我们要开始使用我们的注解。

    自定义注解应用

    我先说下本次示例注解的应用思路:我刚定义的注解是为了方法鉴权操作,所以我把刚定义的注解加在需要进行鉴权操作的方法上,然后定义一个拦截器,拦截器的拦截规则设置为拦截所有,然后在拦截器内进行判断和校验,如果方法有鉴权注解,则进行鉴权操作,否则跳过,具体如下:

    拦截器

    public class AuthenticationInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                if (handlerMethod.hasMethodAnnotation(CheckAuth.class)) {
                    System.out.println("有CheckAuth注解");
                    String token = request.getParameter("token");
                    if (!"ABCDEF12345".equals(token)) {
                        throw new AuthException();
                    }
                }
            }
            return true;
        }
    }
    

    拦截器配置:

     // 鉴权拦截器
    registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**");
    

    这里最核心的操作是handlerMethod.hasMethodAnnotation(CheckAuth.class),即判断当前方法是否有CheckAuth.class注解。

    当然从handler中获取方法也是很重要的一个操作,我们只有从handler中拿到方法,才能判断该方法是否有我们自定义的注解。我们先来看下handler都有哪些类型:

    • HandlerMethod:方法
    • ResourceHttpRequestHandler:静态资源

    根据目前掌握的资料,我还没发现其他类型的handler,后面发现了再补充。

    总结

    好了,今天的内容就到这里,核心内容就是学会自定义注解,然后可以应用自定义注解解决问题。今天提供的思路就是通过自定义注解实现拦截器解耦,即新增方法后只需要在方法上增加鉴权注解即可,无需修改拦截器配置。某个方法不想鉴权,仅需要去掉方法上的鉴权注解即可。好了,大家周末愉快哦!!!

  • 相关阅读:
    格式控制符
    sort快速排序法
    堆积排序
    oracle常用命令
    C#中int和System.Int32理解总结
    IIS 7.5中的配置
    WPF循序渐进:XAML入门 .
    怎样找到excel两列之间同行相同的数据
    pl/sql functions and cbo costing
    Oracle 学习纲要
  • 原文地址:https://www.cnblogs.com/caoleiCoding/p/13419475.html
Copyright © 2011-2022 走看看