${}和#{} 有啥区别

张开发
2026/4/6 23:05:24 15 分钟阅读

分享文章

${}和#{} 有啥区别
这两个符号虽然长得像但在 Java 开发特别是 Spring 和 MyBatis中它们的功能、执行时机和安全性有着天壤之别。简单来说${}是字符串替换简单粗暴直接拼接。#{}是参数占位或表达式解析安全智能预编译或计算。为了让你更清晰地理解我们需要分两个最常见的场景来看Spring 框架配置/注解和MyBatis数据库 SQL。1. 在 Spring 框架中Value, SpEL在 Spring 的配置文件或Value注解中区别在于**“静态文本”与“动态计算”**。特性${}(属性占位符)#{}(SpEL 表达式)全称Property PlaceholderSpring Expression Language作用读取配置文件如 application.yml中的值。执行代码逻辑、数学运算、调用 Bean 方法。执行时机Spring 容器启动时解析。运行时Runtime动态解析。能力只能获取字符串不支持运算。支持加减乘除、三目运算、调用静态方法等。示例Value(${server.port})Value(#{T(Math).random()})代码对比// 1. ${}纯粹的值读取// 从配置文件读取 app.name 的值如果是字符串 MyApp则注入 MyAppValue(${app.name})privateStringname;// 2. #{}强大的逻辑计算// 调用 Math 类的静态方法生成随机数Value(#{T(java.lang.Math).random() * 100})privatedoublerandomNum;// 3. 混合使用高阶玩法// 先通过 ${} 读取配置值 100再通过 #{} 进行乘法运算Value(#{${app.timeout} * 2})privateintdoubleTimeout;2. 在 MyBatis 中SQL 语句在写 SQL 时区别在于**“安全性”**。这是面试和实际开发中最容易踩坑的地方。特性#{}(预编译占位符)${}(字符串替换)原理使用 JDBC 的PreparedStatement。简单的字符串拼接。安全性高防止 SQL 注入。低存在 SQL 注入风险。表现形式数据库看到的是?会自动加上引号。数据库看到的是拼接后的完整 SQL。适用场景绝大多数参数传递如WHERE id #{id}。动态表名、动态排序字段如ORDER BY ${column}。SQL 示例#{}(安全):!-- 传入 123 或 123 OR 11 都会被当作普通字符串处理 --select * from user where id #{id}编译后 SQL:select * from user where id ?(参数被安全设置)${}(危险):!-- 传入恶意字符串会导致 SQL 逻辑被篡改 --select * from user where id ${id}编译后 SQL:select * from user where id 123(直接拼接)3. 总结与建议在 Spring 中读配置文件用${}。做运算、调方法用#{}。在 MyBatis 中永远优先使用#{}。只有当你要动态传入数据库表名、列名如ORDER BY后面的字段时才被迫使用${}此时要注意防范 SQL 注入比如做白名单校验。

更多文章