AOP 依賴
我創(chuàng)建的項目項目為 SpringBoot 項目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
String 類型參數
這里以對前端傳遞過來的加密數據進行解密為例
注解
import java.lang.annotation.*;
/**
* 標注需要進行 RSA 加密算法解密的通用注解。
* 該注解可以使用在類上、方法上、方法參數上、字段/屬性上、局部變量上
*/
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecodeRsaCommonAnnotation {
}
import java.lang.annotation.*;
/**
* 標注需要進行 RSA 加密算法解密的方法參數的注解。
* 該注解可以使用在方法參數上
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecodeRsaParameterAnnotation {
}
控制器方法
@GetMapping("/test")
@DecodeRsaCommonAnnotation
public void test(
@DecodeRsaParameterAnnotation
String text
) {
System.out.println(text);
}
方式一:通過環(huán)繞通知實現 [個人比較推薦]
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Order(1)
@Component
public class DecodeRsaAspect {
/**
* DecodeRsaAspect 的切點為被 @DecodeRsaCommonAnnotation 標記的位置
*/
@Pointcut("@annotation(cn.org.xiaoweiba.graduationdesign.bookmall.annotation.rsa.DecodeRsaCommonAnnotation)")
public void pointCut() {
}
/**
* 采用 Rsa 加密算法進行解密
*
* @param proceedingJoinPoint 切點
*/
@Around("pointCut()")
public Object decodeRsaAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
Object returnVal = null;
try {
// 獲取切點方法的參數
Object[] args = proceedingJoinPoint.getArgs();
// 中間處理 ...
// 對切點方法的參數進行重新賦值
for (int i = 0; i < args.length; i++) {
args[i] = "RSA 加密算法解密后的數據";
}
// 執(zhí)行切點方法,并傳遞重新賦值后的參數列表
returnVal = proceedingJoinPoint.proceed(args);
} catch (Throwable e) {
// 異常處理 ...
}
// 返回切點方法執(zhí)行后的返回值
return returnVal;
}
}
方式二:通過前置通知 + 反射實現
Java ReflectUtil 反射相關的工具類
由于 JDK 8 中有關反射相關的功能自從 JDK 9 開始就已經被限制了,如:通過反射修改 String 類型變量的 value 字段(final byte[]),所以要能夠使用運行此方法,需要在運行項目時,添加虛擬機(VM)選項:--add-opens java.base/java.lang=ALL-UNNAMED
,開啟默認不被允許的行為
通過反射修改 String 類型對象 value 取值的工具方法
獲取指定對象中的指定字段(不包含父類中的字段)
/**
* 獲取指定對象中的指定字段(不包含父類中的字段)。
* 此方法在獲取指定對象中的指定字段時,會包證獲取的指定字段能夠被訪問。
*
* @param object 要獲取字段的指定對象
* @param fieldName 要獲取的指定字段的名稱
* @return 指定對象中的指定字段
*/
public static Field getField(Object object, String fieldName) throws NoSuchFieldException {
// 獲取指定對象的 Class
Class<?> objectClass = object.getClass();
// 獲取指定對象中的指定字段
Field declaredField = objectClass.getDeclaredField(fieldName);
// 保證獲取的指定字段能夠被訪問
declaredField.setAccessible(true);
return declaredField;
}
通過反射為字符串對象的 value 字段重新賦值為 strValue文章來源:http://www.zghlxwxcb.cn/news/detail-763552.html
/**
* 通過反射為字符串對象的 value 字段重新賦值為 strValue,
* 從而保證不修改字符串對象的引用,并且能夠修改字符串的取值
* 由于 JDK 8 中有關反射相關的功能自從 JDK 9 開始就已經被限制了,所以要能夠使用運行此方法,
* 需要在運行項目時,添加虛擬機(VM)選項:--add-opens java.base/java.lang=ALL-UNNAMED
* 開啟默認不被允許的行為
*
* @param str 需要進行重新賦值的字符串對象
* @param strValue 要賦值給字符串對象的值
*/
public static void setValueString(String str, String strValue) throws NoSuchFieldException, IllegalAccessException {
// 獲取字符串的 value 字段
Field strValueField = getField(str, "value");
// 為字符串對象的 value 字段重新賦值
// strValueField.set(str, strValue.getBytes(StandardCharsets.UTF_8)); 不要使用該種方法,會出現亂碼
// 采用如下方式,獲取 strValue 的 value 字段值,將其賦值給 str 的 value 字段
strValueField.set(str, strValueField.get(strValue));
}
切面類
import cn.org.xiaoweiba.graduationdesign.bookmall.utils.ReflectUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Order(1)
@Component
public class DecodeRsaAspect {
/**
* DecodeRsaAspect 的切點為被 @DecodeRsaCommonAnnotation 標記的位置
*/
@Pointcut("@annotation(cn.org.xiaoweiba.graduationdesign.bookmall.annotation.rsa.DecodeRsaCommonAnnotation)")
public void pointCut() {
}
/**
* 采用 Rsa 加密算法進行解密
*
* @param joinPoint 切點
*/
@Before("pointCut()")
public void decodeRsaBeforeAdvice(JoinPoint joinPoint) {
try {
// 獲取切點方法的參數
Object[] args = joinPoint.getArgs();
// 中間處理 ...
// 對切點方法的參數進行重新賦值
for (int i = 0; i < args.length; i++) {
// 對字符串對象的 value 字段重新賦值,不修改字符串對象的指向,保證修改的為切點方法的字符串對象參數
ReflectUtil.setValueString((String) args[i], "解密后的數據");
}
} catch (Throwable e) {
// 異常處理 ...
}
}
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-763552.html
到了這里,關于Java Spring 通過 AOP 實現方法參數的重新賦值、修改方法參數的取值的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!