1. 程式人生 > >java 資料脫敏

java 資料脫敏

所謂資料脫敏是指對某些敏感資訊通過脫敏規則進行資料的變形,實現敏感隱私資料的可靠保護。在涉及客戶安全資料或者一些商業性敏感資料的情況下,在不違反系統規則條件下,對真實資料進行改造並提供測試使用,如身份證號、手機號、卡號、客戶號等個人資訊都需要進行資料脫敏。

  此隨筆是根據其他文章修改後符合自己專案使用的資料脫敏!!

 




以下是根據別的文章修改或者直接拿過來用的程式碼
脫敏enum
/**
 * @Title: SensitiveTypeEnum
 * @Description:
 */
public enum SensitiveTypeEnum {
    /**
     * 中文名
     
*/ CHINESE_NAME, /** * 身份證號 */ ID_CARD, /** * 座機號 */ FIXED_PHONE, /** * 手機號 */ MOBILE_PHONE, /** * 地址 */ ADDRESS, /** * 電子郵件 */ EMAIL, /** * 銀行卡 */ BANK_CARD, /** * 密碼 */ PASSWORD; }

自定義annotation

/**
 * @Title: Desensitized
 * @Description: 敏感資訊註解標記
 */
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desensitized {

    /*脫敏型別(規則)*/
    SensitiveTypeEnum type();

    /*判斷註解是否生效的方法*/
    String isEffictiveMethod() default
""; }

 

utils工具類
public class ObjectUtils {
    /**
     * 用序列化-反序列化方式實現深克隆
     * 缺點:1、被拷貝的物件必須要實現序列化
     *
     * @param obj
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T deepCloneObject(T obj) {
        T t = (T) new Object();
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(obj);
            out.close();
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            t = (T) in.readObject();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return t;
    }



    /**
     * 用序列化-反序列化的方式實現深克隆
     * 缺點:1、當實體中存在介面型別的引數,並且這個介面指向的例項為列舉型別時,會報錯"com.alibaba.fastjson.JSONException: syntax error, expect {, actual string, pos 171, fieldName iLimitKey"
     *
     * @param objSource
     * @return
     */
    public static Object deepCloneByFastJson(Object objSource) {
        String tempJson = JSON.toJSONString(objSource);
        Object clone = JSON.parseObject(tempJson, objSource.getClass());
        return clone;
    }

    /**
     * 深度克隆物件
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Object deepClone(Object objSource) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        if (null == objSource) return null;
        //是否jdk型別、基礎型別、列舉型別
        if (isJDKType(objSource.getClass())
                || objSource.getClass().isPrimitive()
                || objSource instanceof Enum<?>) {
            if ("java.lang.String".equals(objSource.getClass().getName())) {//目前只支援String型別深複製
                return new String((String) objSource);
            } else {
                return objSource;
            }
        }
        // 獲取源物件型別
        Class<?> clazz = objSource.getClass();
        Object objDes = clazz.newInstance();
        // 獲得源物件所有屬性
        Field[] fields = getAllFields(objSource);
        // 迴圈遍歷欄位,獲取欄位對應的屬性值
        for (Field field : fields) {
            field.setAccessible(true);
            if (null == field) continue;
            Object value = field.get(objSource);
            if (null == value) continue;
            Class<?> type = value.getClass();
            if (isStaticFinal(field)) {
                continue;
            }
            try {

                //遍歷集合屬性
                if (type.isArray()) {//對陣列型別的欄位進行遞迴過濾
                    int len = Array.getLength(value);
                    if (len < 1) continue;
                    Class<?> c = value.getClass().getComponentType();
                    Array newArray = (Array) Array.newInstance(c, len);
                    for (int i = 0; i < len; i++) {
                        Object arrayObject = Array.get(value, i);
                        Array.set(newArray, i, deepClone(arrayObject));
                    }
                } else if (value instanceof Collection<?>) {
                    Collection newCollection = (Collection) value.getClass().newInstance();
                    Collection<?> c = (Collection<?>) value;
                    Iterator<?> it = c.iterator();
                    while (it.hasNext()) {
                        Object collectionObj = it.next();
                        newCollection.add(deepClone(collectionObj));
                    }
                    field.set(objDes, newCollection);
                    continue;
                } else if (value instanceof Map<?, ?>) {
                    Map newMap = (Map) value.getClass().newInstance();
                    Map<?, ?> m = (Map<?, ?>) value;
                    Set<?> set = m.entrySet();
                    for (Object o : set) {
                        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                        Object mapVal = entry.getValue();
                        newMap.put(entry.getKey(), deepClone(mapVal));
                    }
                    field.set(objDes, newMap);
                    continue;
                }

                //是否jdk型別或基礎型別
                if (isJDKType(field.get(objSource).getClass())
                        || field.getClass().isPrimitive()
                        || isStaticType(field)
                        || value instanceof Enum<?>) {
                    if ("java.lang.String".equals(value.getClass().getName())) {//目前只支援String型別深複製
                        field.set(objDes, new String((String) value));
                    } else {
                        field.set(objDes, field.get(objSource));
                    }
                    continue;
                }

                //是否列舉
                if (value.getClass().isEnum()) {
                    field.set(objDes, field.get(objSource));
                    continue;
                }

                //是否自定義類
                if (isUserDefinedType(value.getClass())) {
                    field.set(objDes, deepClone(value));
                    continue;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objDes;
    }


    /**
     * 是否靜態變數
     *
     * @param field
     * @return
     */
    private static boolean isStaticType(Field field) {
        return field.getModifiers() == 8 ? true : false;
    }

    private static boolean isStaticFinal(Field field) {
        return Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers());
    }

    /**
     * 是否jdk型別變數
     *
     * @param clazz
     * @return
     * @throws IllegalAccessException
     */
    private static boolean isJDKType(Class clazz) throws IllegalAccessException {
        //Class clazz = field.get(objSource).getClass();
        return StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                || StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                || StringUtils.startsWith(clazz.getName(), "javax.")
                || StringUtils.startsWith(clazz.getName(), "java.");
    }

    /**
     * 是否使用者自定義型別
     *
     * @param clazz
     * @return
     */
    private static boolean isUserDefinedType(Class<?> clazz) {
        return
                clazz.getPackage() != null
                        && !StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                        && !StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                        && !StringUtils.startsWith(clazz.getName(), "javax.")
                        && !StringUtils.startsWith(clazz.getName(), "java.");
    }

    /**
     * 獲取包括父類所有的屬性
     *
     * @param objSource
     * @return
     */
    public static Field[] getAllFields(Object objSource) {
        /*獲得當前類的所有屬性(private、protected、public)*/
        List<Field> fieldList = new ArrayList<Field>();
        Class tempClass = objSource.getClass();
        while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {//當父類為null的時候說明到達了最上層的父類(Object類).
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //得到父類,然後賦給自己
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    /**
     * 深度克隆物件
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Deprecated
    public static Object copy(Object objSource) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {

        if (null == objSource) return null;
        // 獲取源物件型別
        Class<?> clazz = objSource.getClass();
        Object objDes = clazz.newInstance();
        // 獲得源物件所有屬性
        Field[] fields = getAllFields(objSource);
        // 迴圈遍歷欄位,獲取欄位對應的屬性值
        for (Field field : fields) {
            field.setAccessible(true);
            // 如果該欄位是 static + final 修飾
            if (field.getModifiers() >= 24) {
                continue;
            }
            try {
                // 設定欄位可見,即可用get方法獲取屬性值。
                field.set(objDes, field.get(objSource));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objDes;
    }
}
/**
 * @Title: DesensitizedUtils
 * @Description:脫敏工具
 */
public class DesensitizedUtils {

    /**
     * 獲取脫敏json串(遞迴引用會導致java.lang.StackOverflowError)
     *
     * @param javaBean
     * @return
     */
    public static Object getJson(Object javaBean) {
        String json = null;
        if (null != javaBean) {
            try {
                if (javaBean.getClass().isInterface()) return json;
                /* 定義一個計數器,用於避免重複迴圈自定義物件型別的欄位 */
                Set<Integer> referenceCounter = new HashSet<Integer>();

                /* 對實體進行脫敏操作 */
                DesensitizedUtils.replace(ObjectUtils.getAllFields(javaBean), javaBean, referenceCounter);

                /* 清空計數器 */
                referenceCounter.clear();
                referenceCounter = null;
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return javaBean;
    }

    /**
     * 對需要脫敏的欄位進行轉化
     *
     * @param fields
     * @param javaBean
     * @param referenceCounter
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private static void replace(Field[] fields, Object javaBean, Set<Integer> referenceCounter) throws IllegalArgumentException, IllegalAccessException {
        if (null != fields && fields.length > 0) {
            for (Field field : fields) {
                field.setAccessible(true);
                if (null != field && null != javaBean) {
                    Object value = field.get(javaBean);
                    if (null != value) {
                        Class<?> type = value.getClass();
                        //處理子屬性,包括集合中的
                        if (type.isArray()) {//對陣列型別的欄位進行遞迴過濾
                            int len = Array.getLength(value);
                            for (int i = 0; i < len; i++) {
                                Object arrayObject = Array.get(value, i);
                                if (isNotGeneralType(arrayObject.getClass(), arrayObject, referenceCounter)) {
                                    replace(ObjectUtils.getAllFields(arrayObject), arrayObject, referenceCounter);
                                }
                            }
                        } else if (value instanceof Collection<?>) {//對集合型別的欄位進行遞迴過濾
                            Collection<?> c = (Collection<?>) value;
                            Iterator<?> it = c.iterator();
                            while (it.hasNext()) {// TODO: 待優化
                                Object collectionObj = it.next();
                                if (isNotGeneralType(collectionObj.getClass(), collectionObj, referenceCounter)) {
                                    replace(ObjectUtils.getAllFields(collectionObj), collectionObj, referenceCounter);
                                }
                            }
                        } else if (value instanceof Map<?, ?>) {//對Map型別的欄位進行遞迴過濾
                            Map<?, ?> m = (Map<?, ?>) value;
                            Set<?> set = m.entrySet();
                            for (Object o : set) {
                                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                                Object mapVal = entry.getValue();
                                if (isNotGeneralType(mapVal.getClass(), mapVal, referenceCounter)) {
                                    replace(ObjectUtils.getAllFields(mapVal), mapVal, referenceCounter);
                                }
                            }
                        } else if (value instanceof Enum<?>) {
                            continue;
                        }

                        /*除基礎型別、jdk型別的欄位之外,對其他型別的欄位進行遞迴過濾*/
                        else {
                            if (!type.isPrimitive()
                                    && type.getPackage() != null
                                    && !StringUtils.startsWith(type.getPackage().getName(), "javax.")
                                    && !StringUtils.startsWith(type.getPackage().getName(), "java.")
                                    && !StringUtils.startsWith(field.getType().getName(), "javax.")
                                    && !StringUtils.startsWith(field.getName(), "java.")
                                    && referenceCounter.add(value.hashCode())) {
                                replace(ObjectUtils.getAllFields(value), value, referenceCounter);
                            }
                        }
                    }
                    //脫敏操作
                    setNewValueForField(javaBean, field, value);

                }
            }
        }
    }

    /**
     * 排除基礎型別、jdk型別、列舉型別的欄位
     *
     * @param clazz
     * @param value
     * @param referenceCounter
     * @return
     */
    private static boolean isNotGeneralType(Class<?> clazz, Object value, Set<Integer> referenceCounter) {
        return !clazz.isPrimitive()
                && clazz.getPackage() != null
                && !clazz.isEnum()
                && !StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                && !StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                && !StringUtils.startsWith(clazz.getName(), "javax.")
                && !StringUtils.startsWith(clazz.getName(), "java.")
                && referenceCounter.add(value.hashCode());
    }

    /**
     * 脫敏操作(按照規則轉化需要脫敏的欄位並設定新值)
     * 目前只支援String型別的欄位,如需要其他型別如BigDecimal、Date等型別,可以新增
     *
     * @param javaBean
     * @param field
     * @param value
     * @throws IllegalAccessException
     */
    public static void setNewValueForField(Object javaBean, Field field, Object value) throws IllegalAccessException {        //處理自身的屬性
        Desensitized annotation = field.getAnnotation(Desensitized.class);
        if (field.getType().equals(String.class) && null != annotation && executeIsEffictiveMethod(javaBean, annotation)) {
            String valueStr = (String) value;
            if (StringUtils.isNotBlank(valueStr)) {
                switch (annotation.type()) {
                    case CHINESE_NAME: {
                        field.set(javaBean, DesensitizedUtils.chineseName(valueStr));
                        break;
                    }
                    case ID_CARD: {
                        field.set(javaBean, DesensitizedUtils.idCardNum(valueStr));
                        break;
                    }
                    case FIXED_PHONE: {
                        field.set(javaBean, DesensitizedUtils.fixedPhone(valueStr));

                        break;
                    }
                    case MOBILE_PHONE: {
                        field.set(javaBean, DesensitizedUtils.mobilePhone(valueStr));
                        break;
                    }
                    case ADDRESS: {
                        field.set(javaBean, DesensitizedUtils.address(valueStr, 8));
                        break;
                    }
                    case EMAIL: {
                        field.set(javaBean, DesensitizedUtils.email(valueStr));
                        break;
                    }
                    case BANK_CARD: {
                        field.set(javaBean, DesensitizedUtils.bankCard(valueStr));
                        break;
                    }
                    case PASSWORD: {
                        field.set(javaBean, DesensitizedUtils.password(valueStr));
                        break;
                    }
                }
            }
        }
    }

    /**
     * 執行某個物件中指定的方法
     *
     * @param javaBean     物件
     * @param desensitized
     * @return
     */
    private static boolean executeIsEffictiveMethod(Object javaBean, Desensitized desensitized) {
        boolean isAnnotationEffictive = true;//註解預設生效
        if (desensitized != null) {
            String isEffictiveMethod = desensitized.isEffictiveMethod();
            if (isNotEmpty(isEffictiveMethod)) {
                try {
                    Method method = javaBean.getClass().getMethod(isEffictiveMethod);
                    method.setAccessible(true);
                    isAnnotationEffictive = (Boolean) method.invoke(javaBean);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return isAnnotationEffictive;
    }

    private static boolean isNotEmpty(String str) {
        return str != null && !"".equals(str);
    }

    private static boolean isEmpty(String str) {
        return !isNotEmpty(str);
    }

    /**
     * 【中文姓名】只顯示第一個漢字,其他隱藏為2個星號,比如:李**
     *
     * @param fullName
     * @return
     */
    public static String chineseName(String fullName) {
        if (StringUtils.isBlank(fullName)) {
            return "";
        }
        String name = StringUtils.left(fullName, 1);
        return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
    }

    /**
     * 【身份證號】顯示最後四位,其他隱藏。共計18位或者15位,比如:*************1234
     *
     * @param id
     * @return
     */
    public static String idCardNum(String id) {
        if (StringUtils.isBlank(id)) {
            return "";
        }
        String num = StringUtils.right(id, 4);
        return StringUtils.leftPad(num, StringUtils.length(id), "*");
    }

    /**
     * 【固定電話 後四位,其他隱藏,比如1234
     *
     * @param num
     * @return
     */
    public static String fixedPhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
    }

    /**
     * 【手機號碼】前三位,後四位,其他隱藏,比如135****6810
     *
     * @param num
     * @return
     */
    public static String mobilePhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
    }

    /**
     * 【地址】只顯示到地區,不顯示詳細地址,比如:北京市海淀區****
     *
     * @param address
     * @param sensitiveSize 敏感資訊長度
     * @return
     */
    public static String address(String address, int sensitiveSize) {
        if (StringUtils.isBlank(address)) {
            return "";
        }
        int length = StringUtils.length(address);
        return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
    }

    /**
     * 【電子郵箱 郵箱字首僅顯示第一個字母,字首其他隱藏,用星號代替,@及後面的地址顯示,比如:d**@126.com>
     *
     * @param email
     * @return
     */
    public static String email(String email) {
        if (StringUtils.isBlank(email)) {
            return "";
        }
        int index = StringUtils.indexOf(email, "@");
        if (index <= 1)
            return email;
        else
            return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
    }

    /**
     * 【銀行卡號】前六位,後四位,其他用星號隱藏每位1個星號,比如:6222600**********1234>
     *
     * @param cardNum
     * @return
     */
    public static String bankCard(String cardNum) {
        if (StringUtils.isBlank(cardNum)) {
            return "";
        }
        return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
    }

    /**
     * 【密碼】密碼的全部字元都用*代替,比如:******
     *
     * @param password
     * @return
     */
    public static String password(String password) {
        if (StringUtils.isBlank(password)) {
            return "";
        }
        String pwd = StringUtils.left(password, 0);
        return StringUtils.rightPad(pwd, StringUtils.length(password), "*");
    }

    /**
     * 遍歷page對資料脫敏
     * @param pageContent
     * @param page
     * @param size
     * @return
     */
    public static <T> Page desensitizedPage(Page<T> pageContent, int page, int size,Class tClass) {
        //獲取page的內容
        List<T> content = pageContent.getContent();
        if (content == null || content.size() <= 0) {
            return pageContent;
        }
        //資料脫敏
        List list = desensitizedList(content,tClass);
        return new PageImpl(list, new PageRequest(page, size), pageContent.getTotalElements());
    }

    /**
     * 遍歷List脫敏資料
     * @param content
     * @return
     */
    public static <T> List desensitizedList(List<T> content,Class tClass){
        if (content == null || content.size() <= 0) {
            return content;
        }
        List list = new ArrayList<>();
        for (T t : content) {
            list.add(desensitizedObject(t,tClass));
        }
        return list;
    }
    /**
     * 物件脫敏
     * @param content
     * @return
     */
    public static <T> Object desensitizedObject(T content,Class tClass){
      if(content != null){
          try {
              Object o = tClass.newInstance();
              BeanCopyUtil.copyPropertiesIgnoreNull(content,o);
              return getJson(o);
          } catch (InstantiationException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          }
      }
      return null;
    }
}

