1. 程式人生 > 其它 >AOP自定義註解實現指定欄位加密脫敏

AOP自定義註解實現指定欄位加密脫敏

目錄

一、自定義註解

解密自定義註解略

1.方法上註解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CryptMethod {
}

2.欄位上註解

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CryptData {
}

自定義註解解析

  • 1.@Documented:註解型別資訊會被 JavaDoc 工具提取到幫助文件中。
  • 2.@Target:指定一個註解的使用範圍,value 是 java.lang.annotation.ElementType 列舉型別的陣列
名稱 說明
CONSTRUCTOR 用於構造方法
FIELD 用於成員變數(包括列舉常量)
LOCAL_VARIABLE 用於區域性變數
METHOD 用於方法
PACKAGE 用於包
PARAMETER 用於型別引數(JDK 1.8新增)
TYPE 用於類、介面(包括註解型別)或 enum 宣告
  • 3.@Retention:用於描述註解的生命週期,也就是該註解被保留的時間長短 value 是 java.lang.annotation.RetentionPolicy列舉型別的陣列
名稱 說明 使用
SOURCE 在原始檔中有效 檢查性的操作
CLASS 在 class 檔案中有效 編譯時進行預處理操作
RUNTIME 在執行時有效 執行時去動態獲取註解資訊

SOURCE < CLASS < RUNTIME

  • 4.@Inherited:使用被該註解修飾的註解的Class類,其子類擁有該註解
  • 5.@Repeatable:在需要對同一種註解多次使用時,使用此註解修飾
  • 6.@Order:優先順序,Ordered列舉預設為LOWEST_PRECEDENCE還有HIGHEST_PRECEDENCE

二、構造AOP邏輯

@Aspect
@Component
@Log4j2
public class CryptAop {
    @Pointcut("@annotation(com.example.demo.annotation.crypt.CryptMethod)")
    public void cryptPointCut(){
    }

    @Pointcut("@annotation(com.example.demo.annotation.crypt.EnCryptMethod)")
    public void encryptPointCut(){
    }

    @Around("cryptPointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object responseObj = null;
        try {
            responseObj = joinPoint.proceed();
            Field[] fields = responseObj.getClass().getDeclaredFields();
            log.info(fields.length);
            for (Field field : fields) {
                log.info(field.getName());
                if (field.isAnnotationPresent(CryptData.class)){
                    if (!field.isAccessible()){
                        field.setAccessible(true);
                    }
                    Object o = field.get(responseObj);
                    System.out.println("獲取的欄位值"+ JSONObject.toJSONString(o));
                    field.set(responseObj, "加密啦");
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return responseObj;
    }

    @Around("encryptPointCut()")
    public Object encrypt(ProceedingJoinPoint joinPoint){
        Object responseObj = null;
        try {
            responseObj = joinPoint.proceed();
            Field[] fields = responseObj.getClass().getDeclaredFields();
            log.info(fields.length);
            for (Field field : fields) {
                log.info(field.getName());
                if (field.isAnnotationPresent(EnCryptData.class)){
                    if (!field.isAccessible()){
                        field.setAccessible(true);
                    }
                    Object o = field.get(responseObj);
                    System.out.println("獲取的欄位值"+ JSONObject.toJSONString(o));
                    field.set(responseObj, "解密啦");
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return responseObj;
    }
}

三、呼叫方法

@Service
public class PersonServiceImpl implements PersonService {
    @Override
    @CryptMethod
    public Person setNewPerson() {
        Person person = new Person();
        person.setPhoneNumber("110");
        return person;
    }

    @Override
    @EnCryptMethod
    public Person getPerson() {
        Person person = new Person();
        person.setPhoneNumber("110");
        return person;
    }
}

四、實體類

@Data
public class Person implements Serializable {
    private static final long serialVersionUID = 6496689746718741955L;
    //id
    private Integer id;
    //姓名
    private String name;
    //手機號
    @CryptData
    @EnCryptData
    private String phoneNumber;
}