在接触过JsonPath
工具,我发现了使用标记语法编写文本形式的验证的可行性。在完成了基本JsonPath
功能封装和Groovy
终极重载操作符功能之后,自我感觉已经非常完善了,所以停了一阵子。之前的成果如下:
JsonPath文章合集
- JsonPath实践(一)
- JsonPath实践(二)
- JsonPath实践(三)
- JsonPath实践(四)
- JsonPath实践(五)
- JsonPath实践(六)
- JsonPath工具类封装
- JsonPath工具类单元测试
- JsonPath验证类既Groovy重载操作符实践
在最近实践的一个Socket
接口异步验证的功能时,对于响应结果又有了新的验证需求。目前我的方案是单独写一个VerifyBean对象,用来完成不同验证需求的实现。每一个对象都是存储一种验证方式,然后存储验证结果。
对实际值进行运算
这个功能为了方便获取到实际值以后,进行加、减、乘和除运算以后再与期望值进行比较。比如用户消费场景,例如随机立减(吐槽一下立减一分钱),用余额+商品金额>原余额方程可以验证数据的准确性。
JsonVerify
功能具体实现如下:
/**
* 判断是否符合期望
* @param str
* @return
*/
public boolean fit(String str) {
logger.info("verify对象: {},匹配的字符串: {}", extra, str)
OPS o = OPS.getInstance(str.charAt(0))
def res = str.substring(1)
switch (o) {
case OPS.GREATER:
return this > res
case OPS.LESS:
return this < res
case OPS.EQUAL:
return this == res
case OPS.REGEX:
return this ==~ res
default:
ParamException.fail("参数错误!")
}
}
/**
* 判断是否符合操作后期望
* @param str
* @return
*/
public boolean fitFun(String str) {
def split = str.split(REG_PART, 2)
def handle = split[0]
def ops = split[1]
HPS h = HPS.getInstance(handle.charAt(0))
def hr = handle.substring(1)
switch (h) {
case HPS.PLUS:
def n = getInstance((this + hr) as String)
return n.fit(ops)
case HPS.MINUS:
def n = getInstance((this - hr) as String)
return n.fit(ops)
case HPS.MUL:
def n = getInstance((this * hr) as String)
return n.fit(ops)
case HPS.DIV:
def n = getInstance((this / hr) as String)
return n.fit(ops)
default:
ParamException.fail("参数错误!")
}
}
/**
* 支持的判断类型的操作符枚举类
*/
static enum OPS {
GREATER, LESS, EQUAL, REGEX;
static OPS getInstance(char c) {
switch (c) {
case '>':
return GREATER;
case '<':
return LESS;
case '=':
return EQUAL;
case '~':
return REGEX
default:
ParamException.fail("判断操作符参数错误!")
}
}
}
/**
* 支持的运算类型的操作符枚举类
*/
static enum HPS {
PLUS, MINUS, MUL, DIV
static HPS getInstance(char c) {
switch (c) {
case '+':
return PLUS
case '-':
return MINUS
case '*':
return MUL
case '/':
return DIV
default:
ParamException.fail("运算操作符参数错误!")
}
}
}
重载操作符的代码可以通过JsonPath验证类既Groovy重载操作符实践文章查看,或者访问我的仓库:
VerifyBean验证对象
这个比较简单,目前来讲满足需求。
package com.fun.base.bean
import com.alibaba.fastjson.JSON
import com.fun.base.exception.ParamException
import com.fun.config.VerifyType
import com.fun.utils.JsonUtil
import com.fun.utils.Regex
import com.fun.utils.Time
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.util.concurrent.atomic.AtomicLong
import static com.fun.config.Constant.REG_PART
/**
* 验证对象类
*/
class VerifyBean extends AbstractBean implements Serializable, Cloneable {
private static Logger logger = LoggerFactory.getLogger(VerifyBean.class)
private static final long serialVersionUID = -1595942567071153982L;
VerifyType type
/**
* 验证语法
*/
String verify
/**
* 待验证内容
*/
String value
String des
boolean isVerify
boolean result;
VerifyBean(String verify, String value, String des) {
this.value = value
this.des = des
def split = verify.split(REG_PART, 2)
this.verify = split[1]
this.type = VerifyType.getRequestType(split[0])
}
boolean verify() {
isVerify = true
try {
switch (type) {
case VerifyType.CONTAIN:
result = value.contains(verify)
break
case VerifyType.REGEX:
result = Regex.isRegex(value, verify)
break
case VerifyType.JSONPATH:
def split = verify.split(REG_PART, 2)
def path = split[0]
def v = split[1]
def instance = JsonUtil.getInstance(JSON.parseObject(value))
result = instance.getVerify(path).fit(v)
break
case VerifyType.HANDLE:
def sp = verify.split(REG_PART, 2)
def path = sp[0]
def ve = sp[1]
def instance = JsonUtil.getInstance(JSON.parseObject(value))
result = instance.getVerify(path).fitFun(ve)
break
default:
ParamException.fail("验证类型参数错误!")
}
} catch (Exception e) {
logger.warn("验证出现问题!", e)
result = false
} finally {
logger.info("verify对象 {} ,验证结果: {}", verify, result)
result
}
}
@Override
public VerifyBean clone() throws CloneNotSupportedException {
new VerifyBean(this.verify, this.value, this.des)
}
}
Demo演示
测试代码:
public static void main(String[] args) {
String a = "{"msg":"","code":1,"data":{"role":"T","s_sid":123,"deviceVersion":"1.0","userId":61951375269,"token":"c5d28b3e919d45e0a06af2e4d346698a"},"cmd":"registerResponse"}"
def bean1 = new VerifyBean("contain|61951375269", a, "FunTester")
def bean2 = new VerifyBean("regex|.*data.*", a, "FunTester")
def bean3 = new VerifyBean("jsonpath|$.data.s_sid|=123", a, "FunTester")
def bean4 = new VerifyBean("jsonpath|$.data.s_sid|>100", a, "FunTester")
def bean5 = new VerifyBean("jsonpath|$.cmd|~.*Response.*", a, "FunTester")
def bean6 = new VerifyBean("handle|$.code|*200|=200.0", a, "FunTester")
println bean1.verify()
println bean2.verify()
println bean3.verify()
println bean4.verify()
println bean5.verify()
println bean6.verify()
}
控制台输出:
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> 验证校验方式方式:contain
INFO-> 验证校验方式方式:regex
INFO-> 验证校验方式方式:jsonpath
INFO-> 验证校验方式方式:jsonpath
INFO-> 验证校验方式方式:jsonpath
INFO-> 验证校验方式方式:handle
INFO-> verify对象 61951375269 ,验证结果: true
true
INFO-> verify对象 .*data.* ,验证结果: true
true
INFO-> verify对象: 123,匹配的字符串: =123
INFO-> verify对象 $.data.s_sid|=123 ,验证结果: true
true
INFO-> verify对象: 123,匹配的字符串: >100
INFO-> verify对象 $.data.s_sid|>100 ,验证结果: true
true
INFO-> verify对象: registerResponse,匹配的字符串: ~.*Response.*
INFO-> verify对象 $.cmd|~.*Response.* ,验证结果: true
true
INFO-> verify对象: 200.0,匹配的字符串: =200.0
INFO-> verify对象 $.code|*200|=200.0 ,验证结果: true
true
Process finished with exit code 0
- FunTester,简直完美实现了我的需求,下一步开始对
Socket
接口编写异步验证线程,敬请期待!