最後面的幾個方法是我根據泛型和反射建立的對page、list 、實體的脫敏方法。

 

 以下是我的程式碼

  後端實體

import org.hibernate.annotations.GenericGenerator;

import org.springframework.format.annotation.DateTimeFormat;

import javax.persistence.*;
import java.util.Date;

/**
 *  黑名單
 * @ClassName: BlackList
 * @author: guoyuzai
 * @version 0.98
 */
@Entity
@Table(name = "black_list", catalog = "zhsupervision") public class BlackList { /** 主鍵ID,UUID **/ @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid") @Column(nullable = false, length = 32) private String id; /** * 姓名 */ private String name;  /** * 身份證 */ private String idCard; /** * 處罰日期 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private String punishDate;  /** * 處罰事由 */ private String punishCause; /** * 邏輯刪除識別符號 0:正常 1:刪除不顯示 */ private String delFlag; /** * 狀態 */ private String status; /** * 備註 */ private String remark; /** * A新增 U更新D刪除 */ private String identifier; /** * 建立時間 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; /** * 證件型別 */ private String cardType; /** * 建立人 */ private String createUser; /** * 修改人 */ private String updateUser; /** * 更新時間 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateDate; /** * 附件 */ private String attachement; public String getAttachement() { return attachement; } public void setAttachement(String attachement) { this.attachement = attachement; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }   public String getPunishDate() { return punishDate; } public void setPunishDate(String punishDate) { this.punishDate = punishDate; }  public String getPunishCause() { return punishCause; } public void setPunishCause(String punishCause) { this.punishCause = punishCause; } public String getDelFlag() { return delFlag; } public void setDelFlag(String delFlag) { this.delFlag = delFlag; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public String getIdentifier() { return identifier; } public void setIdentifier(String identifier) { this.identifier = identifier; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getCardType() { return cardType; } public void setCardType(String cardType) { this.cardType = cardType; } public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } public String getUpdateUser() { return updateUser; } public void setUpdateUser(String updateUser) { this.updateUser = updateUser; } public Date getUpdateDate() { return updateDate; } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } @Override public String toString() { return "BlackList{" + "name='" + name + '\'' + ", IdCard='" + idCard + '\'' + ", punishDate='" + punishDate + '\'' + ", orgName='" + orgName + '\'' + ", punishCause='" + punishCause + '\'' + ", delFlag='" + delFlag + '\'' + ", status='" + status + '\'' + ", remark='" + remark + '\'' + ", identifier='" + identifier + '\'' + ", createTime=" + createTime + ", cardType='" + cardType + '\'' + ", createUser='" + createUser + '\'' + ", updateUser='" + updateUser + '\'' + ", updateDate=" + updateDate + ", id='" + id + '\'' + '}'; } }

 返回結果給前端的VO

