在我們的項目中和後臺的通信的時候,為了防止別人截獲並篡改信息,於是決定啟用一套自己驗籤規則,那就是將所有屬性的值拼接起來進行SHA256簽名,在這個字符串拼接的時候如果屬性少還好,直接寫一個方法將屬性值拼接起來就好了,但是如果屬性很多的話,並且需要多次不同的數據與後臺進行交互,每次寫個方法拼接太麻煩了,為了造福後來者,使拼接變得簡單,所以用註解進行了優化。
註解是的作用是在類或者方法,屬性等上面打上一個標籤,然後通過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的英文意思是可重複的。顧名思義說明被這個元註解修飾的註解可以同時作用一個對象多次,但是每次作用註解又可以代表不同的含義。
好了,那下面我們說說我們最上面說的簽名的優化,首先定義註解:
<code>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;}/<code>
接著利用反射,根據順序拼接字符串:
<code>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();}/<field>/<code>
好了 我們測試下,先定義個bean:
<code>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; }}/<code>
<code>public static void main(String[] args) { Student student = new Student(); student.setAge(100); student.setName("小明"); student.setSex("男"); student.setAddress("上海"); System.out.println(getValue(student));}/<code>
結果是: 上海男小明
因為地址的sort為0,sex的sort為1,那麼的sort為2
OK 完成
閱讀更多 浩渺煙波 的文章