专业的JAVA编程教程与资源

网站首页 > java教程 正文

利用Java注解的简单封装,进行的一次优化

temp10 2024-11-13 12:42:24 java教程 11 ℃ 0 评论

头条号:浩渺烟波

在我们的项目中和后台的通信的时候,为了防止别人截获并篡改信息,于是决定启用一套自己验签规则,那就是将所有属性的值拼接起来进行SHA256签名,在这个字符串拼接的时候如果属性少还好,直接写一个方法将属性值拼接起来就好了,但是如果属性很多的话,并且需要多次不同的数据与后台进行交互,每次写个方法拼接太麻烦了,为了造福后来者,使拼接变得简单,所以用注解进行了优化。

利用Java注解的简单封装,进行的一次优化

注解是的作用是在类或者方法,属性等上面打上一个标签,然后通过java的反射机制动态的对打上标签的内容进行解析和处理。

在Java中已经内置了几个注解,我们平常可能有看到:

@Override 用在方法上,表示要覆盖父类中的方法

@Deprecated 表示被弃用的代码,如果使用了被他标注的方法会提示警告

@SuppressWarnings,关闭不当编译器警告信息。

我们可以使用元注解自定义自己的注解,首先需要明白什么是元注解,元注解是java中用于表示注解的注解,java中元注解分为:@Retention、 @Target、 @Document、 @Inherited和@Repeatable

@Retention

标示的是注解存留的阶段,有一个枚举类:RetentionPolicy.SOURCE 仅存于源码中RetentionPolicy.CLASS 存在于字节码中,但是在运行时无法获得RetentionPolicy.RUNTIME 在运行是可以通过反射获得,前面也说过注解的目的是通过反射机制动态的获取值,那么我们最常用的那肯定就是这个了

@Target

目标的意思,是说我们制定的注解是用于什么地方,比如方法,属性,还是类等,同样有一个枚举:ElementType.TYPE 表示可以作用于类,方法,枚举 ElementType.FIELD 作用于属性 ElementType.METHOD 作用于方法。。。还有其他的就不说了,反正也不常用,用的时候再看吧

@Documented

它的意思是文档,作用是能将注解包含的Javadoc中去,其实要是用工具javadoc生成文档的时候用,不需要搞什么文档的话,加不加没啥区别

@Inherited

继承的意思,就是子类如果没有其他别的注解的话,可以继承父类标注的注解

@Repeatable

Repeatable的英文意思是可重复的。顾名思义说明被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。

好了,那下面我们说说我们最上面说的签名的优化,首先定义注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ValidateValue {

    //是否参与验证
    boolean isValidate() default false;
    //排序值
    int sortValue() default 0;
}

接着利用反射,根据顺序拼接字符串:

public static String getValue(Object object){
    Class aClass = object.getClass();

    //获取所有声明的属性
    Field[] declaredFields = aClass.getDeclaredFields();

    //过滤出所有带有注解的属性
    List<Field> fields = new ArrayList<>();
    for (Field field : declaredFields){
        if(field.isAnnotationPresent(ValidateValue.class)){
            ValidateValue annotation = field.getAnnotation(ValidateValue.class);
            if(annotation.isValidate()){
                fields.add(field);
            }
        }
    }
    //根据定义的顺序排序
    Collections.sort(fields, (o1, o2) -> {
        ValidateValue annotation1 = o1.getAnnotation(ValidateValue.class);
        ValidateValue annotation2 = o2.getAnnotation(ValidateValue.class);
        return annotation1.sortValue() - annotation2.sortValue();
    });

    StringBuilder sb = new StringBuilder();
    for (Field field : fields){
        field.setAccessible(true);
        try {
            //获取属性的值,因为都是基本类型,并且拼的是字符串,所以不用判断获得值是什么类型,直接用object即可
            Object value = field.get(object);
            sb.append(value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    return sb.toString();
}

好了 我们测试下,先定义个bean:

public class Student {

    @ValidateValue(isValidate = true, sortValue = 0)
    private String address;
    @ValidateValue(isValidate = true, sortValue = 2)
    private String name;
    @ValidateValue(isValidate = true, sortValue = 1)
    private String sex;


    private int age;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
public static void main(String[] args) {
    Student student = new Student();
    student.setAge(100);
    student.setName("小明");
    student.setSex("男");
    student.setAddress("上海");
    System.out.println(getValue(student));
}

结果是: 上海男小明

因为地址的sort为0,sex的sort为1,那么的sort为2

OK 完成


Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表