<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          springboot攔截器解耦——自定義注解

          共 6516字,需瀏覽 14分鐘

           ·

          2021-04-27 19:11

          注解(Annotation)對做java開發(fā)的小伙伴肯定不陌生,不能說熟悉,但一定在學(xué)習(xí)或者做項目的過程中有所耳聞,特別是隨著springboot框架的大火,“約定大于配置”的開發(fā)理念被越來越多的人所喜愛。當(dāng)然使用注解的最重要的好處就是減少代碼的侵入,降低系統(tǒng)耦合性,當(dāng)然就這一個理由就足夠了。
          在沒有詳細了解注解,沒有自己定義注解,沒有應(yīng)用自定義注解之前,我對注解的認知僅僅停留在它是一種標記,特別是在springboot中,通過注解我們可以免去繁瑣的配置過程,簡化開發(fā)流程,但現(xiàn)在我發(fā)現(xiàn)自定義注解如果真的用的好,可以解決很多實際開發(fā)過程中的痛點、難點,讓我們可以提出更多更合理的非侵入式解決方案,比如方法的鑒權(quán)、多數(shù)據(jù)源的數(shù)據(jù)源選擇。好了,這里我們先不多說了,開始正文。

          什么是注解

          這里要多說些,介紹下注解的一些情況。注解(Annotation)相當(dāng)于一種標記,在程序中加入注解就等于為程序打上某種標記。標記可以加在包、類、屬性、方法、方法的參數(shù)以及局部變量上。通過反射可以拿到類、方法、變量上的注解。我們隨便打開一個注解,比如springboot里面的Configuration注解:
          @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration {     @AliasFor(         annotation = Component.class    )     String value() default "";      boolean proxyBeanMethods() default true; }

          根據(jù)上面的代碼,我們可以得出以下結(jié)論:
          • 創(chuàng)建注解的關(guān)鍵字是@interface
          • 注解上也可以加注解
          • 注解可以有屬性
          但注解上加的都是什么注解,都有什么含義呢?這里要引入注解的一個概念——元注解。所謂元注解就是聲明在注解上的注解,元注解是注解的一種聲明,元注解分別有以下五種:
          • @Retention:保留期,聲明注解的存活時間
            • RetentionPolicy.SOURCE:僅源代碼時保留,在編譯時會被丟棄忽略
            • RetentionPolicy.CLASS:編譯為class時保留,但不會被加載到j(luò)vm中
            • RetentionPolicy.RUNTIME:運行環(huán)境保留,會被加載到j(luò)vm中
          • @Documented:保留本類中的注解并能夠被javadoc識別
          • @Target:指定注解的添加位置(類/方法/變量等)
            • ElementType.TYPE:類注解
            • ElementType.FIELD:字段注解
            • ElementType.METHOD:方法注解
            • ElementType.PARAMETER:方法內(nèi)的參數(shù)注解
            • ElementType.CONSTRUCTOR:構(gòu)造方法注解
            • ElementType.LOCAL_VARIABLE:局部變量注解
            • ElementType.ANNOTATION_TYPE:注解注解
            • ElementType.PACKAGE:包注解
            • ElementType.TYPE_PARAMETER
            • ElementType.TYPE_USE
          • @Inherited:注解是否能夠被子類繼承
          注解的介紹就到這里,我們繼續(xù)往下看。

          創(chuàng)建springboot項目

          這里其實我不想介紹太多,因為我覺得這些都是很基礎(chǔ)的東西,應(yīng)該是每個小伙伴都會的,但考慮到還有一些小伙伴處在初學(xué)階段,所以我還是會貼出我的項目結(jié)構(gòu),方便這些小伙伴參考:
          首先是項目結(jié)構(gòu)

          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>

          自定義注解

          根據(jù)我們注解的介紹,我們在聲明注解的時候必須用到元注解,否則這個注解是沒有任何意義的。開始定義我們的第一個注解:
           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 { }

          這樣我們的第一個注解就定義好了,包含了兩個元注解,一個指明注解的類型,一個指明注解的生存時間,是不是很簡單,接下來,我們要開始使用我們的注解。

          自定義注解應(yīng)用

          我先說下本次示例注解的應(yīng)用思路:我剛定義的注解是為了方法鑒權(quán)操作,所以我把剛定義的注解加在需要進行鑒權(quán)操作的方法上,然后定義一個攔截器,攔截器的攔截規(guī)則設(shè)置為攔截所有,然后在攔截器內(nèi)進行判斷和校驗,如果方法有鑒權(quán)注解,則進行鑒權(quán)操作,否則跳過,具體如下:
          攔截器
           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;    } }

          攔截器配置:
            // 鑒權(quán)攔截器 registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**");

          這里最核心的操作是handlerMethod.hasMethodAnnotation(CheckAuth.class),即判斷當(dāng)前方法是否有CheckAuth.class注解。
          當(dāng)然從handler中獲取方法也是很重要的一個操作,我們只有從handler中拿到方法,才能判斷該方法是否有我們自定義的注解。我們先來看下handler都有哪些類型:
          • HandlerMethod:方法
          • ResourceHttpRequestHandler:靜態(tài)資源
          根據(jù)目前掌握的資料,我還沒發(fā)現(xiàn)其他類型的handler,后面發(fā)現(xiàn)了再補充。

          總結(jié)

          好了,今天的內(nèi)容就到這里,核心內(nèi)容就是學(xué)會自定義注解,然后可以應(yīng)用自定義注解解決問題。今天提供的思路就是通過自定義注解實現(xiàn)攔截器解耦,即新增方法后只需要在方法上增加鑒權(quán)注解即可,無需修改攔截器配置。某個方法不想鑒權(quán),僅需要去掉方法上的鑒權(quán)注解即可。

          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久久人人人人人人 | 欧美在线 | 亚洲 | 欧美色图视频一区 | 五月天婷婷激情网 | 欧美成人性爱在线 |