build: 动态解析插件数据
This commit is contained in:
parent
931c7c7e1b
commit
4610d0919e
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.plugin.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PluginSubType {
|
||||
String value();
|
||||
}
|
|
@ -4,25 +4,22 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.metersphere.plugin.util.PluginLogUtils;
|
||||
import lombok.Data;
|
||||
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.apache.jorphan.collections.ListedHashTree;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "clazzName")
|
||||
@Data
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public abstract class TestElementDTO {
|
||||
public abstract class TestElementDTO implements Serializable {
|
||||
// 组件类型
|
||||
private String type;
|
||||
|
||||
// 用于数据反射对象
|
||||
private String clazzName = TestElementDTO.class.getCanonicalName();
|
||||
|
||||
// 当前组件唯一标示
|
||||
private String uuid;
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.api.dto.jmeter.processors;
|
||||
|
||||
import io.metersphere.plugin.annotation.PluginSubType;
|
||||
import io.metersphere.plugin.api.dto.BaseConfigDTO;
|
||||
import io.metersphere.plugin.api.dto.TestElementDTO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@PluginSubType("MSJSR223Processor")
|
||||
public class MSJSR223Processor extends TestElementDTO {
|
||||
private String script;
|
||||
private String scriptLanguage;
|
||||
private Boolean jsrEnable;
|
||||
|
||||
@Override
|
||||
public void toHashTree(HashTree tree, List<TestElementDTO> hashTree, BaseConfigDTO baseConfig) {
|
||||
if (!this.isEnable()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package io.metersphere.api.dto.jmeter.sampler;
|
||||
|
||||
import io.metersphere.plugin.annotation.PluginSubType;
|
||||
import io.metersphere.plugin.api.dto.BaseConfigDTO;
|
||||
import io.metersphere.plugin.api.dto.TestElementDTO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.sampler.DebugSampler;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@PluginSubType("MSDebugSampler")
|
||||
public class MSDebugSampler extends TestElementDTO {
|
||||
private boolean displayJMeterProperties = false;
|
||||
private boolean displayJMeterVariables = true;
|
||||
private boolean displaySystemProperties = false;
|
||||
|
||||
@Override
|
||||
public void toHashTree(HashTree tree, List<TestElementDTO> hashTree, BaseConfigDTO configDTO) {
|
||||
BaseConfigDTO config = (BaseConfigDTO) configDTO;
|
||||
// 非导出操作,且不是启用状态则跳过执行
|
||||
if (!this.isEnable()) {
|
||||
return;
|
||||
}
|
||||
final HashTree groupTree = tree.add(debugSampler());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
// 给所有孩子加一个父亲标志
|
||||
el.setParent(this);
|
||||
el.toHashTree(groupTree, el.getHashTree(), config);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private DebugSampler debugSampler() {
|
||||
DebugSampler debugSampler = new DebugSampler();
|
||||
debugSampler.setEnabled(this.isEnable());
|
||||
if (StringUtils.isEmpty(this.getName())) {
|
||||
this.setName(MSDebugSampler.class.getSimpleName());
|
||||
}
|
||||
debugSampler.setName(this.getName());
|
||||
debugSampler.setProperty(TestElement.TEST_CLASS, DebugSampler.class.getName());
|
||||
debugSampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||
|
||||
debugSampler.setDisplaySystemProperties(this.displaySystemProperties);
|
||||
debugSampler.setDisplayJMeterVariables(this.displayJMeterVariables);
|
||||
debugSampler.setDisplayJMeterProperties(this.displayJMeterProperties);
|
||||
|
||||
//上面三行直接Set属性会导致DebugSampler构建时取不到值,可能是JMeter的Bug,需要SetProperty
|
||||
debugSampler.setProperty("displayJMeterProperties", this.displayJMeterProperties);
|
||||
debugSampler.setProperty("displayJMeterVariables", this.displayJMeterVariables);
|
||||
debugSampler.setProperty("displaySystemProperties", this.displaySystemProperties);
|
||||
return debugSampler;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package io.metersphere.api.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
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.api.dto.jmeter.processors.MSJSR223Processor;
|
||||
import io.metersphere.api.dto.jmeter.sampler.MSDebugSampler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class JSONUtils {
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static StdSubtypeResolver resolver = new StdSubtypeResolver();
|
||||
|
||||
static {
|
||||
// 添加处理资源文件的类
|
||||
final List<NamedType> namedTypes = new LinkedList<>();
|
||||
namedTypes.add(new NamedType(MSJSR223Processor.class, MSJSR223Processor.class.getSimpleName()));
|
||||
namedTypes.add(new NamedType(MSDebugSampler.class, MSDebugSampler.class.getSimpleName()));
|
||||
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
// 自动检测所有类的全部属性
|
||||
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
||||
// 如果一个对象中没有任何的属性,那么在序列化的时候就会报错
|
||||
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
|
||||
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||
namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType));
|
||||
objectMapper.setSubtypeResolver(resolver);
|
||||
}
|
||||
|
||||
public static String toJSONString(Object value) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(value);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object parseObject(String content) {
|
||||
return parseObject(content, Object.class);
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String content, Class<T> valueType) {
|
||||
try {
|
||||
return objectMapper.readValue(content, valueType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(InputStream src, Class<T> valueType) {
|
||||
try {
|
||||
return objectMapper.readValue(src, valueType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String content, TypeReference<T> valueType) {
|
||||
try {
|
||||
return objectMapper.readValue(content, valueType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List parseArray(String content) {
|
||||
return parseArray(content, Object.class);
|
||||
}
|
||||
|
||||
public static <T> List<T> parseArray(String content, Class<T> valueType) {
|
||||
CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, valueType);
|
||||
try {
|
||||
return objectMapper.readValue(content, javaType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置动态加载的jar的Resolver
|
||||
*
|
||||
* @param namedTypes
|
||||
*/
|
||||
public static void setResolver(List<NamedType> namedTypes) {
|
||||
namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType));
|
||||
objectMapper.setSubtypeResolver(resolver);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import io.metersphere.api.dto.jmeter.processors.MSJSR223Processor;
|
||||
import io.metersphere.api.dto.jmeter.sampler.MSDebugSampler;
|
||||
import io.metersphere.api.util.JSONUtils;
|
||||
import io.metersphere.plugin.api.dto.TestElementDTO;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@SpringBootTest
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class PluginSubTypeTests {
|
||||
|
||||
@Test
|
||||
@Order(0)
|
||||
public void pluginSubTypeTest() throws Exception {
|
||||
MSDebugSampler debugSampler = new MSDebugSampler();
|
||||
debugSampler.setName("测试DebugSampler");
|
||||
debugSampler.setUuid(UUID.randomUUID().toString());
|
||||
LinkedList<TestElementDTO> hashTree = new LinkedList<>();
|
||||
hashTree.add(debugSampler);
|
||||
MSJSR223Processor msjsr223Processor = new MSJSR223Processor();
|
||||
msjsr223Processor.setName("测试jsr223");
|
||||
msjsr223Processor.setJsrEnable(true);
|
||||
msjsr223Processor.setHashTree(hashTree);
|
||||
|
||||
String json = JSONUtils.toJSONString(msjsr223Processor);
|
||||
Assertions.assertNotNull(json);
|
||||
TestElementDTO testElementDTO = JSONUtils.parseObject(json, TestElementDTO.class);
|
||||
Assertions.assertNotNull(testElementDTO);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue