場景: 對需要校驗 手機驗證碼和短信驗證碼的controller方法添加 自定義的注解 @CheckType
1. 定義注解
1 /** 2 * 需要短信、驗證碼驗證方法上的注解 3 * date: 2018年11月17日 上午10:28:50 <br/> 4 * 5 * @author ytqiao 6 */ 7 /** 8 *Retention注解:定義被它所注解的注解保留多久( 9 * SOURCE :被編譯器忽略, 10 * CLASS : 注解將會被保留在Class文件中,但在運行時並不會被VM保留。這是默認行 11 * 為,所有沒有用Retention注解的注解,都會采用這種策略。 12 * RUNTIME : 保留至運行時。所以我們可以通過反射去獲取注解信息 13 * ) 14 *Target注解:用於描述被該注解標注的注解的作用范圍(即:被描述的注解可以用在什么 15 * 地方) 16 * 1. CONSTRUCTOR: 用於描述構造器 17 * 2. FIELD: 用於描述域 18 * 3. LOCAL_VARIABLE: 用於描述局部變量 19 * 4. METHOD: 用於描述方法 20 * 5. PACKAGE: 用於描述包 21 * 6. PARAMETER: 用於描述參數 22 * 7. TYPE: 用於描述類、接口(包括注解類型) 或enum聲明 23 */ 24 @Retention(RetentionPolicy.RUNTIME) 25 @Target({ElementType.METHOD}) 26 public @interface CheckType { 27 28 /** 29 * 前置執行方法,定義在CheckTypeInterceptor中 30 * date: 2018年12月29日 下午5:41:19 <br/> 31 * 32 * @author zlliu 33 * @return 34 */ 35 String value() default ""; // 默認漢值 36 }
2: 配置系統參數(在application.yml中配置是否需要驗證驗證碼)
...... info: sys: # 短信或驗證碼 0:短信 1:驗證碼,2:兩個都驗證,其它不驗證 checkType: 2
3: 根據業務使用注解做出相應判斷
這里是在spring的aop中來判斷注解,並決定是否進行驗證碼的校驗
1 /** HandlerInterceptor : spring 中要做攔截器所實現的代理接口。 2 * 要重寫的三個方法為: 3 * 1. preHande: 在進入controller方法之前執行 4 * 2. postHandle: 在進入controller 方法之后,返回視圖模型之前(也就是return語句 5 * 之前)執行 6 * 3. afterCompletion: 在controller 方法執行完之后執行。 7 */ 8 9 public class CheckTypeInterceptor implements HandlerInterceptor { 10 // @Value 注解是springBoot 用來獲取系統配置的。 checkType配置在 11 // application.yml中, 12 @Value("${info.sys.checkType}") 13 private Integer checkType; // 系統中配置的是否需要驗證驗證碼 14 15 // req、res參數就無需多解釋 16 // handler 參數是被代理的方法對象(這里之所以說代理而不是說被攔截的,是因為 17 // spring的攔截器是基於aop而aop是用動態代理實現。也可以理解成是被攔截的方 18 // 法對象) 19 @Override 20 public boolean preHande(HttpServletRequest req, HttpServletResponse 21 res, Object handler) { 22 // 當獲取到的系統中的配置為null,時,說明不校驗。就放過 23 if (checkType == null) { 24 return true; 25 } 26 // 將被攔截的方法對象轉成HandlerMethod對象 27 // 關於HandlerMethod對象,是用來封裝方法定義相關的信息(如:方法所屬 28 // 類、方法的參數、方法本身等)。可以理解成是具有了方法信息的一個實體 29 // 類. 30 // @CheckType 注解標記 31 HandlerMethod handlerMethod = (HandlerMethod)handler; 32 // 調用getMethod()方法來獲取方法本身,一遍 33 Method method = handlerMethod.getMethod(); 34 // 用方法本身來調用getAnnotation(x)方法來拿到參數中傳入的注解類 35 // 如果返回值不為空說明方法被該注解標記。否則沒有被該注解標記 36 CheckType checkType = method.getAnnotation(CheckType.class); 37 if (checkType == null) { 38 // 這里根據業務,如果沒有加注解,說明不需要驗證驗證碼,就返回 39 // true. 40 return true; 41 } 42 // 拿到傳入注解中的值 43 Stirng value = checkType.value(); 44 // 根據傳入的值來做一些業務相關判斷 45 // 下面就都與業務相關了。這里不貼出。 如果要拿到傳入Controller 的參數 46 // 那么就調用req.getParameter("xxx");即可 47 48 } 49 50 }
4. 將自定義的攔截器類注冊到容器系統中
/** * 我們在自定義攔截器的時候,僅僅定義一個類實現HandlerInterceptor接口是不夠的 *我們還要將自定義的攔截器類注冊到系統中並重寫方法來告訴系統都需要攔截什么樣的請*求 * 所以這里就是實現 WebMvcConfigurer 接口(此接口是spring boot中的)。 * WebMvcConfigurer 接口是springboot 定義配置的接口,相當於spring的.xml配置文*件 *代碼如下: */ public class SmsConfiguration implements WebMvcConfigurer{ // @Bean注解是將該方法產生的bean交給spring容器管理 @Bean public CheckTypeInterceptor checkTypeInterceptor() { return new CheckTypeInterceptor(); } // addInterceptors 是來注冊攔截器的方法(如果不使用 // springboot 估計要在配置文件中配置了) @Override public void addInterceptors(InterceptorRegistry registry) { /** addInterceptor("xxx"); 方法是給注冊具體的攔截器的, 參數格式為: *自定義的注解的對象調用addPathPatterns("xxx")方 *法,來為自定義攔截器添加攔截的請求
* 另外一個方法 registry.addInterceptor(checkTypeInterceptor()).addPathPatterns("xxx").excludePathPatterns("xxx","xxx","xxx",...)
* 這里的excludePathPatterns():方法是用來排除特定的請求的,比如首頁等。 所以一般的做法是:先用addInterceptor("/**")方法來添加攔截所有的請求,在用excludePathPatterns
* 來排除不需要攔截的請求即可
registry.addInterceptor(checkTypeInterceptor()).addPathPatterns("/customer/**") // 這樣如果瀏覽器端的請求格式符合上述配置,那么就會被攔截到。 就會進入上面自定義攔截器類中的 preHande 方法
} }
至此, 在springboot 中自定義攔截器就完成了。
純手敲,僅供參考 。 可能方法名等有敲錯的地方,望諒解。
版權所歸: 轉載請注明出處!