From a8241727eb16729894b9eec492ad8012bfebde86 Mon Sep 17 00:00:00 2001 From: song-tianyang Date: Thu, 13 May 2021 15:22:43 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20ESB=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96-ESB=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95=EF=BC=8C?= =?UTF-8?q?=E4=BD=BF=E7=94=A8ESB=E6=95=B0=E6=8D=AE=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=B1=95=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ESB功能优化-测试ESB接口时使用ESB数据格式展现 --- .../controller/ApiDefinitionController.java | 5 +- .../api/service/ApiDefinitionService.java | 9 +- .../api/service/EsbApiParamService.java | 36 +- .../api/definition/ApiDefinition.vue | 6 +- .../api/definition/components/ApiConfig.vue | 4 +- .../components/runtest/RunTestTCPPage.vue | 341 ++++++++++-------- 6 files changed, 230 insertions(+), 171 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index 3305ef0075..5821fcbcbd 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -16,6 +16,7 @@ import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.EsbApiParamService; import io.metersphere.api.service.EsbImportService; import io.metersphere.base.domain.ApiDefinition; +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; @@ -100,9 +101,9 @@ public class ApiDefinitionController { @PostMapping(value = "/update", consumes = {"multipart/form-data"}) @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) - public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List bodyFiles) { + public ApiDefinitionWithBLOBs update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List bodyFiles) { checkPermissionService.checkProjectOwner(request.getProjectId()); - apiDefinitionService.update(request, bodyFiles); + return apiDefinitionService.update(request, bodyFiles); } @GetMapping("/delete/{id}") diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 353354ede9..6d32486f75 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -173,7 +173,7 @@ public class ApiDefinitionService { FileUtils.createBodyFiles(bodyUploadIds, bodyFiles); } - public void update(SaveApiDefinitionRequest request, List bodyFiles) { + public ApiDefinitionWithBLOBs update(SaveApiDefinitionRequest request, List bodyFiles) { if (request.getRequest() != null) { deleteFileByTestId(request.getRequest().getId()); } @@ -182,8 +182,9 @@ public class ApiDefinitionService { if (StringUtils.equals(request.getProtocol(), "DUBBO")) { request.setMethod("dubbo://"); } - updateTest(request); + ApiDefinitionWithBLOBs returnModel = updateTest(request); FileUtils.createBodyFiles(bodyUploadIds, bodyFiles); + return returnModel; } public void delete(String apiId) { @@ -274,7 +275,7 @@ public class ApiDefinitionService { } - private ApiDefinition updateTest(SaveApiDefinitionRequest request) { + private ApiDefinitionWithBLOBs updateTest(SaveApiDefinitionRequest request) { checkNameExist(request); if (StringUtils.equals(request.getMethod(), "ESB")) { //ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据 @@ -546,6 +547,8 @@ public class ApiDefinitionService { * @return */ public String run(RunDefinitionRequest request, List bodyFiles) { + //检查是否是ESB请求:ESB请求需要根据数据结构更换参数 + request = esbApiParamService.checkIsEsbRequest(request); int count = 100; BaseSystemConfigDTO dto = systemParameterService.getBaseInfo(); if (StringUtils.isNotEmpty(dto.getConcurrency())) { diff --git a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java index f648cee5aa..f6da5f444c 100644 --- a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java +++ b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java @@ -5,17 +5,16 @@ import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.automation.EsbDataStruct; import io.metersphere.api.dto.automation.SaveApiScenarioRequest; import io.metersphere.api.dto.automation.parse.EsbDataParser; -import io.metersphere.api.dto.definition.ApiDefinitionResult; -import io.metersphere.api.dto.definition.ApiTestCaseResult; -import io.metersphere.api.dto.definition.SaveApiDefinitionRequest; -import io.metersphere.api.dto.definition.SaveApiTestCaseRequest; +import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.MsTestPlan; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.base.domain.ApiTestCaseWithBLOBs; import io.metersphere.base.domain.EsbApiParamsExample; import io.metersphere.base.domain.EsbApiParamsWithBLOBs; import io.metersphere.base.mapper.EsbApiParamsMapper; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -400,4 +399,33 @@ public class EsbApiParamService { } } } + + public RunDefinitionRequest checkIsEsbRequest(RunDefinitionRequest request) { + try { + //修改reqeust.parameters + //用户交互感受:ESB的发送数据以报文模板为主框架,同时前端不再有key-value的表格数据填充。 + //业务逻辑: 发送ESB接口数据时,使用报文模板中的数据,同时报文模板中的${取值}目的是为了拼接数据结构(比如xml的子节点) + //代码实现: 此处打算解析前端传来的EsbDataStruct数据结构,将数据结构按照报文模板中的${取值}为最高优先级组装keyValue对象。这样Jmeter会自动拼装为合适的xml + if(request.getTestElement() != null ){ + MsTestPlan testPlan = (MsTestPlan) request.getTestElement(); + if(CollectionUtils.isNotEmpty(testPlan.getHashTree())){ + for (MsTestElement testElement: testPlan.getHashTree()) { + if(CollectionUtils.isNotEmpty(testElement.getHashTree())){ + for (MsTestElement apiElement:testElement.getHashTree()) { + if(apiElement instanceof MsTCPSampler){ + MsTCPSampler tcpSampler = (MsTCPSampler) apiElement; + tcpSampler.setProtocol("ESB"); + List keyValueList = this.genKeyValueListByDataStruct(tcpSampler, tcpSampler.getEsbDataStruct()); + tcpSampler.setParameters(keyValueList); + } + } + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return request; + } } diff --git a/frontend/src/business/components/api/definition/ApiDefinition.vue b/frontend/src/business/components/api/definition/ApiDefinition.vue index 8fb2f567d0..73b0e0be10 100644 --- a/frontend/src/business/components/api/definition/ApiDefinition.vue +++ b/frontend/src/business/components/api/definition/ApiDefinition.vue @@ -215,7 +215,7 @@ selectDataRange: 'all', showCasePage: true, apiDefaultTab: 'default', - currentProtocol: null, + currentProtocol: 'HTTP', currentModule: null, selectNodeIds: [], currentApi: {}, @@ -260,7 +260,7 @@ }); }, '$route'(to, from) { // 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除 - if (to.path.indexOf('/api/definition') == -1) { + if (to.path.indexOf('/api/definition') === -1) { if (this.$refs && this.$refs.apiConfig) { this.$refs.apiConfig.forEach(item => { item.removeListener(); @@ -299,7 +299,7 @@ }); // 删除所有tab的 ctrl + s 监听 let tabs = this.apiTabs; let index = tabs.findIndex(item => item.name === tab.name); // 找到当前选中tab的index - if (index != -1 && this.$refs.apiConfig[index - 1]) { + if (index !== -1 && this.$refs.apiConfig[index - 1]) { this.$refs.apiConfig[index - 1].addListener(); // 为选中tab添加 ctrl + s 监听(index-1的原因是要除去第一个固有tab) } } diff --git a/frontend/src/business/components/api/definition/components/ApiConfig.vue b/frontend/src/business/components/api/definition/components/ApiConfig.vue index ebbbcdb323..dc758a14d8 100644 --- a/frontend/src/business/components/api/definition/components/ApiConfig.vue +++ b/frontend/src/business/components/api/definition/components/ApiConfig.vue @@ -101,9 +101,11 @@ export default { runTest(data) { this.setParameters(data); let bodyFiles = this.getBodyUploadFiles(data); - this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => { + this.$fileUpload(this.reqUrl, null, bodyFiles, data, response => { this.$success(this.$t('commons.save_success')); this.reqUrl = "/api/definition/update"; + let newData = response.data; + data.request = JSON.parse(newData.request); this.$emit('runTest', data); }); }, diff --git a/frontend/src/business/components/api/definition/components/runtest/RunTestTCPPage.vue b/frontend/src/business/components/api/definition/components/runtest/RunTestTCPPage.vue index a7ce56b098..e1c87cc9a7 100644 --- a/frontend/src/business/components/api/definition/components/runtest/RunTestTCPPage.vue +++ b/frontend/src/business/components/api/definition/components/runtest/RunTestTCPPage.vue @@ -26,19 +26,32 @@ -

{{$t('api_test.definition.request.req_param')}}

- - + + + + +
+

{{ $t('api_test.definition.request.req_param') }}

+ + + +

{{$t('api_test.definition.request.res_param')}}

+ +
+
+

{{ $t('api_test.definition.request.req_param') }}

+ +
- - -

{{$t('api_test.definition.request.res_param')}}

- - +
+

{{$t('api_test.definition.request.res_param')}}

+ +
+ @@ -65,7 +78,9 @@ import MsBasisParameters from "../request/tcp/TcpBasisParameters"; import {REQ_METHOD} from "../../model/JsonData"; import EnvironmentSelect from "../environment/EnvironmentSelect"; import MsJmxStep from "../step/JmxStep"; - +const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/); +const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinition.vue") : {}; +const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {}; export default { name: "RunTestTCPPage", components: { @@ -77,168 +92,178 @@ export default { MsBottomContainer, MsRequestResultTail, MsRun, - MsBasisParameters - }, - data() { - return { - visible: false, - api: {}, - loaded: false, - loading: false, - currentRequest: {}, - responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []}, - reqOptions: REQ_METHOD, - environments: [], - refreshSign: "", - createCase: "", - rules: { - environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}], - }, - runData: [], - reportId: "", + MsBasisParameters, + "esbDefinition": esbDefinition.default, + "esbDefinitionResponse": esbDefinitionResponse.default + }, + data() { + return { + visible: false, + api: {}, + loaded: false, + loading: false, + currentRequest: {}, + responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []}, + reqOptions: REQ_METHOD, + environments: [], + refreshSign: "", + createCase: "", + rules: { + environmentId: [{required: true, message: this.$t('api_test.definition.request.run_env'), trigger: 'change'}], + }, + runData: [], + reportId: "", + showXpackCompnent:false, + } + }, + props: {apiData: {}, currentProtocol: String,syncTabs: Array, projectId: String}, + methods: { + handleCommand(e) { + switch (e) { + case "load_case": + return this.loadCase(); + case "save_as_case": + return this.saveAsCase(); + case "update_api": + return this.updateApi(); + case "save_as_api": + return this.saveAsApi(); + default: + return this.$refs['requestForm'].validate(); } }, - props: {apiData: {}, currentProtocol: String,syncTabs: Array, projectId: String}, - methods: { - handleCommand(e) { - switch (e) { - case "load_case": - return this.loadCase(); - case "save_as_case": - return this.saveAsCase(); - case "update_api": - return this.updateApi(); - case "save_as_api": - return this.saveAsApi(); - default: - return this.$refs['requestForm'].validate(); + refresh(){ + this.$emit('refresh'); + }, + runTest() { + this.$refs['apiData'].validate((valid) => { + if (valid) { + this.loading = true; + this.api.request.name = this.api.id; + this.api.protocol = this.currentProtocol; + this.runData = []; + this.runData.push(this.api.request); + /*触发执行操作*/ + this.reportId = getUUID().substring(0, 8); } - }, - refresh(){ - this.$emit('refresh'); - }, - runTest() { - this.$refs['apiData'].validate((valid) => { - if (valid) { - this.loading = true; - this.api.request.name = this.api.id; - this.api.protocol = this.currentProtocol; - this.runData = []; - this.runData.push(this.api.request); - /*触发执行操作*/ - this.reportId = getUUID().substring(0, 8); - } - }) - }, - runRefresh(data) { - this.responseData = data; - this.loading = false; - }, - saveAs() { - this.$emit('saveAs', this.api); - }, - loadCase() { - this.refreshSign = getUUID(); - this.$refs.caseList.open(); - this.visible = true; - }, - apiCaseClose() { - this.visible = false; - }, - getBodyUploadFiles() { - let bodyUploadFiles = []; - this.api.bodyUploadIds = []; - let request = this.api.request; - if (request.body) { - request.body.kvs.forEach(param => { - if (param.files) { - param.files.forEach(item => { - if (item.file) { - let fileId = getUUID().substring(0, 8); - item.name = item.file.name; - item.id = fileId; - this.api.bodyUploadIds.push(fileId); - bodyUploadFiles.push(item.file); - } - }); - } - }); - } - return bodyUploadFiles; - }, - saveAsCase() { - this.createCase = getUUID(); - this.$refs.caseList.open(); - this.loaded = false; - }, - saveAsApi() { - let data = {}; - let req = this.api.request; - req.id = getUUID(); - data.request = JSON.stringify(req); - data.method = this.api.method; - data.status = this.api.status; - data.userId = this.api.userId; - data.description = this.api.description; - this.$emit('saveAsApi', data); - this.$emit('refresh'); - }, - updateApi() { - let url = "/api/definition/update"; - let bodyFiles = this.getBodyUploadFiles(); - this.$fileUpload(url, null, bodyFiles, this.api, () => { - this.$success(this.$t('commons.save_success')); - if (this.syncTabs.indexOf(this.api.id) === -1) { - this.syncTabs.push(this.api.id); - } - this.$emit('saveApi', this.api); - }); - }, - selectTestCase(item) { - if (item != null) { - this.api.request = item.request; - } else { - this.api.request = this.currentRequest; - } - }, - getResult() { - let url = "/api/definition/report/getReport/" + this.api.id; - this.$get(url, response => { - if (response.data) { - let data = JSON.parse(response.data.content); - this.responseData = data; + }) + }, + runRefresh(data) { + this.responseData = data; + this.loading = false; + }, + saveAs() { + this.$emit('saveAs', this.api); + }, + loadCase() { + this.refreshSign = getUUID(); + this.$refs.caseList.open(); + this.visible = true; + }, + apiCaseClose() { + this.visible = false; + }, + getBodyUploadFiles() { + let bodyUploadFiles = []; + this.api.bodyUploadIds = []; + let request = this.api.request; + if (request.body) { + request.body.kvs.forEach(param => { + if (param.files) { + param.files.forEach(item => { + if (item.file) { + let fileId = getUUID().substring(0, 8); + item.name = item.file.name; + item.id = fileId; + this.api.bodyUploadIds.push(fileId); + bodyUploadFiles.push(item.file); + } + }); } }); } + return bodyUploadFiles; }, - created() { - // 深度复制 - this.api = JSON.parse(JSON.stringify(this.apiData)); - this.api.protocol = this.currentProtocol; - this.currentRequest = this.api.request; - this.getResult(); + saveAsCase() { + this.createCase = getUUID(); + this.$refs.caseList.open(); + this.loaded = false; + }, + saveAsApi() { + let data = {}; + let req = this.api.request; + req.id = getUUID(); + data.request = JSON.stringify(req); + data.method = this.api.method; + data.status = this.api.status; + data.userId = this.api.userId; + data.description = this.api.description; + this.$emit('saveAsApi', data); + this.$emit('refresh'); + }, + updateApi() { + let url = "/api/definition/update"; + let bodyFiles = this.getBodyUploadFiles(); + if(this.api.method==='ESB'){ + this.api.esbDataStruct = JSON.stringify(this.api.request.esbDataStruct); + this.api.backEsbDataStruct = JSON.stringify(this.api.request.backEsbDataStruct); + } + this.$fileUpload(url, null, bodyFiles, this.api, () => { + this.$success(this.$t('commons.save_success')); + if (this.syncTabs.indexOf(this.api.id) === -1) { + this.syncTabs.push(this.api.id); + } + this.$emit('saveApi', this.api); + }); + }, + selectTestCase(item) { + if (item != null) { + this.api.request = item.request; + } else { + this.api.request = this.currentRequest; + } + }, + getResult() { + let url = "/api/definition/report/getReport/" + this.api.id; + this.$get(url, response => { + if (response.data) { + let data = JSON.parse(response.data.content); + this.responseData = data; + } + }); + } + }, + created() { + // 深度复制 + this.api = JSON.parse(JSON.stringify(this.apiData)); + this.api.protocol = this.currentProtocol; + this.currentRequest = this.api.request; + this.getResult(); + if (requireComponent != null && JSON.stringify(esbDefinition) !== '{}') { + this.showXpackCompnent = true; } } +}