Commit a326c7fd authored by song-tianyang's avatar song-tianyang Committed by 刘瑞斌
Browse files

feat(TCPMock服务): 参考HTTP MOCK功能新增TCP MOCK功能#1001753

https://www.tapd.cn/55049933/prong/stories/view/1155049933001001753#
parent 54ba05d9
Showing with 1107 additions and 195 deletions
+1107 -195
......@@ -292,12 +292,7 @@ public class ApiDefinitionController {
@GetMapping("/getMockEnvironment/{projectId}/{protocal}")
public ApiTestEnvironmentWithBLOBs getMockEnvironment(@PathVariable String projectId, @PathVariable String protocal, HttpServletRequest request) {
String requestUrl = request.getRequestURL().toString();
String baseUrl = "";
if (requestUrl.contains("/api/definition")) {
baseUrl = requestUrl.split("/api/definition")[0];
}
return apiTestEnvironmentService.getMockEnvironmentByProjectId(projectId, protocal, baseUrl);
return apiTestEnvironmentService.getMockEnvironmentByProjectId(projectId);
}
}
......@@ -86,4 +86,8 @@ public class ApiTestEnvironmentController {
apiTestEnvironmentService.delete(id);
}
@GetMapping("/getTcpMockInfo/{projectId}")
public String getMockInfo(@PathVariable(value = "projectId") String projectId) {
return apiTestEnvironmentService.getMockInfo(projectId);
}
}
......@@ -2,6 +2,7 @@ package io.metersphere.api.dto.automation;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
......@@ -177,4 +178,22 @@ public class EsbDataStruct {
}
return element;
}
public List<String> getNameDeep() {
List<String> returnList = new ArrayList<>();
if(StringUtils.isNotEmpty(this.name)){
returnList.add(this.name);
}
if(CollectionUtils.isNotEmpty(this.children)){
for (EsbDataStruct child :this.children) {
List<String> itemNameList = child.getNameDeep();
for (String itemName :itemNameList) {
if(!returnList.contains(itemName)){
returnList.add(itemName);
}
}
}
}
return returnList;
}
}
......@@ -2,6 +2,7 @@ package io.metersphere.api.dto.automation;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
......@@ -11,7 +12,7 @@ import java.util.List;
import java.util.UUID;
/**
* //ESB数据格式
* 树形表格数据格式
*
* @author song.tianyang
* @Date 2021/3/15 4:37 下午
......@@ -181,4 +182,22 @@ public class TcpTreeTableDataStruct {
}
return element;
}
public List<String> getNameDeep() {
List<String> returnList = new ArrayList<>();
if(StringUtils.isNotEmpty(this.name)){
returnList.add(this.name);
}
if(CollectionUtils.isNotEmpty(this.children)){
for (TcpTreeTableDataStruct child :this.children) {
List<String> itemNameList = child.getNameDeep();
for (String itemName :itemNameList) {
if(!returnList.contains(itemName)){
returnList.add(itemName);
}
}
}
}
return returnList;
}
}
......@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestEnvironmentDTO;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.tcp.TCPPool;
import io.metersphere.base.domain.ApiTestEnvironmentExample;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.domain.Project;
......@@ -138,10 +139,12 @@ public class ApiTestEnvironmentService {
* @param projectId
* @return
*/
public synchronized ApiTestEnvironmentWithBLOBs getMockEnvironmentByProjectId(String projectId, String protocal, String baseUrl) {
//创建的时候检查当前站点
public synchronized ApiTestEnvironmentWithBLOBs getMockEnvironmentByProjectId(String projectId) {
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
String baseUrl = baseSystemConfigDTO.getUrl();
String protocal = "http";
if (baseSystemConfigDTO != null && StringUtils.isNotEmpty(baseSystemConfigDTO.getUrl())) {
baseUrl = baseSystemConfigDTO.getUrl();
if (baseUrl.startsWith("http:")) {
......@@ -170,6 +173,8 @@ public class ApiTestEnvironmentService {
private ApiTestEnvironmentWithBLOBs checkMockEvnIsRightful(ApiTestEnvironmentWithBLOBs returnModel, String protocal, String projectId,String projectNumber, String name, String url) {
boolean needUpdate = false;
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
Project project = projectService.getProjectById(projectId);
if (returnModel.getConfig() != null) {
try {
JSONObject configObj = JSONObject.parseObject(returnModel.getConfig());
......@@ -207,6 +212,26 @@ public class ApiTestEnvironmentService {
}
}
}
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
if(configObj.containsKey("tcpConfig")){
if(configObj.containsKey("port")){
if(configObj.getInteger("port").intValue() != project.getMockTcpPort().intValue()){
needUpdate = true;
}
}else {
needUpdate = true;
}
if(configObj.containsKey("server")){
if(!StringUtils.equals(configObj.getString("server"),url)){
needUpdate = true;
}
}else {
needUpdate = true;
}
}
}
} catch (Exception e) {
needUpdate = true;
e.printStackTrace();
......@@ -214,21 +239,35 @@ public class ApiTestEnvironmentService {
}
if (needUpdate) {
String id = returnModel.getId();
returnModel = this.genHttpApiTestEnvironmentByUrl(projectId,projectNumber, protocal, name, url);
returnModel = this.genHttpApiTestEnvironmentByUrl(project,projectNumber, protocal, name, url);
returnModel.setId(id);
apiTestEnvironmentMapper.updateByPrimaryKeyWithBLOBs(returnModel);
}
return returnModel;
}
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(String projectId,String projectNumber, String protocal, String name, String url) {
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(String projectId,String projectNumber, String protocal, String name, String baseUrl) {
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
Project project = projectService.getProjectById(projectId);
if(project != null){
return this.genHttpApiTestEnvironmentByUrl(project,projectNumber, protocal, name, baseUrl);
}
return null;
}
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(Project project,String projectNumber, String protocal, String name, String baseUrl) {
String socket = "";
String url = baseUrl;
if (url.startsWith("http://")) {
url = url.substring(7);
} else if (url.startsWith("https://")) {
url = url.substring(8);
}
socket = url;
String tcpSocket = socket;
if(StringUtils.isNotEmpty(tcpSocket) && tcpSocket.contains(":")){
tcpSocket = socket.split(":")[0];
}
String portStr = "";
String ipStr = url;
......@@ -301,6 +340,10 @@ public class ApiTestEnvironmentService {
tcpConfigObj.put("reUseConnection", false);
tcpConfigObj.put("nodelay", false);
tcpConfigObj.put("closeConnection", false);
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
tcpConfigObj.put("server", tcpSocket);
tcpConfigObj.put("port", 12138);
}
JSONObject object = new JSONObject();
object.put("commonConfig", commonConfigObj);
......@@ -309,7 +352,7 @@ public class ApiTestEnvironmentService {
object.put("tcpConfig", tcpConfigObj);
ApiTestEnvironmentWithBLOBs blobs = new ApiTestEnvironmentWithBLOBs();
blobs.setProjectId(projectId);
blobs.setProjectId(project.getId());
blobs.setName(name);
blobs.setConfig(object.toString());
......@@ -353,4 +396,36 @@ public class ApiTestEnvironmentService {
}
return null;
}
public String getMockInfo(String projectId) {
String returnStr = "";
ApiTestEnvironmentWithBLOBs mockEnv = this.getMockEnvironmentByProjectId(projectId);
if (mockEnv != null && mockEnv.getConfig() != null) {
try {
JSONObject configObj = JSONObject.parseObject(mockEnv.getConfig());
if(configObj.containsKey("tcpConfig")){
JSONObject tcpConfigObj = configObj.getJSONObject("tcpConfig");
int tcpPort = 0;
if(tcpConfigObj.containsKey("port")){
tcpPort = tcpConfigObj.getInteger("port").intValue();
if(tcpPort == 0 || !TCPPool.isTcpOpen(tcpPort)){
return returnStr;
}
}else {
return returnStr;
}
if(tcpConfigObj.containsKey("server")){
String server = tcpConfigObj.getString("server");
returnStr = server +":"+ tcpPort;
}else {
return returnStr;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
return returnStr;
}
}
package io.metersphere.api.tcp;
import io.metersphere.api.tcp.server.TCPServer;
import io.metersphere.commons.exception.MSException;
import java.util.HashMap;
import java.util.Map;
/**
* @author song.tianyang
* @Date 2021/8/10 3:04 下午
*/
public class TCPPool {
private static HashMap<Integer, TCPServer> serverSockedMap = new HashMap<>();
private TCPPool(){}
public static String createTcp(int port){
String returnString = "";
TCPServer tcpServer = null;
if(serverSockedMap.containsKey(port)){
tcpServer = serverSockedMap.get(port);
}else {
tcpServer = new TCPServer(port);
serverSockedMap.put(port,tcpServer);
}
try {
if(!tcpServer.isSocketOpen()){
Thread t = new Thread(tcpServer);
t.start();
}
returnString = "OK";
}catch (Exception e){
returnString = e.getMessage();
e.printStackTrace();
MSException.throwException(e.getMessage());
}
return returnString;
}
public static boolean isTcpOpen(int port){
TCPServer server = serverSockedMap.get(port);
if(server != null ){
return server.isSocketOpen();
}
return false;
}
public static String getTcpStatus() {
if(serverSockedMap.isEmpty()){
return "null";
}else {
StringBuffer stringBuffer = new StringBuffer();
for (Map.Entry<Integer, TCPServer> entry:serverSockedMap.entrySet()) {
int port = entry.getKey();
TCPServer tcpServer = entry.getValue();
if(tcpServer == null){
stringBuffer.append("Port is "+port + ";");
stringBuffer.append("Server is null;");
}else {
stringBuffer.append("Port is "+port + ";");
stringBuffer.append("Server is open: "+ tcpServer.isSocketOpen());
}
}
return stringBuffer.toString();
}
}
public static String closeTcp(int portNum) {
TCPServer server = serverSockedMap.get(portNum);
if(server == null){
return "Tcp Is not create!";
}else {
String returnMsg = null;
try {
server.closeSocket();
returnMsg = "OK";
}catch (Exception e){
returnMsg = e.getMessage();
e.printStackTrace();
}
return returnMsg;
}
}
}
package io.metersphere.api.tcp.server;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author song.tianyang
* @Date 2021/8/11 10:35 上午
*/
public class TCPServer implements Runnable {
private int port;
private ServerSocket serverSocket;
private TCPServicer servicer;
public TCPServer(int port){
this.port = port;
}
public void openSocket() throws Exception {
this.serverSocket = new ServerSocket(this.port);
int connectIndex = 0;
while (true) {
if (!this.serverSocket.isClosed()) {
Socket socket = this.serverSocket.accept();
servicer = new TCPServicer(socket,port);
servicer.run();
}
if (this.serverSocket.isClosed()) {
break;
}
}
}
public boolean isSocketOpen(){
if (this.serverSocket != null && !this.serverSocket.isClosed()) {
return true;
}else {
return false;
}
}
public void closeSocket() throws Exception {
if (this.serverSocket != null && !this.serverSocket.isClosed()) {
if(servicer != null){
servicer.close();
}
this.serverSocket.close();
}
}
@Override
public void run() {
try {
this.openSocket();
} catch (Exception e) {
}
}
}
package io.metersphere.api.tcp.server;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.service.MockConfigService;
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
import io.metersphere.commons.utils.CommonBeanFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPServicer {
private Socket s;
private InputStream is;
private OutputStream os;
private int port;
public TCPServicer(Socket s, int port) {
this.s = s;
this.port = port;
}
public void run() {
byte[] b = new byte[1024];
String returnMsg = "";
String message = "";
try {
is = s.getInputStream();
os = s.getOutputStream();
int len = is.read(b);
message = new String(b,0,len);
// } catch (Exception e) {
// e.printStackTrace();
// }
returnMsg = this.getReturnMsg(message);
// try {
os.write(returnMsg.getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
this.close();
}
//关闭资源
// this.close();
}
private String getReturnMsg(String message) {
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
MockExpectConfigWithBLOBs matchdMockExpect = mockConfigService.matchTcpMockExpect(message,this.port);
String response = matchdMockExpect.getResponse();
JSONObject responseObj = JSONObject.parseObject(response);
try {
int delayed = responseObj.getInteger("delayed");
Thread.sleep(delayed);
} catch (InterruptedException e) {
e.printStackTrace();
}
String returnMsg = responseObj.getString("body");
return returnMsg;
}
public void close() {
//关闭资源
try{
is.close();
}catch (Exception e){}finally {
try{
os.close();
}catch (Exception e){}finally {
try{
s.close();
}catch (Exception e){}finally {
}
}
}
}
}
\ No newline at end of file
......@@ -39,5 +39,9 @@ public class Project implements Serializable {
private String systemId;
private Integer mockTcpPort;
private Boolean isMockTcpOpen;
private static final long serialVersionUID = 1L;
}
\ No newline at end of file
......@@ -1243,6 +1243,126 @@ public class ProjectExample {
addCriterion("system_id not between", value1, value2, "systemId");
return (Criteria) this;
}
public Criteria andMockTcpPortIsNull() {
addCriterion("mock_tcp_port is null");
return (Criteria) this;
}
public Criteria andMockTcpPortIsNotNull() {
addCriterion("mock_tcp_port is not null");
return (Criteria) this;
}
public Criteria andMockTcpPortEqualTo(Integer value) {
addCriterion("mock_tcp_port =", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortNotEqualTo(Integer value) {
addCriterion("mock_tcp_port <>", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortGreaterThan(Integer value) {
addCriterion("mock_tcp_port >", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortGreaterThanOrEqualTo(Integer value) {
addCriterion("mock_tcp_port >=", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortLessThan(Integer value) {
addCriterion("mock_tcp_port <", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortLessThanOrEqualTo(Integer value) {
addCriterion("mock_tcp_port <=", value, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortIn(List<Integer> values) {
addCriterion("mock_tcp_port in", values, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortNotIn(List<Integer> values) {
addCriterion("mock_tcp_port not in", values, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortBetween(Integer value1, Integer value2) {
addCriterion("mock_tcp_port between", value1, value2, "mockTcpPort");
return (Criteria) this;
}
public Criteria andMockTcpPortNotBetween(Integer value1, Integer value2) {
addCriterion("mock_tcp_port not between", value1, value2, "mockTcpPort");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenIsNull() {
addCriterion("is_mock_tcp_open is null");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenIsNotNull() {
addCriterion("is_mock_tcp_open is not null");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenEqualTo(Boolean value) {
addCriterion("is_mock_tcp_open =", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenNotEqualTo(Boolean value) {
addCriterion("is_mock_tcp_open <>", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenGreaterThan(Boolean value) {
addCriterion("is_mock_tcp_open >", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenGreaterThanOrEqualTo(Boolean value) {
addCriterion("is_mock_tcp_open >=", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenLessThan(Boolean value) {
addCriterion("is_mock_tcp_open <", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenLessThanOrEqualTo(Boolean value) {
addCriterion("is_mock_tcp_open <=", value, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenIn(List<Boolean> values) {
addCriterion("is_mock_tcp_open in", values, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenNotIn(List<Boolean> values) {
addCriterion("is_mock_tcp_open not in", values, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenBetween(Boolean value1, Boolean value2) {
addCriterion("is_mock_tcp_open between", value1, value2, "isMockTcpOpen");
return (Criteria) this;
}
public Criteria andIsMockTcpOpenNotBetween(Boolean value1, Boolean value2) {
addCriterion("is_mock_tcp_open not between", value1, value2, "isMockTcpOpen");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
......
......@@ -19,6 +19,8 @@
<result column="scenario_custom_num" jdbcType="BIT" property="scenarioCustomNum" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="system_id" jdbcType="VARCHAR" property="systemId" />
<result column="mock_tcp_port" jdbcType="INTEGER" property="mockTcpPort" />
<result column="is_mock_tcp_open" jdbcType="BIT" property="isMockTcpOpen" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
......@@ -81,7 +83,7 @@
<sql id="Base_Column_List">
id, workspace_id, `name`, description, create_time, update_time, tapd_id, jira_key,
zentao_id, azure_devops_id, `repeatable`, case_template_id, issue_template_id, custom_num,
scenario_custom_num, create_user, system_id
scenario_custom_num, create_user, system_id, mock_tcp_port, is_mock_tcp_open
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultMap="BaseResultMap">
select
......@@ -119,13 +121,15 @@
tapd_id, jira_key, zentao_id,
azure_devops_id, `repeatable`, case_template_id,
issue_template_id, custom_num, scenario_custom_num,
create_user, system_id)
create_user, system_id, mock_tcp_port,
is_mock_tcp_open)
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{tapdId,jdbcType=VARCHAR}, #{jiraKey,jdbcType=VARCHAR}, #{zentaoId,jdbcType=VARCHAR},
#{azureDevopsId,jdbcType=VARCHAR}, #{repeatable,jdbcType=BIT}, #{caseTemplateId,jdbcType=VARCHAR},
#{issueTemplateId,jdbcType=VARCHAR}, #{customNum,jdbcType=BIT}, #{scenarioCustomNum,jdbcType=BIT},
#{createUser,jdbcType=VARCHAR}, #{systemId,jdbcType=VARCHAR})
#{createUser,jdbcType=VARCHAR}, #{systemId,jdbcType=VARCHAR}, #{mockTcpPort,jdbcType=INTEGER},
#{isMockTcpOpen,jdbcType=BIT})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.Project">
insert into project
......@@ -181,6 +185,12 @@
<if test="systemId != null">
system_id,
</if>
<if test="mockTcpPort != null">
mock_tcp_port,
</if>
<if test="isMockTcpOpen != null">
is_mock_tcp_open,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
......@@ -234,6 +244,12 @@
<if test="systemId != null">
#{systemId,jdbcType=VARCHAR},
</if>
<if test="mockTcpPort != null">
#{mockTcpPort,jdbcType=INTEGER},
</if>
<if test="isMockTcpOpen != null">
#{isMockTcpOpen,jdbcType=BIT},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultType="java.lang.Long">
......@@ -296,6 +312,12 @@
<if test="record.systemId != null">
system_id = #{record.systemId,jdbcType=VARCHAR},
</if>
<if test="record.mockTcpPort != null">
mock_tcp_port = #{record.mockTcpPort,jdbcType=INTEGER},
</if>
<if test="record.isMockTcpOpen != null">
is_mock_tcp_open = #{record.isMockTcpOpen,jdbcType=BIT},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
......@@ -319,7 +341,9 @@
custom_num = #{record.customNum,jdbcType=BIT},
scenario_custom_num = #{record.scenarioCustomNum,jdbcType=BIT},
create_user = #{record.createUser,jdbcType=VARCHAR},
system_id = #{record.systemId,jdbcType=VARCHAR}
system_id = #{record.systemId,jdbcType=VARCHAR},
mock_tcp_port = #{record.mockTcpPort,jdbcType=INTEGER},
is_mock_tcp_open = #{record.isMockTcpOpen,jdbcType=BIT}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
......@@ -375,6 +399,12 @@
<if test="systemId != null">
system_id = #{systemId,jdbcType=VARCHAR},
</if>
<if test="mockTcpPort != null">
mock_tcp_port = #{mockTcpPort,jdbcType=INTEGER},
</if>
<if test="isMockTcpOpen != null">
is_mock_tcp_open = #{isMockTcpOpen,jdbcType=BIT},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
......@@ -395,7 +425,9 @@
custom_num = #{customNum,jdbcType=BIT},
scenario_custom_num = #{scenarioCustomNum,jdbcType=BIT},
create_user = #{createUser,jdbcType=VARCHAR},
system_id = #{systemId,jdbcType=VARCHAR}
system_id = #{systemId,jdbcType=VARCHAR},
mock_tcp_port = #{mockTcpPort,jdbcType=INTEGER},
is_mock_tcp_open = #{isMockTcpOpen,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>
\ No newline at end of file
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
import java.util.List;
public interface ExtMockExpectConfigMapper {
List<MockExpectConfigWithBLOBs> selectByProjectIdAndStatusIsOpen(String projectId);
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtMockExpectConfigMapper">
<select id="selectByProjectIdAndStatusIsOpen" resultType="io.metersphere.base.domain.MockExpectConfigWithBLOBs">
SELECT * FROM mock_expect_config WHERE status = 'true' AND mock_config_id IN
(SELECT id FROM mock_config WHERE api_path IS NULL AND project_id = #{0} )
</select>
</mapper>
\ No newline at end of file
......@@ -34,7 +34,7 @@
<select id="getProjectWithWorkspace" resultType="io.metersphere.dto.ProjectDTO">
select p.id, p.workspace_id, p.name, p.description, p.update_time, p.issue_template_id, p.case_template_id,
p.create_time, w.id as workspaceId, w.name as workspaceName, p.tapd_id, p.jira_key, p.zentao_id,p.azure_devops_id,p.repeatable, p.custom_num,
user.name as createUserName,
user.name as createUserName,p.mock_tcp_port AS mockTcpPort,p.is_mock_tcp_open AS isMockTcpOpen,
p.scenario_custom_num
from project p
join workspace w on p.workspace_id = w.id
......
package io.metersphere.commons.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import org.apache.commons.lang3.StringUtils;
......@@ -131,116 +130,4 @@ public class JsonPathUtils {
}
return ret;
}
/**
* 检查一个JSON对象的数据是否被另一个对象匹配(包含)
*
* @param sourceObj 目标JSON
* @param matchObj 要进行匹配的JSON
* @return
*/
public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) {
if (sourceObj == null && matchObj == null) {
return true;
} else if (sourceObj != null && matchObj != null) {
boolean isMatch = false;
try {
Set<String> matchKeys = matchObj.keySet();
for (String key : matchKeys) {
if (sourceObj.containsKey(key)) {
Object sourceObjItem = sourceObj.get(key);
Object matchObjItem = matchObj.get(key);
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
} else {
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return isMatch;
} else {
return false;
}
}
/**
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
* @param sourceArray
* @param matchObj
* @return
*/
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONObject matchObj) {
if (sourceArray == null && matchObj == null) {
return true;
} else if (sourceArray != null && matchObj != null) {
boolean isMatch = false;
try {
Set<String> matchKeys = matchObj.keySet();
for(int sourceIndex = 0;sourceIndex < sourceArray.size();sourceIndex ++){
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
for (String key : matchKeys) {
if (sourceObj.containsKey(key)) {
Object sourceObjItem = sourceObj.get(key);
Object matchObjItem = matchObj.get(key);
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
if(!isMatch){
break;
}
} else {
isMatch = false;
break;
}
}
if(isMatch){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return isMatch;
} else {
return false;
}
}
private static boolean checkObjCompliance(Object sourceObjItem, Object matchObjItem) {
if (matchObjItem instanceof JSONObject) {
if (sourceObjItem instanceof JSONObject) {
return checkJsonObjCompliance((JSONObject) sourceObjItem, (JSONObject) matchObjItem);
} else {
return false;
}
} else if (matchObjItem instanceof JSONArray) {
if (sourceObjItem instanceof JSONArray) {
JSONArray sourceArr = (JSONArray) sourceObjItem;
JSONArray matchArr = (JSONArray) matchObjItem;
//同是arr 可能顺序存在不同。 所以需要循环匹配
if (matchArr.size() > sourceArr.size()) {
return false;
} else {
for (int i = 0; i < matchArr.size(); i++) {
for (int j = i; j < sourceArr.size(); j++) {
Object matchItemObj = matchArr.get(i);
Object sourceItemObj = sourceArr.get(j);
boolean check = checkObjCompliance(sourceItemObj, matchItemObj);
if (!check) {
return check;
}
}
}
return true;
}
} else {
return false;
}
} else {
String sourceValues = String.valueOf(sourceObjItem);
String matchValues = String.valueOf(matchObjItem);
return StringUtils.equals(sourceValues, matchValues);
}
}
}
package io.metersphere.commons.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Set;
/**
* JSON数据结构相关的工具类
* @author song.tianyang
* @Date 2021/8/16 3:50 下午
*/
public class JsonStructUtils {
/**
* 检查一个JSON对象的数据是否被另一个对象匹配(包含)
*
* @param sourceObj 目标JSON
* @param matchObj 要进行匹配的JSON
* @return
*/
public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) {
if (sourceObj == null && matchObj == null) {
return true;
} else if (sourceObj != null && matchObj != null) {
boolean isMatch = false;
try {
Set<String> matchKeys = matchObj.keySet();
for (String key : matchKeys) {
if (sourceObj.containsKey(key)) {
Object sourceObjItem = sourceObj.get(key);
Object matchObjItem = matchObj.get(key);
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
} else {
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return isMatch;
} else {
return false;
}
}
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONArray matchArray) {
if (sourceArray == null && matchArray == null) {
return true;
} else if (sourceArray != null && matchArray != null && sourceArray.size() > matchArray.size()) {
try {
for (int i = 0; i < matchArray.size(); i ++) {
Object obj = matchArray.get(i);
if(!sourceArray.contains(obj)){
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
} else {
return false;
}
}
public static boolean checkJsonArrayContainsObj(JSONArray sourceArray, JSONObject matchObj) {
if (sourceArray == null && matchObj == null) {
return true;
} else if (sourceArray != null && matchObj != null ) {
try {
for (int i = 0; i < sourceArray.size(); i ++) {
Object obj = sourceArray.get(i);
if(obj instanceof JSONObject){
boolean isMatch = checkJsonObjCompliance((JSONObject) obj,matchObj);
if(isMatch){
return isMatch;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
} else {
return false;
}
}
/**
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
* @param sourceArray
* @param matchObj
* @return
*/
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONObject matchObj) {
if (sourceArray == null && matchObj == null) {
return true;
} else if (sourceArray != null && matchObj != null) {
boolean isMatch = false;
try {
Set<String> matchKeys = matchObj.keySet();
for(int sourceIndex = 0;sourceIndex < sourceArray.size();sourceIndex ++){
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
for (String key : matchKeys) {
if (sourceObj.containsKey(key)) {
Object sourceObjItem = sourceObj.get(key);
Object matchObjItem = matchObj.get(key);
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
if(!isMatch){
break;
}
} else {
isMatch = false;
break;
}
}
if(isMatch){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return isMatch;
} else {
return false;
}
}
private static boolean checkObjCompliance(Object sourceObjItem, Object matchObjItem) {
if (matchObjItem instanceof JSONObject) {
if (sourceObjItem instanceof JSONObject) {
return checkJsonObjCompliance((JSONObject) sourceObjItem, (JSONObject) matchObjItem);
} else {
return false;
}
} else if (matchObjItem instanceof JSONArray) {
if (sourceObjItem instanceof JSONArray) {
JSONArray sourceArr = (JSONArray) sourceObjItem;
JSONArray matchArr = (JSONArray) matchObjItem;
//同是arr 可能顺序存在不同。 所以需要循环匹配
if (matchArr.size() > sourceArr.size()) {
return false;
} else {
for (int i = 0; i < matchArr.size(); i++) {
for (int j = i; j < sourceArr.size(); j++) {
Object matchItemObj = matchArr.get(i);
Object sourceItemObj = sourceArr.get(j);
boolean check = checkObjCompliance(sourceItemObj, matchItemObj);
if (!check) {
return check;
}
}
}
return true;
}
} else {
return false;
}
} else {
String sourceValues = String.valueOf(sourceObjItem);
String matchValues = String.valueOf(matchObjItem);
return StringUtils.equals(sourceValues, matchValues);
}
}
public static void deepParseKeyByJsonObject(JSONObject jsonObject, List<String> keyList) {
for (String key : jsonObject.keySet()) {
Object obj = jsonObject.get(key);
if(obj instanceof JSONArray) {
deepParseKeyByJsonArray((JSONArray) obj, keyList);
}else if(obj instanceof JSONObject){
deepParseKeyByJsonObject((JSONObject) obj,keyList);
}else {
if(!keyList.contains(key)){
keyList.add(key);
}
}
}
}
public static void deepParseKeyByJsonArray(JSONArray jsonArray, List<String> keyList) {
for (int i = 0; i < jsonArray.size(); i ++) {
Object itemObj = jsonArray.get(i);
if(itemObj instanceof JSONObject){
deepParseKeyByJsonObject((JSONObject)itemObj,keyList);
}
}
}
public static boolean checkJsonCompliance(String sourceJson, String matchJson) {
boolean isMatch = false;
try {
boolean isSourceJsonIsArray = false;
boolean isMatchJsonIsArray = false;
JSONValidator sourceValidator = JSONValidator.from(sourceJson);
JSONValidator matchValidator = JSONValidator.from(matchJson);
String sourceType = sourceValidator.getType().name();
String matchType = matchValidator.getType().name();
if(StringUtils.equalsIgnoreCase(sourceType,"array")&&StringUtils.equalsIgnoreCase(matchType,"array")){
isSourceJsonIsArray = true;
isMatchJsonIsArray = true;
}else if(StringUtils.equalsIgnoreCase(sourceType,"array")){
isSourceJsonIsArray = true;
}else if(StringUtils.equalsIgnoreCase(matchType,"array")){
isMatchJsonIsArray = true;
}
if(isSourceJsonIsArray && isMatchJsonIsArray){
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
JSONArray compArr = JSONArray.parseArray(matchJson);
isMatch = checkJsonArrayCompliance(sourceArr,compArr);
}else if(isSourceJsonIsArray && !isMatchJsonIsArray){
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
JSONObject compObj = JSONObject.parseObject(matchJson);
isMatch = checkJsonArrayContainsObj(sourceArr,compObj);
}else if(!isSourceJsonIsArray && !isMatchJsonIsArray){
JSONObject sourceObj = JSONObject.parseObject(sourceJson);
JSONObject compObj = JSONObject.parseObject(matchJson);
isMatch = checkJsonObjCompliance(sourceObj,compObj);
}else {
isMatch = false;
}
}catch (Exception e){
}
return isMatch;
}
}
......@@ -73,15 +73,8 @@ public class ProjectController {
@MsAuditLog(module = "project_project_manager", type = OperLogConstants.CREATE, content = "#msClass.getLogDetails(#project.id)", msClass = ProjectService.class)
public Project addProject(@RequestBody AddProjectRequest project, HttpServletRequest request) {
Project returnModel = projectService.addProject(project);
//创建项目的时候默认增加Mock环境
String requestUrl = request.getRequestURL().toString();
String baseUrl = "";
if (requestUrl.contains("/project/add")) {
baseUrl = requestUrl.split("/project/add")[0];
}
apiTestEnvironmentService.getMockEnvironmentByProjectId(returnModel.getId(), project.getProtocal(), baseUrl);
apiTestEnvironmentService.getMockEnvironmentByProjectId(returnModel.getId());
return returnModel;
}
......
......@@ -8,6 +8,7 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.RunInterface;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.service.JarConfigService;
import io.metersphere.service.ProjectService;
import io.metersphere.service.ScheduleService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.service.IssuesService;
......@@ -38,6 +39,8 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
@Resource
private IssuesService issuesService;
@Resource
private ProjectService projectService;
@Resource
private PerformanceTestService performanceTestService;
@Value("${jmeter.home}")
private String jmeterHome;
......@@ -53,6 +56,8 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
initPythonEnv();
projectService.initMockTcpService();
initOperate(apiAutomationService::checkApiScenarioUseUrl, "init.scenario.url");
initOperate(apiAutomationService::checkApiScenarioReferenceId, "init.scenario.referenceId");
initOperate(issuesService::syncThirdPartyIssues, "init.issue");
......@@ -66,6 +71,7 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
}
scheduleService.startEnableSchedules();
}
......
......@@ -5,6 +5,8 @@ import io.metersphere.api.dto.DeleteAPITestRequest;
import io.metersphere.api.dto.QueryAPITestRequest;
import io.metersphere.api.service.APITestService;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.tcp.TCPPool;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtOrganizationMapper;
......@@ -13,6 +15,7 @@ import io.metersphere.base.mapper.ext.ExtUserGroupMapper;
import io.metersphere.base.mapper.ext.ExtUserMapper;
import io.metersphere.commons.constants.UserGroupConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.ProjectRequest;
......@@ -186,6 +189,9 @@ public class ProjectService {
// User Group
deleteProjectUserGroup(projectId);
//关闭TCP
this.closeMockTcp(projectId);
// delete project
projectMapper.deleteByPrimaryKey(projectId);
......@@ -260,6 +266,15 @@ public class ProjectService {
}
public void updateProject(Project project) {
//查询之前的TCP端口,用于检查是否需要开启/关闭 TCP接口
int lastTcpNum = 0;
Project oldData = projectMapper.selectByPrimaryKey(project.getId());
if(oldData!=null && oldData.getMockTcpPort() != null){
lastTcpNum = oldData.getMockTcpPort().intValue();
}
this.checkProjectTcpPort(project);
project.setCreateTime(null);
project.setUpdateTime(System.currentTimeMillis());
checkProjectExist(project);
......@@ -267,6 +282,28 @@ public class ProjectService {
testCaseService.updateTestCaseCustomNumByProjectId(project.getId());
}
projectMapper.updateByPrimaryKeySelective(project);
//检查Mock环境是否需要同步更新
ApiTestEnvironmentService apiTestEnvironmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
apiTestEnvironmentService.getMockEnvironmentByProjectId(project.getId());
//开启tcp mock
if(project.getIsMockTcpOpen()){
this.reloadMockTcp(project,lastTcpNum);
}else {
this.closeMockTcp(project);
}
}
private void checkProjectTcpPort(Project project) {
//判断端口是否重复
if(project.getMockTcpPort() != null && project.getMockTcpPort().intValue() != 0){
ProjectExample example = new ProjectExample();
example.createCriteria().andMockTcpPortEqualTo(project.getMockTcpPort());
long countResult = projectMapper.countByExample(example);
if(countResult > 0){
MSException.throwException("TCP Port is not unique!");
}
}
}
private void checkProjectExist(Project project) {
......@@ -483,4 +520,54 @@ public class ProjectService {
public Map<String, Project> queryNameByIds(List<String> ids) {
return extProjectMapper.queryNameByIds(ids);
}
public void openMockTcp(Project project){
if(project == null){
MSException.throwException("Project not found!");
}else {
if(project.getMockTcpPort() == null){
MSException.throwException("Mock tcp port is not Found!");
}else {
TCPPool.createTcp(project.getMockTcpPort());
}
}
}
public void reloadMockTcp(Project project,int oldPort){
this.closeMockTcp(oldPort);
this.openMockTcp(project);
}
public void closeMockTcp(String projectId){
Project project = projectMapper.selectByPrimaryKey(projectId);
this.closeMockTcp(project);
}
public void closeMockTcp(Project project){
if(project == null){
MSException.throwException("Project not found!");
}else {
if(project.getMockTcpPort() == null){
MSException.throwException("Mock tcp port is not Found!");
}else {
this.closeMockTcp(project.getMockTcpPort().intValue());
}
}
}
public void closeMockTcp(int tcpPort){
if(tcpPort != 0){
TCPPool.closeTcp(tcpPort);
}
}
public void initMockTcpService() {
ProjectExample example = new ProjectExample();
Integer portInteger = new Integer(0);
Boolean statusBoolean = new Boolean(true);
example.createCriteria().andIsMockTcpOpenEqualTo(statusBoolean).andMockTcpPortNotEqualTo(portInteger);
List<Project> projectList = projectMapper.selectByExample(example);
for (Project p :projectList) {
this.openMockTcp(p);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment