专栏首页行者常至022.自定义注解

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 条评论
登录 后参与评论

相关文章

  • 继承的父类的request属性为啥 用不了?

    qubianzhong
  • SpringBoot 中 @ConfigurationProperties 配置后 apollo 自动刷新

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    qubianzhong
  • (08)通过和 ServletAPI 耦合的方式获取 WEB 资源

    qubianzhong
  • 定时任务调度池 原

    南郭先生
  • android利用websocket协议与服务器通信

    最近做一个项目,需求中需要服务器主动推送消息到客户端。这样的话一般的http连接就不能使用了。博主问了个朋友,向我推荐websocket协议,特此测试了一下,发...

    砸漏
  • Hadoop学习之网络爬虫+分词+倒排索引实现搜索引擎案例

    本项目实现的是:自己写一个网络爬虫,对搜狐(或者csdn)爬取新闻(博客)标题,然后把这些新闻标题和它的链接地址上传到hdfs多个文件上,一个文件对应一个标题和...

    汤高
  • 解密Dubbo:自己动手编写一个较为完善的RPC框架(两万字干货)

    现在很多企业都在使用Dubbo或者Spring Cloud做企业的微服务架构,其实对于Dubbo最核心的技术就是RPC调用,现在我们就来动手自己编写一个RPC框...

    java进阶架构师
  • mysql读写分离之springboot集成

    由于涉及到事务处理,可能会遇到事务中同时用到读库和写库,可能会有延时造成脏读,所以增加了线程变量设置,来保证一个事务内读写都是同一个库

    一笠风雨任生平
  • spring boot使用注解的方式引入mybatis的SqlSessionDaoSupport

    出现这个问题, 说明一点, 我对spring的注解方式的配置只是知道一个皮毛. 没有深入理解. 有时间要把这部分充充电

    用户7798898
  • 羊皮书APP(Android版)开发系列(十八)Android 侧滑菜单栏实现

    热心的程序员

扫码关注云+社区

领取腾讯云代金券