程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴

这篇具有很好参考价值的文章主要介绍了程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【前言】先比较一下这两段代码

先看下面代码中的两个方法。executedoPaymentAuthResultQuery,一个方法接收到参数后,直接将参数原样传递给另一个方法。

程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴
@Override
public void execute(String jobParameter) {
    log.info("亿联绑卡打款认证结果查询-定时任务:{}", jobParameter);
    try {
        doPaymentAuthResultQuery(jobParameter);
    } catch (Exception e) {
        log.error("亿联绑卡打款认证结果查询-定时任务异常:", e);
    }
}

private void doPaymentAuthResultQuery(String jobParameter) {
    String startTime, endTime;
    if (StringUtil.isNotEmpty(jobParameter)) {
        JSONObject jsonObject = JSON.parseObject(jobParameter);
        startTime = jsonObject.getString("startTime");
        endTime = jsonObject.getString("endTime");
    } else {
        Date date = new Date();
        startTime = DateUtil.offsetDay(date , -10).getDate();
        endTime = DateUtil.formatDate(date);
    }

    //查询处理中的绑卡流水
    LambdaQueryWrapper<PayMerchantBankCardFlow> bankCardFlowQuery = new LambdaQueryWrapper<PayMerchantBankCardFlow>()
            .eq(PayMerchantBankCardFlow::getStatus, StatusEnum.DEALING.getCode())
            .between(PayMerchantBankCardFlow::getCreateTime, startTime, endTime);

    List<PayMerchantBankCardFlow> listBankCardFlow = payMerchantBankCardFlowManager.list(bankCardFlowQuery);
    
    ...
}
View Code

然后,我们把这段代码稍作改动,主要是变更了第二个被调方法 doPaymentAuthResultQuery 的参数。大家来比较一下,改动前后,哪个更优一些。

程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴
@Override
public void execute(String jobParameter) {
    log.info("亿联绑卡打款认证结果查询-定时任务:{}", jobParameter);
    try {
        String startTime, endTime;
        if (StringUtil.isNotEmpty(jobParameter)) {
            JSONObject jsonObject = JSON.parseObject(jobParameter);
            startTime = jsonObject.getString("startTime");
            endTime = jsonObject.getString("endTime");
        } else {
            Date date = new Date();
            startTime = DateUtil.offsetDay(date , -10).getDate();
            endTime = DateUtil.formatDate(date);
        }
        doPaymentAuthResultQuery(startTime, endTime);
    } catch (Exception e) {
        log.error("亿联绑卡打款认证结果查询-定时任务异常:", e);
    }
}

private void doPaymentAuthResultQuery(String startTime, String endTime) {

    //查询处理中的绑卡流水
    LambdaQueryWrapper<PayMerchantBankCardFlow> bankCardFlowQuery = new LambdaQueryWrapper<PayMerchantBankCardFlow>()
            .eq(PayMerchantBankCardFlow::getStatus, StatusEnum.DEALING.getCode())
            .between(PayMerchantBankCardFlow::getCreateTime, startTime, endTime);

    List<PayMerchantBankCardFlow> listBankCardFlow = payMerchantBankCardFlowManager.list(bankCardFlowQuery);
    
    ...
}
View Code

 

 

【下面是正文】

在接收到请求参数后,我们的程序应该先进行参数的合法性校验,包括非空判断、数据格式校验以及数据有效性校验,然后再执行后续的业务逻辑。尤其对于分布式架构模式的系统,更要先进行参数的合法性校验,再调用后续的RPC接口。关于这个基本的程序设计和实现,我相信大家对此没有什么异议。

再一点,单就RPC接口的调用,程序设计和实现上也有必要说道说道。

我们来看一个案例。

前端页面上,用户在订单详情页确认完信息后,点击“确认支付”,发起余额支付。

程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴

这里,我们做如下3项设定。

1)网站后台程序暴露的“支付”REST接口名为 order/pay。

2)后台程序对于“支付”的处理逻辑,我们简化成下面的业务流程。

3)后台程序是分布式的微服务结构,包括提供REST接口的MVC服务和后面提供RPC接口的订单服务、账户服务。

程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴

 

 

那么, 比较下面两种实现方式,左边第一种是在order/pay这个REST接口里先查单校验订单状态,通过后才调用订单服务的“支付订单”RPC接口。右边第二种是直接转发请求给订单服务的“支付订单”RPC接口。你更倾向于哪一种实现方式呢?

程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴 

 

 

相比来说,我认为第一种更靠谱一些。

Why?

看上去,虽然两种实现方式都能达到目的,第一种方式还多了一个前置的校验。为什么我建议采用第一种方式呢?

这是典型的程序业务处理的方式。——接收到请求入参后,先进行前置校验,如果校验失败直接中止返回,否则才走后续的业务处理流程。

 

有同学就说了,按第二种实现方式,直接调用订单服务的“支付订单”RPC接口,“支付订单”RPC接口的实现里不是也有订单状态的前置校验吗?

这是有区别的。按第一种实现方式的话,支付订单RPC接口除了流程图里的实现方式外,也可以省掉查询订单这一步,直接通过包含状态机幂等的update操作来变更订单状态(sql诸如UPDATE order SET pay_status='PAYING' WHERE order_no = '001' AND pay_status = 'INIT'),根据update是否成功来决定后面的扣减用户余额的逻辑。如果采用第二种实现方式,那就最好先老老实实的通过查询订单来判断状态,毕竟数据库的update开销比select开销要高。

