chore: 部分验证逻辑调整
This commit is contained in:
parent
727e7eb928
commit
035b8f8f61
|
@ -149,6 +149,12 @@ CREATE INDEX idx_plan ON api_scenario_report(`plan`);
|
||||||
-- 测试计划配置 增加运行模式
|
-- 测试计划配置 增加运行模式
|
||||||
ALTER table test_plan_config
|
ALTER table test_plan_config
|
||||||
ADD COLUMN `case_run_mode` VARCHAR(50) NOT NULL DEFAULT 'PARALLEL' COMMENT '不同用例之间的执行方式(串行/并行)';
|
ADD COLUMN `case_run_mode` VARCHAR(50) NOT NULL DEFAULT 'PARALLEL' COMMENT '不同用例之间的执行方式(串行/并行)';
|
||||||
|
-- 修改默认资源池id
|
||||||
|
UPDATE project_test_resource_pool set test_resource_pool_id = '100001100001' WHERE test_resource_pool_id IN (SELECT id FROM test_resource_pool where `name`= '默认资源池');
|
||||||
|
UPDATE project_application set type_value = '100001100001' WHERE type_value IN (SELECT id FROM test_resource_pool where `name`= '默认资源池');
|
||||||
|
|
||||||
|
-- 默认资源池固定ID
|
||||||
|
update test_resource_pool set id ='100001100001' where `name`= '默认资源池';
|
||||||
|
|
||||||
-- set innodb lock wait timeout to default
|
-- set innodb lock wait timeout to default
|
||||||
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.metersphere</groupId>
|
||||||
|
<artifactId>monitoring-engine</artifactId>
|
||||||
|
<version>${monitoring-engine.revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<artifactId>metersphere-project-management</artifactId>
|
<artifactId>metersphere-project-management</artifactId>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.api.dto.request.controller.MsScriptElement;
|
||||||
import io.metersphere.api.parser.TestElementParser;
|
import io.metersphere.api.parser.TestElementParser;
|
||||||
import io.metersphere.api.parser.TestElementParserFactory;
|
import io.metersphere.api.parser.TestElementParserFactory;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
|
import io.metersphere.engine.MsHttpClient;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.domain.FileMetadata;
|
import io.metersphere.project.domain.FileMetadata;
|
||||||
|
@ -33,7 +34,6 @@ import io.metersphere.system.domain.TestResourcePool;
|
||||||
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
|
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
|
||||||
import io.metersphere.system.dto.pool.TestResourcePoolReturnDTO;
|
import io.metersphere.system.dto.pool.TestResourcePoolReturnDTO;
|
||||||
import io.metersphere.system.service.*;
|
import io.metersphere.system.service.*;
|
||||||
import io.metersphere.system.utils.TaskRunnerClient;
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
@ -168,6 +168,7 @@ public class ApiExecuteService {
|
||||||
|
|
||||||
return taskInfo;
|
return taskInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给 taskRequest 设置当前项目相关的文件信息
|
* 给 taskRequest 设置当前项目相关的文件信息
|
||||||
*
|
*
|
||||||
|
@ -219,12 +220,12 @@ public class ApiExecuteService {
|
||||||
taskInfo.setMsUrl(testResourcePoolDTO.getServerUrl());
|
taskInfo.setMsUrl(testResourcePoolDTO.getServerUrl());
|
||||||
}
|
}
|
||||||
taskInfo.setPoolSize(testResourceNodeDTO.getConcurrentNumber());
|
taskInfo.setPoolSize(testResourceNodeDTO.getConcurrentNumber());
|
||||||
String endpoint = TaskRunnerClient.getEndpoint(testResourceNodeDTO.getIp(), testResourceNodeDTO.getPort());
|
String endpoint = MsHttpClient.getEndpoint(testResourceNodeDTO.getIp(), testResourceNodeDTO.getPort());
|
||||||
LogUtils.info("开始发送请求【 {}_{} 】到 {} 节点执行", taskItem.getReportId(), taskItem.getResourceId(), endpoint);
|
LogUtils.info("开始发送请求【 {}_{} 】到 {} 节点执行", taskItem.getReportId(), taskItem.getResourceId(), endpoint);
|
||||||
if (StringUtils.equalsAny(taskInfo.getRunMode(), ApiExecuteRunMode.FRONTEND_DEBUG.name(), ApiExecuteRunMode.BACKEND_DEBUG.name())) {
|
if (StringUtils.equalsAny(taskInfo.getRunMode(), ApiExecuteRunMode.FRONTEND_DEBUG.name(), ApiExecuteRunMode.BACKEND_DEBUG.name())) {
|
||||||
TaskRunnerClient.debugApi(endpoint, taskRequest);
|
MsHttpClient.debugApi(endpoint, taskRequest);
|
||||||
} else {
|
} else {
|
||||||
TaskRunnerClient.runApi(endpoint, taskRequest);
|
MsHttpClient.runApi(endpoint, taskRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (HttpServerErrorException e) {
|
} catch (HttpServerErrorException e) {
|
||||||
|
@ -254,7 +255,6 @@ public class ApiExecuteService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送执行任务
|
* 发送执行任务
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void batchExecute(TaskBatchRequestDTO taskRequest) {
|
public void batchExecute(TaskBatchRequestDTO taskRequest) {
|
||||||
setTaskRequestParams(taskRequest.getTaskInfo());
|
setTaskRequestParams(taskRequest.getTaskInfo());
|
||||||
|
@ -289,14 +289,14 @@ public class ApiExecuteService {
|
||||||
// todo 优化某个资源池不可用的情况,以及清理 executionSet
|
// todo 优化某个资源池不可用的情况,以及清理 executionSet
|
||||||
TestResourceNodeDTO testResourceNode = nodesList.get(i);
|
TestResourceNodeDTO testResourceNode = nodesList.get(i);
|
||||||
TaskBatchRequestDTO subTaskRequest = distributeTasks.get(i);
|
TaskBatchRequestDTO subTaskRequest = distributeTasks.get(i);
|
||||||
String endpoint = TaskRunnerClient.getEndpoint(testResourceNode.getIp(), testResourceNode.getPort());
|
String endpoint = MsHttpClient.getEndpoint(testResourceNode.getIp(), testResourceNode.getPort());
|
||||||
try {
|
try {
|
||||||
List<String> taskKeys = subTaskRequest.getTaskItems().stream()
|
List<String> taskKeys = subTaskRequest.getTaskItems().stream()
|
||||||
.map(taskItem -> taskItem.getReportId() + "_" + taskItem.getResourceId())
|
.map(taskItem -> taskItem.getReportId() + "_" + taskItem.getResourceId())
|
||||||
.toList();
|
.toList();
|
||||||
LogUtils.info("开始发送批量任务到 {} 节点执行:\n" + taskKeys, endpoint);
|
LogUtils.info("开始发送批量任务到 {} 节点执行:\n" + taskKeys, endpoint);
|
||||||
|
|
||||||
TaskRunnerClient.batchRunApi(endpoint, subTaskRequest);
|
MsHttpClient.batchRunApi(endpoint, subTaskRequest);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error("发送批量任务到 {} 节点执行失败", endpoint);
|
LogUtils.error("发送批量任务到 {} 节点执行失败", endpoint);
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
|
@ -304,7 +304,24 @@ public class ApiExecuteService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static boolean validate() {
|
||||||
|
try {
|
||||||
|
LicenseService licenseService = CommonBeanFactory.getBean(LicenseService.class);
|
||||||
|
return Optional.ofNullable(licenseService)
|
||||||
|
.map(LicenseService::validate)
|
||||||
|
.map(dto -> StringUtils.equals(dto.getStatus(), "valid"))
|
||||||
|
.orElse(false);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TestResourceNodeDTO getNextExecuteNode(TestResourcePoolReturnDTO resourcePoolDTO) {
|
private TestResourceNodeDTO getNextExecuteNode(TestResourcePoolReturnDTO resourcePoolDTO) {
|
||||||
|
if (!validate()) {
|
||||||
|
return resourcePoolDTO.getTestResourceReturnDTO().getNodesList().getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
roundRobinService.initializeNodes(resourcePoolDTO.getId(), resourcePoolDTO.getTestResourceReturnDTO().getNodesList());
|
roundRobinService.initializeNodes(resourcePoolDTO.getId(), resourcePoolDTO.getTestResourceReturnDTO().getNodesList());
|
||||||
try {
|
try {
|
||||||
TestResourceNodeDTO node = roundRobinService.getNextNode(resourcePoolDTO.getId());
|
TestResourceNodeDTO node = roundRobinService.getNextNode(resourcePoolDTO.getId());
|
||||||
|
@ -337,8 +354,8 @@ public class ApiExecuteService {
|
||||||
* @param taskInfo 执行参数
|
* @param taskInfo 执行参数
|
||||||
*/
|
*/
|
||||||
private void setServerInfoParam(TaskInfo taskInfo) {
|
private void setServerInfoParam(TaskInfo taskInfo) {
|
||||||
taskInfo.setKafkaConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(KafkaConfig.getKafkaConfig())));
|
taskInfo.setKafkaConfig(JSON.toJSONString(KafkaConfig.getKafkaConfig()));
|
||||||
taskInfo.setMinioConfig(EncryptUtils.aesEncrypt(JSON.toJSONString(getMinio())));
|
taskInfo.setMinioConfig(JSON.toJSONString(getMinio()));
|
||||||
taskInfo.setMsUrl(systemParameterService.getBaseInfo().getUrl());
|
taskInfo.setMsUrl(systemParameterService.getBaseInfo().getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import io.metersphere.api.dto.definition.ExecuteReportDTO;
|
||||||
import io.metersphere.api.dto.report.ReportDTO;
|
import io.metersphere.api.dto.report.ReportDTO;
|
||||||
import io.metersphere.api.mapper.ExtApiReportMapper;
|
import io.metersphere.api.mapper.ExtApiReportMapper;
|
||||||
import io.metersphere.api.mapper.ExtApiScenarioReportMapper;
|
import io.metersphere.api.mapper.ExtApiScenarioReportMapper;
|
||||||
|
import io.metersphere.engine.MsHttpClient;
|
||||||
import io.metersphere.project.domain.Project;
|
import io.metersphere.project.domain.Project;
|
||||||
import io.metersphere.project.mapper.ProjectMapper;
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.sdk.constants.*;
|
import io.metersphere.sdk.constants.*;
|
||||||
|
@ -36,7 +37,6 @@ import io.metersphere.system.service.UserLoginService;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
import io.metersphere.system.utils.TaskRunnerClient;
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
@ -278,7 +278,7 @@ public class ApiTaskCenterService {
|
||||||
Map<String, String> testPlanIdMap = reports.stream()
|
Map<String, String> testPlanIdMap = reports.stream()
|
||||||
.collect(Collectors.toMap(ReportDTO::getId, ReportDTO::getTestPlanId));
|
.collect(Collectors.toMap(ReportDTO::getId, ReportDTO::getTestPlanId));
|
||||||
nodesList.parallelStream().forEach(node -> {
|
nodesList.parallelStream().forEach(node -> {
|
||||||
String endpoint = TaskRunnerClient.getEndpoint(node.getIp(), node.getPort());
|
String endpoint = MsHttpClient.getEndpoint(node.getIp(), node.getPort());
|
||||||
//需要去除取消勾选的report
|
//需要去除取消勾选的report
|
||||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||||
reportList.removeAll(request.getExcludeIds());
|
reportList.removeAll(request.getExcludeIds());
|
||||||
|
@ -294,7 +294,7 @@ public class ApiTaskCenterService {
|
||||||
SubListUtils.dealForSubList(reportList, 100, (subList) -> {
|
SubListUtils.dealForSubList(reportList, 100, (subList) -> {
|
||||||
try {
|
try {
|
||||||
LogUtils.info(String.format("开始发送停止请求到 %s 节点执行", endpoint), subList.toString());
|
LogUtils.info(String.format("开始发送停止请求到 %s 节点执行", endpoint), subList.toString());
|
||||||
TaskRunnerClient.stopApi(endpoint, subList);
|
MsHttpClient.stopApi(endpoint, subList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -39,4 +39,11 @@ public interface ExtUserMapper {
|
||||||
long countByIdAndPassword(@Param("userId") String id, @Param("password") String password);
|
long countByIdAndPassword(@Param("userId") String id, @Param("password") String password);
|
||||||
|
|
||||||
long updatePasswordByUserId(@Param("userId") String id, @Param("password") String password);
|
long updatePasswordByUserId(@Param("userId") String id, @Param("password") String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户的安装时间,兼容历史用户使用问题
|
||||||
|
* @return 安装时间
|
||||||
|
*/
|
||||||
|
long gaInstalledTime();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,4 +97,11 @@
|
||||||
SET password = MD5(#{password})
|
SET password = MD5(#{password})
|
||||||
WHERE id = #{userId}
|
WHERE id = #{userId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<select id="gaInstalledTime" resultType="java.lang.Long">
|
||||||
|
SELECT
|
||||||
|
UNIX_TIMESTAMP(installed_on) * 1000 as installed_on
|
||||||
|
FROM metersphere_version
|
||||||
|
WHERE version ='3.0.1.2'
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -2,8 +2,6 @@ package io.metersphere.system.utils;
|
||||||
|
|
||||||
import com.bastiaanjansen.otp.TOTPGenerator;
|
import com.bastiaanjansen.otp.TOTPGenerator;
|
||||||
import io.metersphere.sdk.constants.MsHttpHeaders;
|
import io.metersphere.sdk.constants.MsHttpHeaders;
|
||||||
import io.metersphere.sdk.dto.api.task.TaskBatchRequestDTO;
|
|
||||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import io.metersphere.system.controller.handler.ResultHolder;
|
import io.metersphere.system.controller.handler.ResultHolder;
|
||||||
import io.metersphere.system.controller.handler.result.MsHttpResultCode;
|
import io.metersphere.system.controller.handler.result.MsHttpResultCode;
|
||||||
|
@ -21,17 +19,12 @@ import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class TaskRunnerClient {
|
public class TaskRunnerClient {
|
||||||
private static TOTPGenerator totpGenerator;
|
private static TOTPGenerator totpGenerator;
|
||||||
|
|
||||||
private static final String API_DEBUG = "/api/debug";
|
|
||||||
private static final String API_RUN = "/api/run";
|
|
||||||
private static final String BATCH_API_RUN = "/api/batch/run";
|
|
||||||
private static final String HTTP_BATH = "http://%s:%s";
|
private static final String HTTP_BATH = "http://%s:%s";
|
||||||
private static final String API_STOP = "/api/stop";
|
|
||||||
|
|
||||||
private static final RestTemplate restTemplateWithTimeOut = new RestTemplate();
|
private static final RestTemplate restTemplateWithTimeOut = new RestTemplate();
|
||||||
private final static int RETRY_COUNT = 3;
|
private final static int RETRY_COUNT = 3;
|
||||||
|
@ -44,22 +37,6 @@ public class TaskRunnerClient {
|
||||||
restTemplateWithTimeOut.setRequestFactory(httpRequestFactory);
|
restTemplateWithTimeOut.setRequestFactory(httpRequestFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void debugApi(String endpoint, TaskRequestDTO taskRequest) throws Exception {
|
|
||||||
post(endpoint + API_DEBUG, taskRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void runApi(String endpoint, TaskRequestDTO taskRequest) throws Exception {
|
|
||||||
post(endpoint + API_RUN, taskRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void batchRunApi(String endpoint, TaskBatchRequestDTO taskRequest) throws Exception {
|
|
||||||
post(endpoint + BATCH_API_RUN, taskRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stopApi(String endpoint, List<String> reportIds) throws Exception {
|
|
||||||
post(endpoint + API_STOP, reportIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getEndpoint(String ip, String port) {
|
public static String getEndpoint(String ip, String port) {
|
||||||
return String.format(HTTP_BATH, ip, port);
|
return String.format(HTTP_BATH, ip, port);
|
||||||
}
|
}
|
||||||
|
@ -78,20 +55,6 @@ public class TaskRunnerClient {
|
||||||
return retry(url, null, action);
|
return retry(url, null, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResultHolder post(String url, Object requestBody, Object... uriVariables) throws Exception {
|
|
||||||
// 定义action
|
|
||||||
Action action = (u, b) -> {
|
|
||||||
String token = totpGenerator.now();
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add(MsHttpHeaders.OTP_TOKEN, token);
|
|
||||||
HttpEntity<Object> httpEntity = new HttpEntity<>(b, headers);
|
|
||||||
ResponseEntity<ResultHolder> entity = restTemplateWithTimeOut.exchange(u, HttpMethod.POST, httpEntity, ResultHolder.class, uriVariables);
|
|
||||||
return entity.getBody();
|
|
||||||
};
|
|
||||||
|
|
||||||
return retry(url, requestBody, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ResultHolder retry(String url, Object requestBody, Action action) throws Exception {
|
private static ResultHolder retry(String url, Object requestBody, Action action) throws Exception {
|
||||||
ResultHolder body;
|
ResultHolder body;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
package io.metersphere.system.service;
|
|
||||||
|
|
||||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
|
||||||
import io.metersphere.system.base.BaseTest;
|
|
||||||
import io.metersphere.system.utils.TaskRunnerClient;
|
|
||||||
import org.junit.jupiter.api.MethodOrderer;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
|
||||||
@AutoConfigureMockMvc
|
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
||||||
public class TaskRunnerClientTest extends BaseTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Value("${embedded.mockserver.host}")
|
|
||||||
private String mockServerHost;
|
|
||||||
@Value("${embedded.mockserver.port}")
|
|
||||||
private Integer mockServerHostPort;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void debugApi() throws Exception {
|
|
||||||
mockPost("/api/debug", "");
|
|
||||||
String endpoint = TaskRunnerClient.getEndpoint(mockServerHost, mockServerHostPort.toString());
|
|
||||||
TaskRunnerClient.debugApi(endpoint, new TaskRequestDTO());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void runApi() throws Exception {
|
|
||||||
mockPost("/api/run", "");
|
|
||||||
String endpoint = TaskRunnerClient.getEndpoint(mockServerHost, mockServerHostPort.toString());
|
|
||||||
TaskRunnerClient.runApi(endpoint, new TaskRequestDTO());
|
|
||||||
}
|
|
||||||
}
|
|
3
pom.xml
3
pom.xml
|
@ -83,6 +83,9 @@
|
||||||
<!-- 用于解析 ${__jexl2} 和 ${__jexl3} 函数变量 -->
|
<!-- 用于解析 ${__jexl2} 和 ${__jexl3} 函数变量 -->
|
||||||
<commons-jexl.version>2.1.1</commons-jexl.version>
|
<commons-jexl.version>2.1.1</commons-jexl.version>
|
||||||
<commons-jexl3.version>3.3</commons-jexl3.version>
|
<commons-jexl3.version>3.3</commons-jexl3.version>
|
||||||
|
<revision>3.x</revision>
|
||||||
|
<monitoring-engine.revision>3.0</monitoring-engine.revision>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|
Loading…
Reference in New Issue