LoadRunner 支持 Java 作为虚拟用户协议,这意味着你可以使用 Java 语言来编写性能测试脚本,这对于测试基于 Java 的技术栈(如 J2EE, Spring Boot, Hibernate, JMS, JDBC 等)的 Web 应用、API 或后端服务非常有用。

为什么选择 LoadRunner Java 脚本?
- 强大的 Java 生态:可以直接使用 Java 库(如 Apache HttpClient, OkHttp, Jackson, Gson, JUnit TestNG 等)来构建复杂的测试逻辑,而不仅仅是录制和回放简单的 HTTP 请求。
- 复用现有代码:如果你的团队已经有现成的 Java 测试框架或业务逻辑代码,可以很方便地迁移或集成到 LoadRunner 脚本中。
- 处理复杂业务:对于需要复杂状态管理、数据驱动、加密解密、调用第三方 Java SDK 的场景,Java 脚本比 Web (HTTP/HTML) 协议更灵活、更强大。
- 测试非 Web 应用:除了 Web 应用,Java 脚本还可以用来测试通过 RMI、EJB、JMS、Socket 等协议通信的 Java 后端服务。
Java 脚本的核心结构
一个标准的 LoadRunner Java 脚本主要由以下几个部分构成,这些函数可以在 VuGen 的脚本视图中找到:
| 函数名 | 作用 | 执行时机 |
|---|---|---|
init() |
初始化函数,用于建立数据库连接、初始化变量、读取外部数据文件等,每个虚拟用户只执行一次。 | 脚本开始时 |
action() |
核心操作函数,这是脚本的主体,包含了主要的业务逻辑,如发送请求、接收响应、验证结果等,在迭代场景中,每个迭代都会执行一次。 | 性能测试时 |
end() |
结束函数,用于释放资源,如关闭数据库连接、清理临时文件等,每个虚拟用户在所有迭代完成后执行一次。 | 脚本结束时 |
vuser_init() |
Vuser 初始化函数,通常用于登录等建立会话的操作,每个 Vuser 只执行一次。 | 在 init() 之前执行 |
vuser_end() |
Vuser 结束函数,通常用于登出等销毁会话的操作,在 end() 之后执行。 |
在 end() 之后执行 |
脚本执行流程:
vuser_init() -> init() -> [循环开始] -> action() -> action() -> ... -> [循环结束] -> end() -> vuser_end()
创建 Java 脚本的两种主要方式
录制 (Recording)
这是最简单的方式,适用于已有可操作的 GUI 应用。
- 新建脚本:打开 VuGen,选择 "New Script",然后选择 Java 协议。
- 设置录制选项:
- Application to Record: 选择你要录制的 Java 应用,这通常是一个
.jnlp(Java Web Start) 文件或一个本地的.jar文件。 - Working Directory: 指定 Java 应用的主目录。
- Classpath: 指定 Java 应用的类路径,确保 VuGen 能找到所有必需的库。
- JVM Options: 可以设置 JVM 参数,如内存大小等。
- Application to Record: 选择你要录制的 Java 应用,这通常是一个
- 开始录制:点击 "Record" 按钮,VuGen 会启动一个指定的 JVM 来运行你的 Java 应用,你在应用中的所有操作(如点击按钮、输入文本)都会被记录下来,并转化为 Java 代码中的
lr_函数调用(如lr_think_time,lr_output_message)或对特定 Java GUI 组件的操作。
录制脚本的优缺点:

- 优点:快速生成脚本骨架,无需手动编写所有代码。
- 缺点:生成的代码通常比较冗余,不够灵活,难以维护,对于复杂的动态业务逻辑,录制往往力不从心。
手动编写 (Manual Scripting)
对于 API 测试、无界面后端服务测试或需要高度定制化的场景,手动编写是更好的选择。
- 新建脚本:同样选择 Java 协议创建一个新脚本。
- 引入外部库:在 VuGen 的 "Classpath" 设置中,添加你需要的第三方库的
.jar文件(如httpclient-4.5.13.jar,gson-2.10.1.jar等)。 - 在
action()函数中编写代码:使用你熟悉的 Java 代码来构建和发送请求。
实战示例:手动编写 Java 脚本测试 REST API
假设我们要测试一个简单的用户注册 API:
- URL:
http://api.example.com/users/register - Method:
POST - Header:
Content-Type: application/json - Request Body:
{"username": "testuser", "password": "password123"} - Expected Response:
HTTP Status Code 201
步骤 1:准备环境
- 确保你的 LoadVuGen 安装了 Java 协议支持。
- 下载
httpclient-4.5.13.jar和httpcore-4.4.15.jar(或其他版本),并将其复制到你的 LoadRunner 安装目录下的include文件夹,或者在脚本的 "Classpath" 中指定。
步骤 2:编写脚本代码
在 VuGen 的脚本视图中,修改 action() 函数如下:
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
// lr_*** 函数是 LoadRunner 提供的 C 语言风格的函数,可以在 Java 中使用
import lrapi.lr;
public class Actions {
// 定义常量,方便维护
private static final String BASE_URL = "http://api.example.com";
private static final String REGISTER_ENDPOINT = "/users/register";
private static final String USERNAME = "testuser_" + System.currentTimeMillis(); // 使用时间戳保证用户名唯一
private static final String PASSWORD = "password123";
int init() {
// 初始化代码,例如创建一个全局的 HttpClient 实例
// 注意:在 init 中创建,可以在所有 action 迭代中复用,提高性能
return 0;
}
int action() {
lr.vuser_status_message("Starting user registration test for user: " + USERNAME);
// 1. 创建 HttpClient 和 HttpPost 对象
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(BASE_URL + REGISTER_ENDPOINT);
// 2. 设置请求头
httpPost.setHeader("Content-Type", "application/json");
lr.vuser_status_message("Request Header set to: application/json");
// 3. 设置请求体
// 使用 JSON 格式构建请求体
String jsonPayload = String.format("{\"username\": \"%s\", \"password\": \"%s\"}", USERNAME, PASSWORD);
httpPost.setEntity(new StringEntity(jsonPayload));
lr.vuser_status_message("Request Body: " + jsonPayload);
// 4. 发送请求并获取响应
HttpResponse response = httpClient.execute(httpPost);
// 5. 处理响应
int statusCode = response.getStatusLine().getStatusCode();
lr.vuser_status_message("Received Response Status Code: " + statusCode);
HttpEntity entity = response.getEntity();
String responseBody = entity != null ? EntityUtils.toString(entity) : null;
lr.vuser_status_message("Response Body: " + responseBody);
// 6. 验证结果
if (statusCode == 201) {
lr.output_message("User registration successful for user: " + USERNAME);
lr.pass("Status code is 201 as expected.");
} else {
lr.error_message("User registration failed. Expected status code 201, but got " + statusCode);
lr.fail("Test failed due to incorrect status code.");
}
} catch (ClientProtocolException e) {
lr.error_message("ClientProtocolException: " + e.getMessage());
lr.fail("Test failed due to a protocol error.");
return -1; // 返回非零值表示脚本出错
} catch (IOException e) {
lr.error_message("IOException: " + e.getMessage());
lr.fail("Test failed due to an IO error.");
return -1;
}
// 模拟思考时间
lr.think_time(2);
return 0;
}
int end() {
// 结束代码,例如关闭资源
// 在 try-with-resources 中管理的资源会自动关闭,这里可以放其他清理逻辑
return 0;
}
}
步骤 3:参数化 (Parameterization)
为了模拟不同用户,我们需要对用户名进行参数化。

