Spel 表达式

文章介绍了如何在Java项目中使用SPEL表达式进行模板占位替换,如获取方法参数、注解中的参数处理,以及结合JacksonUtils解析JSON数据。示例展示了变量替换、字符串拼接和条件判断的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模板占位替换,在项目开发中,还是很常用的。比如在代码中获取参数,消息推送可以使用变量占位,我比较推荐使用 SPEL 表达式。

  1. 在注解中,获取方法的参数
public class SpElParser {

    private static final ExpressionParser parser = new SpelExpressionParser();

    public static String getKey(String key, String [] parameterNames, Object [] args) {
        Expression expression = parser.parseExpression(key);
        EvaluationContext context = new StandardEvaluationContext();
        if (args.length == 0) {
            return null;
        }
        for (int i = 0; i < args.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        return expression.getValue(context, String.class);
    }

}

用法:

@LogRecord(logBizId = “#dto.id”)

@LogRecord(logBizId = “#dto.id + ‘_’ + #dto.name”)

  1. 模板占位替换
    public static String convert(String content, Map<String, String> paramMap) {
        if (!StringUtils.hasText(content) || CollectionUtils.isEmpty(paramMap)) {
            return content;
        }
        ExpressionParser parser = new SpelExpressionParser();
        TemplateParserContext parserContext = new TemplateParserContext();
        return parser
                .parseExpression(content, parserContext)
                .getValue(paramMap, String.class);
    }

    public static String convert(String content, String json) {
        if (!StringUtils.hasText(content) || !StringUtils.hasText(json)) {
            return content;
        }
        Map<String, String> paramMap = JacksonUtils.jsonObject(
                json,
                new TypeReference<Map<String, String>>() {
                }
        );
        return convert(content, paramMap);
    }
{
    "name":"张三"
}

用法1,变量占位替换

String content = "#{[name]}";

用法2,变量占位替换 + 字符串拼接

String content = "#{'Hello, ' + [name] + '!'}"; 

用法3,判断变量是否为空

String content = "#{[name1] != null ? 'Hello, ' + [name1] + '!' : ''}"; 
### Spring Data JPA 中 SpEL 表达式的使用 Spring Expression Language (SpEL) 是一种强大的表达式语言,可以在运行时动态计算值。在 Spring Data JPA 的 `@Query` 注解中,可以通过 `${...}` 或者 `?#{...}` 来嵌入 SpEL 表达式[^1]。 #### 位置参数绑定 默认情况下,Spring Data JPA 支持基于位置的参数绑定方式。这种方式通过占位符 `?n` 将查询语句中的参数与方法签名中的参数一一对应。例如: ```java @Query("SELECT u FROM User u WHERE u.emailAddress = ?1") User findByEmailAddress(String emailAddress); ``` 在这个例子中,`?1` 对应的是方法的第一个参数 `emailAddress`[^2]。 然而,这种绑定方式存在一定的局限性——当需要调整查询逻辑或者重构代码时,可能会因为参数顺序的变化而导致错误。 --- #### 命名参数绑定 为了提高可读性和灵活性,推荐使用命名参数的方式替代位置参数绑定。命名参数允许开发者显式地指定参数名称,从而减少因参数顺序变化而引发的问题。以下是两种常见的命名参数绑定形式: 1. **使用 `@Param` 显式标注** 当方法参数的名字无法直接映射到查询语句中的变量名字时,可以借助 `@Param` 进行手动绑定。例如: ```java @Query("SELECT u FROM User u WHERE u.username = :username OR u.phone = :phone") List<User> findUsersByUsernameOrPhone(@Param("username") String username, @Param("phone") String phone); ``` 2. **隐式绑定(无需 `@Param`)** 如果方法参数的名字能够完全匹配查询语句中的变量名字,则可以直接省略 `@Param` 标注。例如: ```java @Query("SELECT u FROM User u WHERE u.phone = :phone OR u.username = :username") List<User> findUsersByUsernameOrPhone(String username, String phone); ``` 在这种场景下,框架会自动完成参数绑定操作[^3]。 --- #### SpEL 表达式的作用 除了传统的静态 SQL 查询外,Spring Data JPA 还支持利用 SpEL 动态生成部分查询条件。这使得开发人员可以根据外部环境或者其他上下文信息灵活构建查询语句。下面是一个简单的案例演示如何结合 SpEL 和命名参数一起工作: 假设我们有一个需求:根据当前用户的权限级别过滤数据记录。此时可以这样写: ```java @Query("SELECT e FROM Employee e WHERE e.department.id = :departmentId AND e.level >= ?#{hasRole('ADMIN') ? 'LEVEL_ADMIN' : 'LEVEL_USER'}") List<Employee> getEmployeesByDepartmentAndLevel(@Param("departmentId") Long departmentId); ``` 在此处: - `:departmentId` 属于普通的命名参数; - 而 `?#{...}` 则引入了一个 SpEL 表达式用于断用户角色并返回相应的字符串常量作为比较依据。 需要注意的一点是,虽然 SpEL 提供了极大的便利性,但在实际项目应用过程中应当谨慎评估其复杂度以免影响性能或降低代码维护难度[^4]。 --- ### 总结 综上所述,在 Spring Data JPA 开发实践中可以选择适合自己的参数传递机制。对于简单情形来说采用位置参数即可满足基本功能需求;而对于更复杂的业务场景则建议优先考虑命名参数配合 SpEL 实现更加智能化的数据访问层设计模式。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯文议

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值