我正在尝试调用一个java方法,该方法接受一个字符串作为空手道脚本中的参数,并在该字符串中插入空手道中定义的值。
在我的例子中,这是一个简单的数据库 INSERT 语句,例如:
INSERT INTO A(id, time, value) VALUES(1, '2099-05-10 18:20:18.674 UTC', 'test')
脚本本身如下所示:
Background:
* def db = Java.type('com.example.DbTestHelper')
* def offsetDateTime = Java.type('java.time.OffsetDateTime')
* def zoneId = Java.type('java.time.ZoneId')
Scenario: testScenario
* def t = offsetDateTime.now(zoneId.of("Europe/Berlin")).plusDays(1)
* def row = db.insertRow("INSERT INTO A(id, time, value) VALUES(123, #t, 'test')")
并且 insertRow 方法如下所示:
@JvmStatic
fun insertRow(vararg strings: String) {
jdbc.batchUpdate(*strings)
}
我尝试了设置值t的多种组合,例如#(t)、#t、“#(t)”等。不幸的是,它们都不起作用,甚至在调用java方法之前就导致了各种javascript解析错误。
实现这一目标的正确方法是什么?还可能吗?
首先阅读此内容:https://github.com/karatelabs/karate#rules-for-embedded-expressions
好消息是,从 1.0 开始,Karate 支持在反引号内进行 ES6 JS 字符串插值:
* def foo = 1
* def txt = `hello ${foo}`
* match txt == 'hello 1'
当然,字符串连接总是有效的。你只需要考虑大多数空手道语法,尤其是当你调用 Java 时 - 只不过是普通的旧式 JavaScript。
* db.insertRow("INSERT INTO A(id, time, value) VALUES(123, " + t + ", 'test')")
我想你现在就可以继续了。
您可以使用Java的字符串模板功能。 它在 JEP 430 中进行了描述,并作为预览功能出现在 JDK 21 中。这是一个使用示例:
String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan"); // true
Java 的字符串模板比其他语言(例如 C# 的字符串插值和 Python 的 f 字符串)中的功能更通用,也更安全。例如,字符串连接或插值使得 SQL 注入攻击成为可能:
String query = "SELECT * FROM Person p WHERE p.last_name = '" + name + "'";
ResultSet rs = conn.createStatement().executeQuery(query);
但是这个变体(来自 JEP 430)可以防止 SQL 注入:
PreparedStatement ps = DB."SELECT * FROM Person p WHERE p.last_name = \{name}";
ResultSet rs = ps.executeQuery();