从技术的角度来分析,两种实现方式也是有区别的。“支付订单”作为一个业务处理的RPC接口,我们要做的控制会比较多,例如事务控制、幂等、异常处理、耗时、锁、监控,等等。因此,从这个角度来看,在确认需要支付订单的时候再调用“支付订单”,是不是更合理呢?

 

类似的案例,也包括,我们的MQ消费者,在从队列里拿到消息后,先进行必要的判断和校验,然后再调用业务方法。而不是一上来就直接把参数丢给业务方法。

 

本文设计文稿物料:https://www.processon.com/view/link/611e38c2e0b34d3511f7c479

 


 

 

花絮:

人力外包需求开发完成后,我们那天上午在评审代码时,针对“发起结算”这个controller方法是否做前置校验的事情上出现分歧。Yamei和Haipeng等人认为没必要做前置校验,反正后面调用的dubbo接口的实现里也会做前置校验。尽管我做了一些解释,终未能达成共识。 下午继续评审代码时,看到一个mq的listener方法里,解析到业务单号后,直接将业务单号作为入参调用业务处理方法。Yamei建议这个listener方法先验证业务单据,验证通过后再调用业务处理方法。  我向她确认了她是这个观点后,类比了上午的争论,我俩相视一笑。举一反三,多么重要。

 

分享:

经验这个东西,往往并不能告诉我们什么一定对,但是可以告诉我们什么一定不对。----《The Pragmatic Programmer,程序员修炼之道:从小工到专家》
文章来源地址https://www.toymoban.com/news/detail-710730.html

到了这里,关于程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 仅仅是调用第三方接口那么简单吗?

    最近有个项目需要本地处理之后,然后调用第三方接口,本来开始觉得很简单得事情,不就是调用第三方接口吗?但是却一波三折。 首先有了下面的第一版的设计。 这个设计很简单,也是最容易想到的。主要有下面几步 1、本地处理; 2、调用第三方接口; 3、本地日志打印

    2024年02月06日
    浏览(66)
  • uniapp小程序实现调用前置拍照上传

      官方文档:

    2024年02月15日
    浏览(54)
  • 如何保证对外接口的安全?

    1.什么是安全接口? 通常来说要将暴露在外网的 API 接口视为安全接口,需要实现防篡改和防重放的功能。 1.1 什么是篡改问题? 由于 HTTP 是一种无状态协议,服务端无法确定客户端发送的请求是否合法,也不了解请求中的参数是否正确。以一个充值接口为例: 如果非法用户

    2024年03月08日
    浏览(49)
  • 如何设计一个安全的对外接口 ?

    最近有个项目需要对外提供一个接口,提供公网域名进行访问,而且接口和交易订单有关,所以安全性很重要;这里整理了一下常用的一些安全措施以及具体如何去实现。 个人觉得安全措施大体来看主要在两个方面,一方面就是如何保证数据在传输过程中的安全性,另一个方

    2024年02月08日
    浏览(79)
  • 如何设计一个安全的对外接口

    非对称加密:服务端会生成一对密钥,私钥存放在服务器端,公钥可以发布给任何人使用;优点就是比起对称加密更加安全,但是加解密的速度比对称加密慢太多了;广泛使用的是RSA算法; 两种方式各有优缺点,而https的实现方式正好是结合了两种加密方式,整合了双方的优

    2024年04月16日
    浏览(61)
  • 业务开发时,接口不能对外暴露怎么办?

    在业务开发的时候,经常会遇到某一个接口不能对外暴露,只能内网服务间调用的实际需求。面对这样的情况,我们该如何实现呢? 今天,我们就来理一理这个问题,从几个可行的方案中,挑选一个来实现。 推荐一个开源免费的 Spring Boot 实战项目: https://github.com/javastacks

    2024年02月12日
    浏览(44)
  • 2023 TVBox 电视盒子 最新配置接口地址 持续更新 公开自用大佬源

    TVBox专业版2023是一款专门为用户打造的电视盒子软件,TVBox官方下载最新版汇聚了海量电视节目与影视资源,用户简单的就能找到自己喜欢的分类板块,都能拥有超赞的观影体验。电影、电视剧、少儿、综艺、动漫、音乐、体育等节目分类特别分明,你想要的这里都能为你提

    2024年02月11日
    浏览(95)
  • 超详细!完整版!基于spring对外开放接口的签名认证方案(拦截器方式)

    由于项目需要开发第三方接口给多个供应商,为保证Api接口的安全性,遂采用Api接口签名验证。 请求发起时间得在限制范围内 请求的用户是否真实存在 是否存在重复请求 请求参数是否被篡改 1、服务端生成一对 accessKey/secretKey密钥对,将 accessKey公开给客户端,将 secretKey 保

    2024年01月22日
    浏览(57)
  • 创建OneNET新版MQTT设备:实现远程控制单片机 为微信小程序与单片机通信打基础(微信小程序通信单片机前置任务)

    本项目教程总共分为四节 1.(当前文章)创建OneNET新版MQTT设备:为微信小程序与单片机通信打基础(微信小程序通信单片机前置任务) 2.ESP8266-01s入门:烧录AT固件与OneNET MQTT通信教程包含MQTT.fx1.7.1教程(微信小程序通信单片机前置任务) 3.物联网实践教程:微信小程序结合

    2024年02月04日
    浏览(83)
  • 仅仅用java就能简单实现区块链(BlockChain)

    区块链逻辑:根据所需信息创建一个区块,再利用定义的计算hash值方法,不断进行计算,直到达到想要的结果,再通过层层验证,加入到我们的区块链中。 所谓挖矿,就是进行不断地计算,直到“挖到”,而这步算法我们是借助hash算法完成的。 老实说,“挖矿”这件事本身

    2024年02月02日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包