diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/logic/controller/MsLoopController.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/logic/controller/MsLoopController.java index 3e2db23f05..dec46278dc 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/logic/controller/MsLoopController.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/dto/api/request/logic/controller/MsLoopController.java @@ -9,6 +9,5 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @PluginSubType("MsLoopController") public class MsLoopController extends TestElementDTO { - private String clazzName = MsLoopController.class.getCanonicalName(); private String loopType; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/util/ApiDataUtils.java b/backend/services/api-test/src/main/java/io/metersphere/api/util/ApiDataUtils.java index 7f62b474a2..a37fefbb18 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/util/ApiDataUtils.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/util/ApiDataUtils.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.jsontype.NamedType; -import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; import com.fasterxml.jackson.databind.type.CollectionType; import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor; import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler; @@ -24,18 +23,23 @@ public class ApiDataUtils { private ApiDataUtils() { } - private static final ObjectMapper objectMapper = JsonMapper.builder() + private static ObjectMapper objectMapper = JsonMapper.builder() .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS) .build(); - private static final StdSubtypeResolver resolver = new StdSubtypeResolver(); + // 默认内置子组件,如果有新的子组件,需要在这里添加 + static final List namedTypes = new LinkedList<>(); static { - // 添加处理资源文件的类 - final List namedTypes = new LinkedList<>(); + // 默认内置的子组件 namedTypes.add(new NamedType(MsPostJSR223Processor.class, MsPostJSR223Processor.class.getSimpleName())); namedTypes.add(new NamedType(MsDebugSampler.class, MsDebugSampler.class.getSimpleName())); + setObjectMapper(objectMapper); + namedTypes.forEach(objectMapper::registerSubtypes); + } + + private static void setObjectMapper(ObjectMapper objectMapper) { objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 支持json字符中带注释符 objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); @@ -44,8 +48,6 @@ public class ApiDataUtils { // 如果一个对象中没有任何的属性,那么在序列化的时候就会报错 objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); - namedTypes.forEach(resolver::registerSubtypes); - objectMapper.setSubtypeResolver(resolver); } public static String toJSONString(Object value) { @@ -88,11 +90,23 @@ public class ApiDataUtils { /** * 设置动态加载的jar的Resolver * - * @param namedTypes PluginSubType 注解的类 + * @param newTypes PluginSubType 注解的类 */ - public static void setResolver(List namedTypes) { - namedTypes.forEach(resolver::registerSubtypes); - objectMapper.setSubtypeResolver(resolver); + public static void setResolver(List newTypes) { + // 获取所有子组件 TODO:此方法无法卸载组件 + // SubtypeResolver subtypeResolver = objectMapper.getSubtypeResolver(); + // objectMapper.setSubtypeResolver(subtypeResolver); + + objectMapper = JsonMapper.builder() + .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS) + .build(); + setObjectMapper(objectMapper); + + // 加入默认组件 + namedTypes.forEach(objectMapper::registerSubtypes); + // 加入新的动态组件 + newTypes.forEach(objectMapper::registerSubtypes); + } /** @@ -101,7 +115,8 @@ public class ApiDataUtils { * @param clazz PluginSubType 注解的类 */ public static void setResolver(Class clazz) { - resolver.registerSubtypes(clazz); - objectMapper.setSubtypeResolver(resolver); + setResolver(new LinkedList<>()); + // 加入新的动态组件 + objectMapper.registerSubtypes(clazz); } } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java index aaf49ea14e..2f0e35efae 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/PluginSubTypeTests.java @@ -1,7 +1,9 @@ package io.metersphere.api.controller; +import com.fasterxml.jackson.databind.jsontype.NamedType; import io.metersphere.api.util.ApiDataUtils; import io.metersphere.plugin.api.dto.TestElementDTO; +import io.metersphere.sdk.dto.api.request.logic.controller.MsLoopController; import io.metersphere.sdk.dto.api.request.post.processors.MsPostJSR223Processor; import io.metersphere.sdk.dto.api.request.sampler.MsDebugSampler; import io.metersphere.system.uid.IDGenerator; @@ -10,13 +12,15 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.context.SpringBootTest; import java.util.LinkedList; +import java.util.List; -@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @AutoConfigureMockMvc public class PluginSubTypeTests { + @Test @Order(0) public void pluginSubTypeTest() throws Exception { @@ -35,4 +39,44 @@ public class PluginSubTypeTests { TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class); Assertions.assertNotNull(testElementDTO); } + + @Test + @Order(1) + public void resolverTest() throws Exception { + // ApiDataUtils.setResolver(MsLoopController.class); + List namedTypes = new LinkedList<>(); + namedTypes.add(new NamedType(MsLoopController.class, MsLoopController.class.getSimpleName())); + ApiDataUtils.setResolver(namedTypes); + } + + @Test + @Order(2) + public void newPluginSubTypeTest() throws Exception { + MsLoopController loopController = new MsLoopController(); + loopController.setName("测试loopController"); + String json = ApiDataUtils.toJSONString(loopController); + + TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class); + Assertions.assertNotNull(testElementDTO); + + } + + @Test + @Order(3) + public void retrySubTypeTest() throws Exception { + MsDebugSampler debugSampler = new MsDebugSampler(); + debugSampler.setName("测试DebugSampler"); + debugSampler.setUuid(IDGenerator.nextStr()); + LinkedList hashTree = new LinkedList<>(); + hashTree.add(debugSampler); + MsPostJSR223Processor msjsr223Processor = new MsPostJSR223Processor(); + msjsr223Processor.setName("测试jsr223"); + msjsr223Processor.setJsrEnable(true); + msjsr223Processor.setChildren(hashTree); + + String json = ApiDataUtils.toJSONString(msjsr223Processor); + Assertions.assertNotNull(json); + TestElementDTO testElementDTO = ApiDataUtils.parseObject(json, TestElementDTO.class); + Assertions.assertNotNull(testElementDTO); + } }