java反射-變量鍵值對排序

1、問題描述

因爲要做API接口安全設計方案(已實現)(https://ruanjianlaowang.blog.csdn.net/article/details/118806853 ),牽扯到前後端加密簽名,從前端獲取json數據後,首先需要對json數據按照首字母進行排序,再按照key1value1key2value2進行加密(json數據從前端到後端,順序會亂),結合網上的方案,使用java的反射機制,對鍵值對按照首字母排序加密。

2、解決方案

2.1 方案

(1)使用@RequestBody將json轉換成對象;

(2)使用反射機制獲取鍵值對,需要使用treemap,treemap會按照首字母順序排序插入;

(3)從map中按順序遍歷出鍵值對;

1和3就簡單說一下,重點是2。

2.2 上代碼及說明

2.2.1 實體類ReflesTes1與ReflesBase

public class ReflesTest1 extends ReflesBase{
    private String aLaowang;
    private String bLaowang;
    private String cLaowang;

    public String getaLaowang() {
        return aLaowang;
    }

    public void setaLaowang(String aLaowang) {
        this.aLaowang = aLaowang;
    }

    public String getbLaowang() {
        return bLaowang;
    }

    public void setbLaowang(String bLaowang) {
        this.bLaowang = bLaowang;
    }

    public String getcLaowang() {
        return cLaowang;
    }

    public void setcLaowang(String cLaowang) {
        this.cLaowang = cLaowang;
    }
}

(2)ReflesBase類及說明

public class ReflesBase {
    public String token;
    public String sign;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }
}

簡要說明

這裏有個業務場景,就是所有從前端接受到的DTO都要有token/sign等字段,以便進行鑑權驗證,需要創建個基礎類來繼承(有需要),爲什麼基類中變量是public,接下來會介紹。

2.2.2 核心方法類ReflexUtils

import java.lang.reflect.Field;
import java.util.Map;
import java.util.TreeMap;

public class ReflexUtils {
    public static Map<String, Object> getKeyAndValue(Object obj) {
        Map<String, Object> map = new TreeMap<String, Object>();
        // 得到類對象
        Class userCla = (Class) obj.getClass();
        /* 得到類中的所有屬性集合 */
        Field[] fs = userCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); // 設置些屬性是可以訪問的
            Object val = new Object();
            try {
                val = f.get(obj);
                // 得到此屬性的值
                map.put(f.getName(), val);// 設置鍵值
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }

        Field[] fs2 = userCla.getFields();
        for (int i = 0; i < fs2.length; i++) {
            Field f = fs2[i];
            f.setAccessible(true); // 設置些屬性是可以訪問的
            Object val = new Object();
            try {
                val = f.get(obj);
                // 得到此屬性的值
                map.put(f.getName(), val);// 設置鍵值
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
        return map;
    }

    public static void main(String[] args) {
        ReflesTest1 test1 = new ReflesTest1();
        test1.setaLaowang("aaaa");
        test1.setbLaowang("bbbb");
        test1.setcLaowang("cccc");

        test1.setToken("fdaflkjdskfj ");

          Map<String, Object> map = getKeyAndValue(test1);
        System.out.println(map);

        for (String s : map.keySet()) {
            String value =  (String) map.get(s);
            if (value != null) {
                System.out.println(s+value);
            }

        }
    }
}

簡要說明:

(1)從代碼看,其實也很簡單,就是利用反射機制進行變量的獲取。

(2)利用用到的是treemap,該map子類可以實現按字典排序(按首字母順序),也可以自定義。

(TreeMap 默認排序規則:按照key的字典順序來排序(升序),當然,也可以自定義排序規則:要實現Comparator接口。)

(3) Field[] fs = userCla.getDeclaredFields();方法中同時使用了getDeclaredFields和getFields方法。

getDeclaredFields():獲得某個類的所有聲明的字段,即包括public、private和proteced,但是不包括父類的申明字段。

getFields():獲得某個類的所有的公共(public)的字段,包括父類中的字段;

組合起來就滿足業務場景了。

(4)map遍歷,合併keyvalue

2.3 效果


更多信息請關注公衆號:「軟件老王」,關注不迷路,軟件老王和他的IT朋友們,分享一些他們的技術見解和生活故事。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章