当前位置: 首页 > news >正文

Java Spring 通过 AOP 实现方法参数的重新赋值、修改方法参数的取值

AOP 依赖

我创建的项目项目为 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")@DecodeRsaCommonAnnotationpublic void test(@DecodeRsaParameterAnnotationString text) {System.out.println(text);}

方式一:通过环绕通知实现 [个人比较推荐]

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 加密算法解密后的数据";}// 执行切点方法,并传递重新赋值后的参数列表returnVal = proceedingJoinPoint.proceed(args);} catch (Throwable e) {// 异常处理 ...}// 返回切点方法执行后的返回值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 {// 获取指定对象的 ClassClass<?> objectClass = object.getClass();// 获取指定对象中的指定字段Field declaredField = objectClass.getDeclaredField(fieldName);// 保证获取的指定字段能够被访问declaredField.setAccessible(true);return declaredField;}

通过反射为字符串对象的 value 字段重新赋值为 strValue

    /*** 通过反射为字符串对象的 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.lryc.cn/news/205610.html

相关文章:

  • Real3D FlipBook jQuery Plugin 3.41 Crack
  • Pytorch:model.train()和model.eval()用法和区别,以及model.eval()和torch.no_grad()的区别
  • Linux CentOS 8(firewalld的配置与管理)
  • C复习-指针
  • Runnable和Thread的区别,以及如何调用start()方法
  • 云音乐Android Cronet接入实践
  • Linux dup和dup2
  • Spring Boot实战 | 如何整合高性能数据库连接池HikariCP
  • Spring依赖注入
  • Linux下Jenkins自动化部署SpringBoot应用
  • 【git 学习】--- ubuntu18.04 搭建本地git服务器
  • JAVA电商平台免费搭建 B2B2C商城系统 多用户商城系统 直播带货 新零售商城 o2o商城 电子商务 拼团商城 分销商城
  • Android 13 Framework 裁剪
  • 【Axios封装示例Vue2】
  • k8s-----20、持久化存储--PV/PVC
  • python matplotlib 生成矢量图
  • 机器学习中常见的特征工程处理
  • Spring IOC 和 AOP
  • echarts插件-liquidFill(水球图)
  • c++ vscode cmake debug for mac
  • 17 结构型模式-享元模式
  • 创建Secret(手动)
  • 基于PHP的线上购物商城,MySQL数据库,PHPstudy,原生PHP,前台用户+后台管理,完美运行,有一万五千字论文。
  • Lua 事件触发机制(注册,触发)
  • c++ 并发与多线程(12)线程安全的单例模式-1
  • Python学习笔记--迭代
  • idea免费插件分享
  • Pytorch使用torch.utils.data.random_split拆分数据集,拆分后的数据集状况
  • 每日一练 | 华为认证真题练习Day122
  • SQL sever中函数(2)