import com.honebay.spv.core.annotation.Desensitized;
import com.honebay.spv.core.enums.SensitiveTypeEnum;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

public class BlackListVO {
    private String id; /** * 姓名 */ private String name;  /** * 身份證 */ @Desensitized(type = SensitiveTypeEnum.ID_CARD) private String idCard; /** * 處罰日期 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private String punishDate;  /** * 處罰事由 */ private String punishCause; /** * 邏輯刪除識別符號 0:正常 1:刪除不顯示 */ private String delFlag; /** * 狀態 */ private String status; /** * 備註 */ private String remark; /** * A新增 U更新D刪除 */ private String identifier; /** * 建立時間 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; /** * 證件型別 */ private String cardType; /** * 建立人 */ private String createUser; /** * 修改人 */ private String updateUser; /** * 更新時間 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateDate; /** * 附件 */ private String attachement; public String getAttachement() { return attachement; } public void setAttachement(String attachement) { this.attachement = attachement; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }  public String getPunishDate() { return punishDate; } public void setPunishDate(String punishDate) { this.punishDate = punishDate; }  public String getPunishCause() { return punishCause; } public void setPunishCause(String punishCause) { this.punishCause = punishCause; } public String getDelFlag() { return delFlag; } public void setDelFlag(String delFlag) { this.delFlag = delFlag; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public String getIdentifier() { return identifier; } public void setIdentifier(String identifier) { this.identifier = identifier; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getCardType() { return cardType; } public void setCardType(String cardType) { this.cardType = cardType; } public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } public String getUpdateUser() { return updateUser; } public void setUpdateUser(String updateUser) { this.updateUser = updateUser; } public Date getUpdateDate() { return updateDate; } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } }

上面的身份證我添加了自定義的註解,在脫敏的時候會找到這個註解然後獲取屬性的值進行脫敏

 

Service

import com.honebay.spv.core.service.BaseService;
import com.honebay.spv.org.entity.BlackList;
import com.honebay.spv.org.entity.EmployeesInfor;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * @author guoyuzai
 * @version 0.98
 */
public interface BlackListService  extends BaseService<BlackList,String> {
    /**
     * 獲取分頁列表
     *
     * @param page
     * @param size
     * @return
     */
    public Page<BlackList> getBlackListPage(BlackList info, int page, int size);

}

 

Impl

@Service
public class BlackListServiceImpl  extends BaseServiceImpl<BlackList, String> implements BlackListService {
    private final Logger log = LoggerFactory.getLogger(BlackListServiceImpl.class);
  
 @SuppressWarnings("unchecked")
    @Override
    public Page<BlackList> getBlackListPage(BlackList blackList, int page, int size) {
        Page<BlackList> result = null; Specification<BlackList> specialized = new Specification<BlackList>() { @Override public Predicate toPredicate(Root<BlackList> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { List<Predicate> predicates = new ArrayList<Predicate>(); if(StringUtils.isNotBlank(blackList.getIdCard())){ Predicate idCard = criteriaBuilder.equal(root.get("idCard"), blackList.getIdCard()); predicates.add(idCard); } if(StringUtils.isNotBlank(blackList.getName())){ Predicate name = criteriaBuilder.equal(root.get("name"), blackList.getName()); predicates.add(name); } //獲取沒刪除的資訊 Predicate flag = criteriaBuilder.equal(root.get("delFlag"), "0"); predicates.add(flag); return criteriaBuilder.and(predicates.toArray(new Predicate[] {})); } }; /** * 按照建立時間排序 */ List<Sort.Order> orderList = new ArrayList<Sort.Order>(); orderList.add(new Sort.Order(Sort.Direction.ASC, "createTime")); result = blackListRepository.findAll(specialized,new PageRequest(page, size,new Sort(orderList))); return result; } }

Repository
public interface BlackListRepository extends BaseRepository<BlackList, String>, JpaSpecificationExecutor {
 
}

 

Controller

/**
 *  黑名單
 * @ClassName: BlackList
 * @author: guoyuzai
 * @version 0.98
 */
@RestController
public class BlackListController {
    @Autowired
    private BlackListService blackListService;

 /**
     *
     * @Title: infoQueryPortalList
     * @Description: 分頁查詢
     * @param: @return
     * @return: JsonResponseN
     * @throws
     */
    @SuppressWarnings("rawtypes")
    @RequestMapping(value = "/getBlackListPage") @ResponseBody public JsonResponseExt getBlackListPage(BlackList info, @RequestParam("page")String page, @RequestParam("limit") String limit) { Page<BlackList> pageData =blackListService.getBlackListPage(info,Integer.parseInt(page) - 1,Integer.parseInt(limit));
    
     JsonResponseExt je = JsonResponseExt.successPage(DesensitizedUtils.desensitizedPage(pageData,Integer.parseInt(page) - 1,Integer.parseInt(limit),BlackListVO.class));
     return je; 
  }
}
JsonResponseExt je = JsonResponseExt.successPage()這個方法是自己封裝給前端的返回物件(這裡不提供)
根據工具類的 DesensitizedUtils.desensitizedPage()方法 傳入page物件、page、limit和傳回前端的VO的Class物件就可以進行脫敏了