Java 自定義注解在登錄驗證的應用


java注解

從 JDK 5開始,Java 增加了注解的新功能,注解其實是代碼里面的特殊標記,這些標記可以在編譯、類加載和運行時被讀取,在不改變代碼原有邏輯下,給源文件嵌入注解信息。再通過返回獲取注解信息,根據不同的注解信息處理不同邏輯。其中 Java 有以下幾個元Annotation:

@Retention

@Retention修飾 Annotation 可以保留多長時間,只包含一個 RetentionPolicy 一個成員變量。

  • RetentionPolicy.CLASS 默認值,編譯器把 Annotation 記錄在 class 文件中。當運行 Java 程序時,JVM 不能獲取 Annotation 信息。
  • RetentionPolicy.RUNTIME 編譯器把 Annotation 記錄在 class 文件中,當運行 Java 程序時,JVM 可以獲取 Annotation 信息,可以通過反射獲取 Annotation 信息,自定義注解使用此變量比較多
  • RetentionPolicy.SOURCE Annotation 只保留在源代碼(也就是 Java 文件),編譯器直接拋棄 Annotation。

@Target

@Target 修飾一個 Annotation 定義,它表示 Annotation 可以修飾在哪些地方:

  • ElementType.TYPE 類、接口以及枚舉
  • ElementType.FIELD 成員變量
  • ElementType.METHOD 方法
  • ElementType.PARAMETER 包定義
  • ElementType.CONSTRUCTOR 構造器
  • ElementType.ANNOTATION_TYPE Annotation
  • ElementType.PARAMETER 參數

登錄注解 @Logined

注解需求

以電商系統舉例,請求后端接口分成兩類:需要登錄后才能訪問不需要登錄訪問,所以就需要根據不同的需求做不同的處理,不需要登錄的訪問的接口不用做處理,而需要登錄的接口需要在每次請求時驗證請求,而在 Spring 可以使用攔截器作一個登錄信息驗證,而是否需要登錄驗證,這就需要用到注解了。

首先創建一個注解 @Logined,它要實現的功能:在需要登錄才能訪問的接口上添加該注解,可以添加在類和方法上,如果添加在類上,類下面所以的請求方法都需要進行登錄驗證。添加到方法上,只針對該方法需要驗證。@Logined 注解定義如下:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Logined {
    /**
     * 是否需要已經登錄才允許訪問
     *
     * @return
     */
    boolean isLogined() default true;

}

其中 @Target 設置 ElementType.METHOD 和 ElementType.TYPE 表示注解可以修飾在類和方法上,@Retention 設置 RetentionPolicy.RUNTIME 需要在運行時,JVM 可以獲取到注解信息。isLogined 是注解的一個成員變量,這個在后面會講到。
首先定義一個 Controller 控制器:

@RestController
@Logined
public class TestController {

	@GetMapping("/login")
	public String login() {
		return "need login";
	}
}

在攔截器上獲取 @Logined 注解

每次發送一個 http 請求后,都會進入到攔截器中。

public class MyInterceptor extends HandlerInterceptorAdapter{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (!(handler instanceof HandlerMethod)) {
			return true;
		}
		HandlerMethod handlerMethod = (HandlerMethod) handler;
		Method method = handlerMethod.getMethod();
		boolean isLogin = this.isLogin(method);
		if (!isLogin){
			return true;
		}
               // 這里對登錄信息驗證,比如token驗證,cookie驗證

		return true;
	}

	private boolean isLogin(Method method) {
		//獲取方法頭部值
		Logined classLogined = method.getDeclaringClass().getAnnotation(Logined.class);
		Logined methodLogined = method.getAnnotation(Logined.class);
                // 如果方法上有注解返回 isLogined 
		if (classLogined != null && methodLogined == null) {
			System.out.println(classLogined.isLogined());
			return classLogined.isLogined();
		}
                // 方法沒有注解,再找類上注解
		if ((classLogined != null && methodLogined != null) || (classLogined == null && methodLogined != null)) {
			return methodLogined.isLogined();
		}
		return false;
	}
}

攔截器流程:

  • 獲取請求類對應的方法
  • 通過反射找到方法上的 @Logined 注解,和類上的 @Logined 注解
    • 如果類上有 @Logined 注解,方法上沒有 @Logined 注解,返回類 @Logined 注解的 isLogined
    • 如果類和方法都有 @Logined 注解或者類沒有 @Logined 方法有注解,返回方法的 isLogined

經過上述判斷,如果返回是false,就不進行后續登錄信息驗證,否則需要登錄信息驗證。登錄信息驗證可以 token 驗證、cookie驗證。

總結

  • 在需要請求的接口類或者方法上添加 @Logined,表明需要改請求接口需要登錄后才能訪問。如果不需要就不添加,如果類添加了,而某個方法不需要登錄才能訪問,添加 @Logined(isLogined = false) 即可。
  • 在攔截器里面獲取類或者方法的注解,如果有注解,則需要登錄驗證,如果沒有,就直接通過。

如果覺得文章對你有幫助的話,請點個推薦吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM