徒手生撸一个验证框架,API 参数校验不再怕!
2021-03-11 17:28
你们之中大概率早已练就了代码的拷贝、粘贴,无敌的码农神功,其实做久了业务功能开发,练就这两个无敌神功,那是迟早的事儿。今天先抛一个小问题,来打通你的任督二脉,就是很好奇的问一下:业务功能开发中,输入参数校验占了你多少时间呢?有没有考虑如何进行验证模块化、通用化?
咱们还是换个问法,看看元芳怎么看。“到底该如何保证业务 API 的健壮性”,元芳你怎么看类?
关注“一猿小讲”久了的元芳,多多少少都有点进步,所以不加思索的答到:首先要保证 API 输入参数的校验;然后……
听到“首先要保证 API 输入参数的校验”,就要给元芳打满分,因为他撬开了咱们今天的话题。
好了,请准备好小板凳,接下来看看如何玩转、生撸一个 API 参数校验的框架。
1.
常规写法。
备注:上面代码截图我仅用来举栗阐述,return 中的信息临时写死,应该动态设置返回码以及返回描述封装为 JSON 返回。
上图代码的栗子,也是众多新手最喜欢用的方式,毕竟在初入职场的程序猿眼中,错误的以为「代码量就是钱」,也可能是想在 SVN 或者 Git 上多留存更新记录,因为更新记录也是能体现代码量及劳动力的啊(捂嘴笑)。
但是往往一个 API 接口不简单只有两个输入参数,多则几十个参数,那岂不是大量代码的篇幅,都在进行参数校验,岂不是会耗费大量的时间精力,在参数校验上。
其实 API 接口入参校验步骤,我们大概可以分为:获取接口输入参数;校验必传参数是否传入;检验参数是否符合规则。
其实一旦找到规律,都可以交给机器去做,那咱们肯定可以打造一款高效的 API 参数校验的轮子。
2.
轮子应该有什么组成?
A. 接口入参配置;
B. 参数校验规则配置;
C. 封装参数校验失败时异常码以及异常信息;
结合上面的思考,咱们还是画个简单的流程图吧,上一图就秒懂。
3.
轮子应该咋实现?
A. 定义 API 接口入参配置文件 param.properties
########业务功能健壮性参数规则配置############################ #接口参数配置=Param group(按照|分割参数组,按照逗号分隔每组的参数) ########################################################## #系统接口所需参数配置(PARAMS.apiURL=参数列表) PARAMS./sys/login.do=username,password
B. 定义 API 接口参数正则校验 regex.properties
########业务功能健壮性参数规则配置############################ #接口参数正则表达式配置(PARAMS.接口URL.参数.regex=正则表达式) PARAMS./sys/login.do.username.regex=\\w{1,32} #全局参数正则表达式配置(参数.regex=正则表达式) password.regex=\\w{1,32}
C. 开始生撸代码
第一步:定义如何根据请求的 api 接口获取对应的入参配置。
第二步:验证传入参数的值是否符合规则。由于每个 API 支持多组参数传入的情形,所以可以按照“|”分割多组参数。
第三步:验证传入参数的值是否符合规则,真正的校验逻辑。
第四步:按照咱们的流程图,把上面的方法串在一起,封装成一个 Service,想在哪儿用,在哪儿用,So Easy!!!其中 doService 方法的入参,apiUrl 就是接口的 url,json 是传入的参数。
还是要把主要代码分享给大家,以便你们更好的进步。
import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; /** * 请求参数校验服务 * desc: * 1、通过传入的apiUrl找到需要校验的数据(param.properties), * 2、通过传入的参数key找到对应的正则表达式(regex.properties), * 3、对需要校验的数据进行正则表达式 * 4、支持必填非必填字段校验 */ public class RequestParamCheckService { public static final String REGKEY = "PARAMS."; public static final String REGEX = ".regex"; public void doService(String apiUrl, JSONObject json) { //1. 校验 API URL 是否传入 if (StringUtils.isEmpty(apiUrl)) { System.out.println("Miss api url"); return; } //2. 根据 API URL 获取参数的配置 String paramKeyConf = StringUtils.trim(getKeyByApiUrl(apiUrl)); if (StringUtils.isEmpty(paramKeyConf)) { System.out.println(String.format("%s found no check info", apiUrl)); return; } //3. 验证传入参数的值是否符合配置定义的规则 boolean[] validateAry = validate(apiUrl, paramKeyConf, json); //4. 校验参数校验结果 if (!ArrayUtils.contains(validateAry, true)) { System.out.println(String.format("%s param validate fail", apiUrl)); //TODO 此处需要根据字段获取对应的返回码以及返回信息,可以自行扩展实现一下,本次硬编码 throw new ValidateException("99999999", "参数校验失败"); } } /** * 验证传入参数的值是否符合配置定义的规则 * * @param apiUrl 接口 * @param paramKeyConf 配置的参数key * @param json 传入的json报文内容 * @return 验证结果 */ private boolean[] validate(String apiUrl, String paramKeyConf, JSONObject json) { // 将KEY分隔 String[] chkKeys = paramKeyConf.split("\\|"); //判断拆分后的参数是否为组合配置 //针对每组参数校验是否传入,最后得出参数传入是否正确 boolean[] validateAry = new boolean[chkKeys.length]; for (int i = 0; i true, 否则返回false */ private boolean isOptionalParam(String key) { return key.startsWith("[") && key.endsWith("]"); } }
好了,时间也不早了,生撸验证框架就分享到这儿吧,其实还有很多细节没有深入去说,只是讲了大体的思路,不过代码中注释已经写的很清晰了。如果你能搞明白,并在实际项目中应用,那肯定会大幅度提升开发效率,腾出更多时间去冲咖啡。
看完这篇硬核文章,懂与不懂,都请多点赞、收藏、分享,因为你每一个不经意的神操作,我都认真当成了喜欢。
上一篇:WPF 依赖属性
文章标题:徒手生撸一个验证框架,API 参数校验不再怕!
文章链接:http://soscw.com/index.php/essay/63295.html