划重点,${} 占位符处理如下:
handleToken(String content) 方法中, Mybatis 会通过 ognl 表达式将 ${} 的结果直接拼接在 sql 语句中 , 由此我们得知 ${} 占位符拼接的字段就是我们传入的原样字段,有着 Sql 注入风险
2、#{}占位符处理#{} 占位符文本的 SqlNode 实现类为 StaticTextSqlNode,查看源码 。
【Mybatis占位符#和$的区别?源码解读】public class StaticTextSqlNode implements SqlNode {private final String text;public StaticTextSqlNode(String text) {this.text = text;}@Overridepublic boolean apply(DynamicContext context) {context.appendSql(text);return true;}}StaticTextSqlNode 会直接将节点内容拼接在 sql 语句中,也就是说在 rootSqlNode.apply(context) 方法执行完毕后 , 此时的 sql 语句如下:
select order_id, order_no, user_id, total_price, pay_status, pay_type, pay_time, order_status, extra_info, user_name, user_phone, user_address, is_deleted, create_time, update_time from tb_newbee_mall_orderorder by create_time desclimit #{start},#{limit}Mybatis会通过上面提到getBoundSql(Object parameterObject)方法中的 。

文章插图
sqlSourceParser.parse()方法完成 #{} 占位符的处理,代码如下:
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);String sql;if (configuration.isShrinkWhitespacesInSql()) {sql = parser.parse(removeExtraWhitespaces(originalSql));} else {sql = parser.parse(originalSql);}return new StaticSqlSource(configuration, sql, handler.getParameterMappings());}看到了熟悉的 #{ 占位符没有,哈哈, Mybatis 对于 #{} 占位符的处理就在 GenericTokenParser类的 parse() 方法中 , 代码如下:public class GenericTokenParser {public String parse(String text) {...do {...if (end == -1) {...} else {builder.append(handler.handleToken(expression.toString()));offset = end + closeToken.length();}}...} while (start > -1);...return builder.toString();}}public class SqlSourceBuilder extends BaseBuilder {...// 划重点,#{}占位符替换逻辑在就SqlSourceBuilder.handleToken(String content)方法中@Overridepublic String handleToken(String content) {parameterMappings.add(buildParameterMapping(content));return "?";}}划重点,#{} 占位符处理如下:handleToken(String content) 方法中 , Mybatis 会直接将我们的传入参数转换成问号(就是 jdbc 规范中的问号),也就是说我们的 sql 语句是预处理的 。能够避免 sql 注入问题
三. 总结由上经过源码分析,我们知道 Mybatis 对 #{} 占位符是直接转换成问号,拼接预处理 sql 。 ${} 占位符是原样拼接处理,有sql注入风险,最好避免由客户端传入此参数 。
推荐阅读
- Linux上使用Docker实现应用程序打包和分发
- 打造高质量Web应用程序:React 和 Vue 框架对比和实践经验总结
- 如何使用 Python 和 python-docx 库读取、写入和操作 Word 文件
- 养老金又有新消息!
- 个人养老金制度出炉!我们该如何解读和面对?
- 城市退休职工和农民养老金差距大,原因何在?
- 泰国椰青和海南椰青的区别 泰国椰青和海南椰青的区别在哪
- 蚕宝宝怎么养视频教程 蚕宝宝的养殖方法和注意事项
- 刘家昌发长文控诉前妻和儿子,每天找律师争夺财产,丝毫没有人性
- 新西兰属于哪个洲,澳大利亚和新西兰属于哪个洲
