From f9255c243c68b3b162054b2d89dae654297aafcd Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 27 Dec 2019 18:07:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=A7=84=E5=88=99=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/bean/SceneValidateRule.hbm.xml | 5 +- .../message/bean/SceneValidateRule.java | 25 +- .../message/enums/SceneValidateCondition.java | 43 +++ .../message/enums/SceneValidateType.java | 6 +- .../enums/SceneValidateValueGetMethod.java | 14 +- .../message/test/MessageAutoTest.java | 2 +- .../message/test/MessageValidateResponse.java | 217 +++++++++++-- src/main/java/yi/master/util/DBUtil.java | 15 +- src/main/resources/update/1.0.1 | 4 + .../resource/message/validateParameters.html | 4 +- .../resource/message/validateParameters.js | 307 +++++++++++------- update.md | 4 + 12 files changed, 486 insertions(+), 160 deletions(-) create mode 100644 src/main/java/yi/master/business/message/enums/SceneValidateCondition.java create mode 100644 src/main/resources/update/1.0.1 diff --git a/src/main/java/yi/master/business/message/bean/SceneValidateRule.hbm.xml b/src/main/java/yi/master/business/message/bean/SceneValidateRule.hbm.xml index 02b5da7..d519a5e 100644 --- a/src/main/java/yi/master/business/message/bean/SceneValidateRule.hbm.xml +++ b/src/main/java/yi/master/business/message/bean/SceneValidateRule.hbm.xml @@ -17,7 +17,7 @@ - + @@ -25,6 +25,9 @@ + + + diff --git a/src/main/java/yi/master/business/message/bean/SceneValidateRule.java b/src/main/java/yi/master/business/message/bean/SceneValidateRule.java index 5f2e83a..1ba83e8 100644 --- a/src/main/java/yi/master/business/message/bean/SceneValidateRule.java +++ b/src/main/java/yi/master/business/message/bean/SceneValidateRule.java @@ -39,15 +39,20 @@ public class SceneValidateRule implements Serializable { /** * 获取validate_value的方式
*/ - @FieldRealSearch(names = {"常量", "入参节点值", "SQL语句", "全局变量", "正则表达式"}, values = {"0", "1", "2", "3", "4"}) + @FieldRealSearch(names = {"常量", "入参节点值", "SQL语句", "全局变量", "正则表达式"}, values = {"0", "1", "999999", "3", "4"}) private String getValueMethod; /** * 0-左右边界取关键字验证
* 1-节点参数验证
*/ - @FieldRealSearch(names = {"关联验证", "节点验证"}, values = {"0", "1"}) + @FieldRealSearch(names = {"关联验证", "节点验证", "自定义验证"}, values = {"0", "1", "2"}) private String validateMethodFlag; + + /** + * 比对条件 + */ + private String validateCondition; /** * 当validate_method_flag为1时有效:
@@ -89,11 +94,17 @@ public class SceneValidateRule implements Serializable { super(); } - - - - - public String getGetValueMethod() { + + + public void setValidateCondition(String validateCondition) { + this.validateCondition = validateCondition; + } + + public String getValidateCondition() { + return validateCondition; + } + + public String getGetValueMethod() { return getValueMethod; } public void setGetValueMethod(String getValueMethod) { diff --git a/src/main/java/yi/master/business/message/enums/SceneValidateCondition.java b/src/main/java/yi/master/business/message/enums/SceneValidateCondition.java new file mode 100644 index 0000000..ec662b2 --- /dev/null +++ b/src/main/java/yi/master/business/message/enums/SceneValidateCondition.java @@ -0,0 +1,43 @@ +package yi.master.business.message.enums; + +/** + * 验证条件 + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2019/12/26 17:27 + */ +public enum SceneValidateCondition { + /** + * 大于 + */ + gt, + /** + * 等于 + */ + eq, + /** + * 小于 + */ + lt, + /** + * 包含 + */ + contain, + /** + * 不包含 + */ + notcontain, + /** + * 存在值即可 + */ + exist, + /** + * 匹配正则 + */ + reg, + /** + * 不做任何验证 + */ + nothing +} diff --git a/src/main/java/yi/master/business/message/enums/SceneValidateType.java b/src/main/java/yi/master/business/message/enums/SceneValidateType.java index 0ccab26..52bfcf3 100644 --- a/src/main/java/yi/master/business/message/enums/SceneValidateType.java +++ b/src/main/java/yi/master/business/message/enums/SceneValidateType.java @@ -13,7 +13,11 @@ public enum SceneValidateType { /** * 1 - 节点验证 */ - NODE_VALIDATION("1"); + NODE_VALIDATION("1"), + /** + * 2 - 自定义验证 + */ + CUSTOM_VALIDATION("2"); private String type; diff --git a/src/main/java/yi/master/business/message/enums/SceneValidateValueGetMethod.java b/src/main/java/yi/master/business/message/enums/SceneValidateValueGetMethod.java index 320f350..8d1c20f 100644 --- a/src/main/java/yi/master/business/message/enums/SceneValidateValueGetMethod.java +++ b/src/main/java/yi/master/business/message/enums/SceneValidateValueGetMethod.java @@ -25,7 +25,19 @@ public enum SceneValidateValueGetMethod { /** * 正则表达式 */ - REGULAR_EXPRESSION("4"); + REGULAR_EXPRESSION("4"), + /** + * 响应时间 + */ + RESPONSE_TIME("5"), + /** + * 状态码 + */ + STATUS_CODE("6"), + /** + * 响应头 + */ + RESPONSE_HEADER("7"); private String method; diff --git a/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java b/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java index ed39459..ccb23fd 100644 --- a/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java +++ b/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java @@ -188,7 +188,7 @@ public class MessageAutoTest { } - Map map = validateUtil.validate(result.getResponseMessage(), testScene.getRequestMessage(), scene, msg.getMessageType(), testScene.getConfig().getConfigId()); + Map map = validateUtil.validate(result, msg.getMessageType(), testScene.getConfig().getConfigId()); //变更数据状态 if (MessageValidateResponse.VALIDATE_SUCCESS_FLAG.equals(map.get(MessageValidateResponse.VALIDATE_MAP_STATUS_KEY))) { diff --git a/src/main/java/yi/master/coretest/message/test/MessageValidateResponse.java b/src/main/java/yi/master/coretest/message/test/MessageValidateResponse.java index 1ecdfba..16d9f3c 100644 --- a/src/main/java/yi/master/coretest/message/test/MessageValidateResponse.java +++ b/src/main/java/yi/master/coretest/message/test/MessageValidateResponse.java @@ -1,24 +1,30 @@ package yi.master.coretest.message.test; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; +import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import yi.master.business.message.bean.MessageScene; import yi.master.business.message.bean.SceneValidateRule; +import yi.master.business.message.bean.TestResult; import yi.master.business.message.enums.CommonStatus; +import yi.master.business.message.enums.SceneValidateCondition; import yi.master.business.message.enums.SceneValidateType; import yi.master.business.message.enums.SceneValidateValueGetMethod; import yi.master.business.message.service.SceneValidateRuleService; import yi.master.business.testconfig.bean.DataDB; import yi.master.business.testconfig.service.GlobalVariableService; +import yi.master.constant.SystemConsts; import yi.master.coretest.message.parse.MessageParse; import yi.master.util.DBUtil; import yi.master.util.PracticalUtils; import yi.master.util.cache.CacheUtil; +import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -53,16 +59,14 @@ public class MessageValidateResponse { private GlobalVariableService globalVariableService; /** - * - * @param responseMessage - * @param requestMessage - * @param scene + * 验证方法 + * @param result * @return Map<String, String>
* status 验证结果 0-成功 1-不成功
* msg 备注信息 */ - public Map validate(String responseMessage, String requestMessage, MessageScene scene, String messageType, Integer configId) { - List rules = validateRuleService.getParameterValidate(scene.getMessageSceneId()); + public Map validate(TestResult result, String messageType, Integer configId) { + List rules = validateRuleService.getParameterValidate(result.getMessageScene().getMessageSceneId()); List configRules = validateRuleService.getConfigRules(configId); CollUtil.addAll(rules, configRules); @@ -93,11 +97,13 @@ public class MessageValidateResponse { Map resultMap = null; //关键字匹配验证,通过左右边界 if (SceneValidateType.ASSOCIATED_VALIDATION.getType().equals(rule.getValidateMethodFlag())) { - resultMap = relateKeyValidate(responseMessage, requestMessage, rule, parseUtil); + resultMap = relateKeyValidate(result, rule, parseUtil); //节点参数验证,复杂验证 } else if (SceneValidateType.NODE_VALIDATION.getType().equals(rule.getValidateMethodFlag())) { - resultMap = nodeParameterValidate(responseMessage, requestMessage, rule, parseUtil); - } + resultMap = nodeParameterValidate(result, rule, parseUtil); + } else if (SceneValidateType.CUSTOM_VALIDATION.getType().equals(rule.getValidateMethodFlag())) { + resultMap = customValidate(result, rule, parseUtil); + } msg.append(resultMap.get(VALIDATE_MAP_MSG_KEY) + "\n"); if (!VALIDATE_SUCCESS_FLAG.equals(resultMap.get(VALIDATE_MAP_STATUS_KEY))) { @@ -112,16 +118,181 @@ public class MessageValidateResponse { + successCount + "条,失败" + failCount + "条。"); return validateMap; } - + + + /** + * 自定义验证 + * @author xuwangcheng + * @date 2019/12/27 9:38 + * @param result result + * @param rule rule + * @param parseUtil parseUtil + * @return {@link Map} + */ + private Map customValidate (TestResult result, SceneValidateRule rule, MessageParse parseUtil) { + Map map = new HashMap(); + map.put(VALIDATE_MAP_STATUS_KEY, VALIDATE_FAIL_FLAG); + StringBuilder msg = new StringBuilder("【自定义验证】"); + + String verifyVal = null; + String compareVal = rule.getValidateValue(); + + //响应时间 + if (SceneValidateValueGetMethod.RESPONSE_TIME.getMethod().equals(rule.getGetValueMethod())) { + verifyVal = result.getUseTime().toString(); + msg.append("验证响应时间,响应时间为" + verifyVal + "ms,"); + + } + + //状态码 + if (SceneValidateValueGetMethod.STATUS_CODE.getMethod().equals(rule.getGetValueMethod())) { + verifyVal = result.getStatusCode(); + msg.append("验证状态码,状态码为" + verifyVal + ","); + } + + //响应头 + if (SceneValidateValueGetMethod.RESPONSE_HEADER.getMethod().equals(rule.getGetValueMethod())) { + JSONObject headerObject = JSONObject.fromObject(result.getHeaders()).getJSONObject("ResponseHeader"); + msg.append("验证响应头,"); + + for (Object key:headerObject.keySet()) { + if (key != null && key.toString().equalsIgnoreCase(rule.getParameterName())) { + verifyVal = headerObject.getString(key.toString()); + } + } + + if (StringUtils.isBlank(verifyVal)) { + map.put(VALIDATE_MAP_MSG_KEY, msg.append("没有获取key为" + rule.getParameterName() + "的响应头信息。").toString()); + return map; + } + msg.append("key为" + rule.getParameterName() + "的响应头值为" + verifyVal + ","); + } + + //数据库取值 + if (rule.getGetValueMethod().startsWith(SceneValidateValueGetMethod.QUERY_SQL.getMethod())) { + msg.append("验证数据库变动,"); + DataDB db = CacheUtil.getQueryDBById(rule.getGetValueMethod()); + + if (db == null) { + map.put(VALIDATE_MAP_MSG_KEY, msg.append("没有找到dbId为 " + rule.getGetValueMethod() + " 的数据源信息!").toString()); + return map; + } + + String querySql = PracticalUtils.replaceGlobalVariable( + parseUtil.parameterReplaceByNodePath(result.getRequestMessage(), rule.getParameterName()), globalVariableService); + + verifyVal = DBUtil.getDBData(db, querySql); + + if (StringUtils.isBlank(verifyVal)) { + map.put(VALIDATE_MAP_MSG_KEY, msg.append("从数据源 " + db.getDbName() + " 中查询数据出错[" + querySql + "]").toString()); + return map; + } + + msg.append("数据源" + db.getDbName() + ",执行SQL[" + querySql + "],获取校验值为" + verifyVal + ","); + } + + String verifyResult = customCompareValue(verifyVal, compareVal, rule.getValidateCondition()); + if (SystemConsts.DefaultBooleanIdentify.TRUE.getString().equalsIgnoreCase(verifyResult)) { + map.put(VALIDATE_MAP_STATUS_KEY, VALIDATE_SUCCESS_FLAG); + map.put(VALIDATE_MAP_MSG_KEY, msg.append("与比对值" + compareVal + "比对正确,验证成功!").toString()); + return map; + } + + map.put(VALIDATE_MAP_MSG_KEY, msg.append("与比对值" + compareVal + "比对失败:[" + verifyResult + "],验证失败!").toString()); + return map; + } + + + /** + * 按照配置对校验值和比对值进行正确比对 + * @author xuwangcheng + * @date 2019/12/27 11:02 + * @param val1 val1 校验值 + * @param val2 val2 比对值 + * @param compareCondition compareCondition + * @return {@link String} 正确返回true,否则返回错误信息 + */ + private String customCompareValue (String val1, String val2, String compareCondition) { + String result = "true"; + if (StringUtils.isBlank(val1) || StringUtils.isBlank(compareCondition)) { + return "校验值、比对条件不能为空"; + } + + if (SceneValidateCondition.eq.name().equalsIgnoreCase(compareCondition)) { + if (!StringUtils.equals(val1, val2)) { + return val1 + "不等于" + val2; + } + + return result; + } + + if (SceneValidateCondition.nothing.name().equalsIgnoreCase(compareCondition)) { + return result; + } + + if (SceneValidateCondition.contain.name().equalsIgnoreCase(compareCondition)) { + if (!StringUtils.contains(val1, val2)) { + return val1 + "不包含" + val2; + } + + return result; + } + + if (SceneValidateCondition.notcontain.name().equalsIgnoreCase(compareCondition)) { + if (StringUtils.contains(val1, val2)) { + return val1 + "包含" + val2; + } + + return result; + } + + if (SceneValidateCondition.exist.name().equalsIgnoreCase(compareCondition)) { + if (StringUtils.isBlank(val1)) { + return "校验值不存在"; + } + + return result; + } + + if (SceneValidateCondition.reg.name().equalsIgnoreCase(compareCondition)) { + if (!ReUtil.isMatch(val2, val1)) { + return val1 + "无法正确匹配正则表达式" + val2; + } + + return result; + } + + if (!NumberUtils.isDigits(val1)) { + return val1 + "不是数字类型,无法比对"; + } + + if (!NumberUtils.isDigits(val2)) { + return val2 + "不是数字类型,无法比对"; + } + + if (SceneValidateCondition.gt.name().equalsIgnoreCase(compareCondition)) { + if ((new BigDecimal(val1).compareTo(new BigDecimal(val2))) <= 0) { + return val1 + "小于等于" + val2; + } + } + + if (SceneValidateCondition.lt.name().equalsIgnoreCase(compareCondition)) { + if ((new BigDecimal(val1).compareTo(new BigDecimal(val2))) >= 0) { + return val1 + "大于等于" + val2; + } + } + + return result; + } + /** * 关联左右边界取值 - * @param responseMessage - * @param requestMessage + * @param result * @param rule * @return */ @SuppressWarnings("rawtypes") - private Map relateKeyValidate(String responseMessage, String requestMessage, SceneValidateRule rule, MessageParse parseUtil) { + private Map relateKeyValidate(TestResult result, SceneValidateRule rule, MessageParse parseUtil) { Map map = new HashMap(); Map maps = null; try { @@ -136,7 +307,7 @@ public class MessageValidateResponse { return map; } - String getValue = PracticalUtils.getValueByRelationKeyWord(maps, responseMessage); + String getValue = PracticalUtils.getValueByRelationKeyWord(maps, result.getResponseMessage()); if (getValue == null) { map.put(VALIDATE_MAP_STATUS_KEY, VALIDATE_FAIL_FLAG); map.put(VALIDATE_MAP_MSG_KEY, "根据指定的左右边界等参数无法在出参报文中匹配到相应的内容,请检查!"); @@ -155,7 +326,7 @@ public class MessageValidateResponse { //入参节点获取 if (SceneValidateValueGetMethod.REQUEST_PARAMS_NODE.getMethod().equals(rule.getGetValueMethod())) { - validateValue = parseUtil.getObjectByPath(requestMessage, rule.getValidateValue()); + validateValue = parseUtil.getObjectByPath(result.getRequestMessage(), rule.getValidateValue()); if (validateValue == null) { map.put(VALIDATE_MAP_MSG_KEY, msg + "在入参报文中没有找到路径为 " + rule.getValidateValue() + " 的节点,请检查验证规则!"); @@ -190,23 +361,21 @@ public class MessageValidateResponse { /** * 针对返回报文中各个指定path的节点进行验证
* 出错则停止验证并返回失败标记 - * @param responseMessage - * @param requestMessage + * @param result * @param rule * @param parseUtil * @return */ - private Map nodeParameterValidate(String responseMessage, String requestMessage, SceneValidateRule rule, MessageParse parseUtil) { + private Map nodeParameterValidate(TestResult result, SceneValidateRule rule, MessageParse parseUtil) { Map map = new HashMap(); map.put(VALIDATE_MAP_STATUS_KEY, VALIDATE_FAIL_FLAG); StringBuilder msg = new StringBuilder(); //不是指定的格式,不能用此方式验证 - MessageParse responseMessageParseUtil = MessageParse.judgeMessageType(responseMessage); + MessageParse responseMessageParseUtil = MessageParse.judgeMessageType(result.getResponseMessage()); - msg.append("【节点验证】在验证出参节点路径为 " + rule.getParameterName() + " 时: "); - String vaildateStr = responseMessageParseUtil.getObjectByPath(responseMessage, rule.getParameterName()); + String vaildateStr = responseMessageParseUtil.getObjectByPath(result.getResponseMessage(), rule.getParameterName()); if (vaildateStr == null) { map.put(VALIDATE_MAP_MSG_KEY, msg + "返回报文中没有找到该路径节点,请检查验证规则!"); @@ -222,7 +391,7 @@ public class MessageValidateResponse { //入参节点获取 if (rule.getGetValueMethod().equals(SceneValidateValueGetMethod.REQUEST_PARAMS_NODE.getMethod())) { - validateValue = parseUtil.getObjectByPath(requestMessage, rule.getValidateValue()); + validateValue = parseUtil.getObjectByPath(result.getRequestMessage(), rule.getValidateValue()); if (validateValue == null) { map.put(VALIDATE_MAP_MSG_KEY, msg + "在入参报文中没有找到路径为 " + rule.getValidateValue() + " 的节点,请检查验证规则!"); @@ -245,7 +414,7 @@ public class MessageValidateResponse { } String querySql = PracticalUtils.replaceGlobalVariable( - parseUtil.parameterReplaceByNodePath(requestMessage, rule.getValidateValue()), globalVariableService); + parseUtil.parameterReplaceByNodePath(result.getRequestMessage(), rule.getValidateValue()), globalVariableService); validateValue = DBUtil.getDBData(db, querySql); diff --git a/src/main/java/yi/master/util/DBUtil.java b/src/main/java/yi/master/util/DBUtil.java index 7d2a6ac..c7009ec 100644 --- a/src/main/java/yi/master/util/DBUtil.java +++ b/src/main/java/yi/master/util/DBUtil.java @@ -1,15 +1,10 @@ package yi.master.util; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - import org.apache.log4j.Logger; - import yi.master.business.testconfig.bean.DataDB; +import java.sql.*; + /** * 仅用于测试过程中查询数据的数据库连接工具类 * @author xuwangcheng @@ -55,7 +50,7 @@ public class DBUtil { if (dbType.equals("mysql")) { Class.forName("com.mysql.jdbc.Driver"); - con = DriverManager.getConnection("jdbc:mysql://" + dbUrl + "/" + dbName + "?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true", dbUserName, dbPasswd); + con = DriverManager.getConnection("jdbc:mysql://" + dbUrl + "/" + dbName + "?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&useSSL=false", dbUserName, dbPasswd); } } catch (ClassNotFoundException e) { @@ -65,10 +60,6 @@ public class DBUtil { } catch (SQLException e1) { LOGGER.error("创建数据库连接出错!", e1); throw new SQLException(); - } finally { - if (con != null) { - con.close(); - } } if (!dbType.equals("oracle") && !dbType.equals("mysql")) { diff --git a/src/main/resources/update/1.0.1 b/src/main/resources/update/1.0.1 new file mode 100644 index 0000000..06af0fd --- /dev/null +++ b/src/main/resources/update/1.0.1 @@ -0,0 +1,4 @@ +ALTER TABLE `at_scene_validate_rule` ADD COLUMN `validate_condition` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '验证条件,例如大于小于等于等' AFTER `get_value_method`; +ALTER TABLE `at_scene_validate_rule` MODIFY COLUMN `parameter_name` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '根据validate_method_flag的值有不同的含义:validate_method_flag=0时,其为取值的json串,例如:{\"LB\":\"ss\",\"RB\":\"vv\",\"ORDER\":1},分别表示左边界、右边界、取值顺序,validate_method_flag=1时,该值表示节点路径' AFTER `message_scene_id`; +ALTER TABLE `at_scene_validate_rule` MODIFY COLUMN `validate_method_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '验证方式0-左右边界取关键字验证,1-节点参数验证' AFTER `parameter_name`; +ALTER TABLE `at_scene_validate_rule` MODIFY COLUMN `get_value_method` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '获取validate_value的方式,0 - 常量,1 - 入参节点值,2 - SQL语句,3 - 全局变量,4 - 正则表达式' AFTER `validate_method_flag`; diff --git a/src/main/webapp/resource/message/validateParameters.html b/src/main/webapp/resource/message/validateParameters.html index 25b8d0d..561c188 100644 --- a/src/main/webapp/resource/message/validateParameters.html +++ b/src/main/webapp/resource/message/validateParameters.html @@ -15,9 +15,9 @@ - + + -