-
在 VuGen 中,选择 "Create" -> "Parameter List"。
-
点击 "New Parameter",命名为
username_param。 -
选择数据类型为 "File",然后创建一个数据文件(如
users.txt),每行一个用户名。 -
在脚本中,将硬编码的
USERNAME替换为参数:// 原代码 // private static final String USERNAME = "testuser_" + System.currentTimeMillis(); // 替换为 private static final String USERNAME = lr.eval_string("{username_param}");
步骤 4:运行和调试
- Run Single User: 先运行单个 Vuser,检查日志输出 (
lr.vuser_status_message和lr.output_message的内容),确认脚本逻辑是否正确。 - Run in Controller: 确认无误后,将脚本添加到 Controller 中,设计场景并运行负载测试。
LoadRunner Java 脚本的常用函数
除了标准的 Java 语法,你还可以使用 LoadRunner 提供的 lr_ 系列函数来增强脚本能力。
| 函数类别 | 常用函数 | 作用 |
|---|---|---|
| 输出和日志 | lr.output_message() |
输出信息到日志,级别为 "Message"。 |
lr.vuser_status_message() |
输出信息到 Vuser 日志,在 Controller 中实时可见。 | |
lr.error_message() |
输出错误信息。 | |
lr.log() |
更底层的日志函数,可以指定日志级别。 | |
| 事务 | lr.start_transaction("transaction_name") |
开始一个事务,用于测量特定操作的性能。 |
lr.end_transaction("transaction_name", LR_AUTO) |
结束一个事务。LR_AUTO 表示根据事务中的最后一个 lr_ 函数(如 lr.eval_string)是否成功来自动确定事务状态。 |
|
| 参数 | lr.eval_string("{param_name}") |
获取参数的当前值。 |
lr.save_string("value", "param_name") |
在运行时动态保存一个值到参数。 | |
| 思考时间 | lr.think_time(seconds) |
在脚本中插入暂停,模拟真实用户的思考时间。 |
| 错误处理 | lr.fail("error message") |
标记当前迭代为失败。 |
lr.pass("success message") |
标记当前迭代为成功。 | |
| 关联 | lr.save_search() |
虽然在 Java 中不像 Web 协议那样常用,但可以用来从响应中提取数据并保存到参数。 |
最佳实践和注意事项
- 资源管理:使用
try-with-resources语句(如try (CloseableHttpClient ...) {})来管理数据库连接、HTTP 客户端等资源,确保它们能被正确关闭,避免内存泄漏。 - 避免硬编码:将 URL、端点、用户名、密码等配置信息定义为常量或参数,提高脚本的可维护性。
- 使用日志:善用
lr.vuser_status_message()在关键步骤输出日志,这对于调试和分析问题至关重要。 - 事务分离:将核心业务逻辑(如“提交订单”)封装在一个事务中,以便精确测量其性能。
- 参数化:始终对动态数据(如用户ID、Session ID)和可变数据(如用户名)进行参数化,确保脚本的可重用性和数据的唯一性。
- 性能考虑:在
init()中创建和初始化重量级的对象(如HttpClient、数据库连接池),在action()中复用它们,而不是在每次迭代中都重新创建。 - 错误处理:使用
try-catch块来捕获和处理可能发生的异常,并在发生错误时使用lr.fail()标记失败,而不是让脚本直接崩溃。
希望这份详细的指南能帮助你掌握 LoadRunner Java 脚本的编写!如果你有更具体的问题,比如如何处理特定的协议或技术,可以随时提出。
