java 自定义注解,并使用示例

场景: 对需要校验 手机验证码和短信验证码的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 中自定义拦截器就完成了。

纯手敲,仅供参考 。 可能方法名等有敲错的地方,望谅解。

版权所归: 转载请注明出处!