022.自定义注解

版权声明:本文为博主原创文章,允许转载,请标明出处。

注解是Jdk1.5新增新技术。很多框架为了简化代码,都会提供有些注解。 可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。


定义

Java文件中叫做Annotation,用@interface表示。


元注解

@interface上面按需要注解上一些东西, 包括 @Retention@Target@Document@Inherited四种。


注解的保留策略

// 注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.SOURCE)   
// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.CLASS)     
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)  

注解的作用目标

// 接口、类、枚举、注解
@Target(ElementType.TYPE)                      
// 字段、枚举的常量
@Target(ElementType.FIELD)                     
// 方法
@Target(ElementType.METHOD)                 
 // 方法参数
@Target(ElementType.PARAMETER)           
// 构造函数
@Target(ElementType.CONSTRUCTOR)       
// 局部变量
@Target(ElementType.LOCAL_VARIABLE)   
 // 注解
@Target(ElementType.ANNOTATION_TYPE)
// 包
@Target(ElementType.PACKAGE)               

注解包含在javadoc中

@Documented

注解可以被继承

@Inherited

通过注解进行校验

demo1
package cn.qbz.thread.day1121;

import java.lang.annotation.*;

@Documented
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserAnnotation {
    int min() default 0;

    int max() default 120;

    boolean isNotNull() default true;
}
package cn.qbz.thread.day1121;

public class User {
    @UserAnnotation(isNotNull = true)
    private String name;
    @UserAnnotation(min = 18, max = 50)
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
package cn.qbz.thread.day1121;

import java.lang.reflect.Field;

public class UserCheck {

    public static boolean check(User user) throws Exception {

        if (user == null) {
            System.out.println("user is null.");
            return false;
        }

        Field[] fields = User.class.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            UserAnnotation userAnnotation = field.getAnnotation(UserAnnotation.class);
            String name = field.getName();
            Object value = field.get(user);
            int min = userAnnotation.min();
            int max = userAnnotation.max();
            boolean isNull = userAnnotation.isNotNull();

            if (isNull) {
                if (value == null) {
                    throw new Exception(name + " is null.");
                }
                int length = value.toString().length();
                if (length < min) {
                    throw new Exception(name + " length min is " + min);
                }
                if (length > max) {
                    throw new Exception(name + " length max is " + max);
                }
            }
        }
        return true;
    }
}
package cn.qbz.thread.day1121;

public class AnnotationTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setAge(3);
        user.setName("sdfaf");

        UserCheck.check(user);
    }

}
demo2
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
package com.antzb.chaos.annotations;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.antzb.chaos.constant.ConstantKey;
import com.antzb.chaos.utils.CommonUtil;
import org.springframework.util.StringUtils;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: qubianzhong
 * @Date: 18-4-12 下午1:38
 */
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ProjectUpdateTemplate.OrderByValidator.class)
public @interface ProjectUpdateTemplate {

    String message() default "[任务步骤格式有误!]";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    class OrderByValidator implements ConstraintValidator<ProjectUpdateTemplate, JSONObject> {
        @Override
        public void initialize(ProjectUpdateTemplate projectUpdateTemplate) {
        }

        @Override
        public boolean isValid(JSONObject template, ConstraintValidatorContext context) {
            context.disableDefaultConstraintViolation();
            boolean isRight = true;
            String errorMessage = "";
            if (template != null && template.size() > 0) {
                for (String key : template.keySet()) {
                    JSONObject element = template.getJSONObject(key);
                    if (element == null) {
                        isRight = false;
                        errorMessage = "任务步骤序号异常!必须为:1,2,3,4的字符串.";
                        break;
                    }
                }
            } else {
                isRight = false;
                errorMessage = "任务步骤不能为空";
            }
            context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
            return isRight;
        }
    }
}
public class ProjectUpdateTemplateReq {
    @NotNull
    private Integer projectInfoId;
    @ProjectUpdateTemplate
    private JSONObject stepTemplate;

    public Integer getProjectInfoId() {
        return projectInfoId;
    }

    public void setProjectInfoId(Integer projectInfoId) {
        this.projectInfoId = projectInfoId;
    }

    public JSONObject getStepTemplate() {
        return stepTemplate;
    }

    public void setStepTemplate(JSONObject stepTemplate) {
        this.stepTemplate = stepTemplate;
    }
}
    @PostMapping
    public ResultMessage updateProjectOfTemplate(@Valid @RequestBody ProjectUpdateTemplateReq projectUpdateTemplateReq) {
     
     }
demo3
package com.rongyi.smart.web.checker.annotation;

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 CheckLogin {
}
package com.antzb.chaos.www.aspect;

import com.antzb.chaos.annotations.CheckLogin;
import com.antzb.chaos.constant.ConstantKey;
import com.antzb.chaos.www.util.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;

/**
 * @Author: qubianzhong
 * @Date: 18-5-4 上午10:01
 */
@Component
@Aspect
public class CheckLoginAspect {
    @Pointcut("@annotation(checkLogin)")
    public void checkLoginPointCut(CheckLogin checkLogin) {
    }

    @Before("checkLoginPointCut(checkLogin)")
    public void doBefore(JoinPoint joinPoint, CheckLogin checkLogin) {
        String message = "请扫码登录后重新访问!";
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();

        request.setAttribute(ConstantKey.HTTPSERVLETREQUEST_ATTRIBUTES_CHECKLOGIN, true);

        String token = request.getHeader(ConstantKey.JWT_HEADER_KEY);
        if (token == null) {
            throw new SecurityException(message);
        }
        Claims claims = JwtTokenUtil.getClaimsFromToken(token.replace(ConstantKey.JWT_TOKENHEAD_KEY, ""));
        if (claims == null) {
            throw new SecurityException(message);
        }
        Object userName = claims.get(JwtTokenUtil.CLAIM_KEY_USERNAME);
        Object userId = claims.get(JwtTokenUtil.CLAIM_KEY_USERID);

        Timestamp expirationTime = new Timestamp(claims.getExpiration().getTime());
        if (userId == null
                || userName == null
                || expirationTime == null
                || expirationTime.before(new Timestamp(System.currentTimeMillis()))) {
            throw new SecurityException(message);
        }
    }

    @After("checkLoginPointCut(checkLogin)")
    public void doAfter(CheckLogin checkLogin) {
    }
}
    @GetMapping("/task/list")
    @CheckLogin
    public ResultMessage queryProjectTaskList() {
        ResultMessage resultMessage = new ResultMessage();
        //......
        return resultMessage;
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员宝库

Java 8 时间 API 快速入门

Java 8 出来很久了,各位也可能已经在用了,不过其中新的时间日期 API 可能很少人用,甚至不知道怎么上手。本文快速介绍一下其中的主要的类的概念和用法。 一...

3285
来自专栏行者常至

java 自定义注解之ElementType.PARAMETER

1862
来自专栏码匠的流水账

聊聊storm worker的executor与task

storm-2.0.0/storm-client/src/jvm/org/apache/storm/daemon/worker/Worker.java

1012
来自专栏数据结构与算法

BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)

1143
来自专栏Netkiller

Struts Ajax Json

Netkiller Java 手札 Java, Servlet, JavaBean ... 5.4. Ajax + JSON struts.xml 中加入 ...

2663
来自专栏编码小白

ofbiz 服务引擎(一) controller中服务的调用解析

首先根据handler-controller.xml文件中对应handler文件,然后运行RequestHandler中的runEvent方法,方法如下: /*...

3724
来自专栏函数式编程语言及工具

Akka(11): 分布式运算:集群-均衡负载

在上篇讨论里我们主要介绍了Akka-Cluster的基本原理。同时我们也确认了几个使用Akka-Cluster的重点:首先,Akka-Cluster集群构建与...

5307
来自专栏函数式编程语言及工具

Akka(23): Stream:自定义流构件功能-Custom defined stream processing stages

    从总体上看:akka-stream是由数据源头Source,流通节点Flow和数据流终点Sink三个框架性的流构件(stream components)...

4398
来自专栏JAVA技术站

SpringMVC 请求参数,返回值格式打印,遍于开发调试

972
来自专栏技术专栏

自定义注解实现参数验证与业务代码解耦

2682

扫码关注云+社区

领取腾讯云代金券