1.创建自定义注解:
java
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptDecrypt {
}
2.创建加解密工具类:
java
public class EncryptionUtils {
// 加密方法
public static String encrypt(String data) {
// 实现加密逻辑
// ...
return encryptedData;
}
// 解密方法
public static String decrypt(String encryptedData) {
// 实现解密逻辑
// ...
return decryptedData;
}
}
3.创建切面类:
java
@Aspect
@Component
public class EncryptionAspect {
@Around("execution(* com.example.*.*(..)) && (@annotation(com.example.EncryptDecrypt) || @args(com.example.EncryptDecrypt))")
public Object encryptDecryptMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法参数
Object[] args = joinPoint.getArgs();
// 遍历参数,对带有 EncryptDecrypt 注解的参数进行加解密操作
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg != null) {
if (arg instanceof String) {
if (arg.getClass().isAnnotationPresent(EncryptDecrypt.class)) {
String encryptedData = (String) arg;
String decryptedData = EncryptionUtils.decrypt(encryptedData);
args[i] = decryptedData;
}
} else {
Field[] fields = arg.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(EncryptDecrypt.class)) {
field.setAccessible(true);
Object fieldValue = field.get(arg);
if (fieldValue instanceof String) {
String encryptedData = (String) fieldValue;
String decryptedData = EncryptionUtils.decrypt(encryptedData);
field.set(arg, decryptedData);
}
}
}
}
}
}
// 执行原方法
Object result = joinPoint.proceed(args);
// 对返回值进行加密操作(可根据需求进行操作)
return result;
}
}
4.参数解释
java
@Target({ElementType.FIELD, ElementType.PARAMETER}) 是一个注解的元注解,用于指定注解可以应用的目标元素类型。在这个例子中,@Target 注解表明注解 EncryptDecrypt 可以应用于字段(Field)和参数(Parameter)上。
ElementType.FIELD 表示注解可以应用于字段上,即类的成员变量。
ElementType.PARAMETER 表示注解可以应用于方法的参数上。
通过指定这些目标元素类型,你可以限制注解的使用范围,确保它只能应用在指定的地方。在这个场景中,EncryptDecrypt 注解旨在用于标记需要进行加解密操作的字段和方法参数。
java
1.execution(* com.example.*.*(..)):表示匹配 com.example 包及其子包下的所有类的所有方法。
execution() 是切点函数,用于匹配方法执行的连接点。
* 表示匹配任意返回类型的方法。
com.example.* 表示匹配 com.example 包下的任意类。
*.*(..) 表示匹配任意方法名和参数的方法。
2.(@annotation(com.example.EncryptDecrypt) || @args(com.example.EncryptDecrypt)):表示匹配带有 EncryptDecrypt 注解的方法或参数。
@annotation(com.example.EncryptDecrypt) 匹配带有 EncryptDecrypt 注解的方法。
@args(com.example.EncryptDecrypt) 匹配带有 EncryptDecrypt 注解的参数。
-----------------------------------------分割线-------------------------------------------------------------------------------------------
对出参进行解密
注解类
java
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Decrypt {
String value() default "";
}
java
mport org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Collection;
@Aspect
@Component
public class DecryptionAspect {
@Around("execution(* com.example.*.*(..))")
public Object decryptMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// 执行原方法并获取返回值
Object result = joinPoint.proceed();
// 对带有 @Decrypt 注解的字段进行解密操作
if (result != null) {
if(result instanceof GatewayResp){
//GatewayResp 为统一定义的出参 包括code,msg,data
GatewayResp r = (GatewayResp) result;
Object data = r.getData();
if(data instanceof Collection<?>) {
//集合
data = decryptCollectionFields((Collection<?>)data);
}else{
//单对象
data = decryptObjectFields(data);
}
r.setData(data);
}
}
return result;
}
private Collection<?> decryptCollectionFields(Collection<?> collection) throws IllegalAccessException {
for (Object object : collection) {
decryptObjectFields(object);
}
return collection;
}
private Object decryptObjectFields(Object object) throws IllegalAccessException {
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
// 如果字段带有 @Decrypt 注解,则对其进行解密操作
if (field.isAnnotationPresent(Decrypt.class)) {
field.setAccessible(true);
Object fieldValue = field.get(object);
if (fieldValue instanceof String) {
String decryptedValue = EncryptionUtils.decrypt((String) fieldValue);
field.set(object, decryptedValue);
}
} else {
// 如果字段不带有 @Decrypt 注解,则递归调用 decryptObjectFields() 方法
field.setAccessible(true);
Object fieldValue = field.get(object);
if (fieldValue != null) {
if (fieldValue instanceof Collection<?>) {
decryptCollectionFields((Collection<?>) fieldValue);
} else if(isCustomObject(fieldValue)){
decryptObjectFields(fieldValue);
}
}
}
}
return object;
}
/**
* 判断一个对象不是八大基本数据类型和String类型
*/
private boolean isCustomObject(Object object) {
Class<?> objectType = object.getClass();
// 判断是否为八大基本数据类型
if (objectType.isPrimitive()) {
return false;
}
// 判断是否为String类型
if (objectType.equals(String.class)) {
return false;
}
return true;
}
}