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

@PreAuthorize(“hasPermission(#resourceId, ‘DATA_ASSET‘, ‘read‘)“)无法识别参数

您提到使用 #p2(参数索引)可以正常工作,但使用参数名称(如 #resourceId)不行。这是典型的 Java 编译参数名丢失问题,根本原因是 Spring 的 SpEL 表达式引擎无法在运行时获取方法参数名称。以下是详细分析和解决方案:


问题根源:字节码参数名缺失

Java 编译器默认不会保留方法参数名称到字节码中(除非使用特殊编译选项)。例如您的 Controller 方法:

public Result<?> getPermissionByUserIdAndResource2(@PathVariable("userId") int userId,@PathVariable("resourceType") String resourceType,@PathVariable("resourceId") String resourceId) // ← 编译后参数名会变成 arg0, arg1, arg2

当 SpEL 尝试解析 #resourceId 时:

  1. 它会在字节码中查找名为 resourceId 的参数
  2. 由于参数名未被保留,实际找到的是 arg2(或其他占位名)
  3. 导致解析失败,返回 null

解决方案(任选其一)

✅ 方案1:使用参数索引(推荐 - 您已验证有效)
@PreAuthorize("hasPermission(#p2, 'DATA_ASSET', 'read')") // #p2 = 第三个参数
public Result<?> getPermissionByUserIdAndResource2(...) {...}
  • 优势:无需任何配置,100% 可靠
  • 索引规则
    • #p0 = 第一个参数 (userId)
    • #p1 = 第二个参数 (resourceType)
    • #p2 = 第三个参数 (resourceId)
✅ 方案2:启用编译器参数名保留(一劳永逸)

在编译时保留参数名,需修改构建配置:

Maven 项目(pom.xml)
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><compilerArgs><arg>-parameters</arg> <!-- 关键参数 --></compilerArgs></configuration></plugin></plugins>
</build>
Gradle 项目(build.gradle)
tasks.withType(JavaCompile) {options.compilerArgs << "-parameters"
}

生效后

@PreAuthorize("hasPermission(#resourceId, 'DATA_ASSET', 'read')") // 名称可正常使用
✅ 方案3:使用 Spring 的 @Param 注解(无需编译配置)
import org.springframework.data.repository.query.Param; // 注意导入正确包@PreAuthorize("hasPermission(#resId, 'DATA_ASSET', 'read')")
public Result<?> getPermissionByUserIdAndResource2(@PathVariable("userId") int userId,@PathVariable("resourceType") String resourceType,@Param("resId") @PathVariable("resourceId") String resourceId) { // 添加@Param注解// ...
}
  • 通过 @Param 显式声明表达式用到的名称
  • 表达式使用 #resId(注解定义名)而非 #resourceId

为什么 #p2 有效而名称无效?

方式实现机制是否依赖参数名保留
#resourceId通过反射获取参数名是 (需-parameters)
#p2通过参数位置索引访问否 (始终可靠)
@Param通过注解显式绑定名称

最终建议

  1. 短期解决:继续使用 #p2(您已验证有效)
  2. 长期维护
    • 重要项目 → 启用 -parameters 编译选项(方案2)
    • 快速修复 → 使用 @Param 注解(方案3)

参数名保留是 Java 8+ 的官方特性,启用后对工程无副作用,还能增强调试信息,推荐全局启用。

http://www.dtcms.com/a/333540.html

相关文章:

  • 机器学习案例——《红楼梦》文本分析与关键词提取
  • C语言第八章指针五
  • 国内著名AI搜索优化专家孟庆涛发表《AI搜索内容可信度评估综合指南》
  • AI智能体在软件测试中的应用与未来趋势
  • 快速了解PCA降维
  • exec函数族、线程
  • termios 线程 poll epoll进化 二叉AVL红黑树
  • Redis入门和简介
  • python学习打卡day35
  • 分库分表和sql的进阶用法总结
  • AI客户维护高效解决方案
  • element-plus 如何通过js验证页面的表单
  • 开发避坑指南(27):Vue3中高效安全修改列表元素属性的方法
  • IP地址代理服务避坑指南:如何选择优质的IP地址代理服务公司?
  • 前端设置不同环境高德地图 key 和秘钥(秘钥通过运维统一配置)
  • 六大主流负载均衡算法
  • w484扶贫助农系统设计与实现
  • 【postgresql】一文详解postgresql中的统计模块
  • [Pyro概率编程] 概率分布 | 共轭计算 | 参数存储库
  • Qt开发:实现跨组件的条件触发
  • android 悬浮窗权限申请
  • 正点原子STM32H743配置 LTDC + DMA2D
  • 零基础学会制作 基于STM32单片机智能加湿系统/加湿监测/蓝牙系统/监测水量
  • Docker部署MySQL命令解读
  • redis-保姆级配置详解
  • 嵌入式软件开发--回调函数
  • 大肠杆菌重组蛋白表达致命痛点:包涵体 / 低表达 / 可溶性差?高效解决方案全解析!
  • JVM核心原理与实战优化指南
  • c++程序示例:多线程下的实例计数器
  • Nginx反向代理与缓存实现