后端思维篇:如何抽个上报模板

news2024/12/26 22:33:04

前言

大家好,我是田螺

我的后端思维专栏好久没更新啦,本文是后端思维专栏的第六篇哈。我的整个后端思维专栏都是跟日常工作相关的哈。

最近刚好优化了安全上报这块的代码,抽了一个基础模板,看起来挺优雅的。所以今天手把手教大家,基于重复代码,如何思考和抽取模板

  • 公众号:捡田螺的小男孩
  • github地址,感谢每颗star:github

1. 优化前的代码

我们的业务场景,如修改密码,修改pin等,需要将操作结果上报到安全管理中心系统。优化前的伪代码如下:

修改密码的逻辑:

  public Response<?> modifyPasswordWithReportSafe(Request request) {

        boolean isSuccess = true;
        Response<?> response = null;

        try {
            //修改密码
            return modifyPasswordAdaptor.modifyPassword();
        } catch (BizException bizException) {

            log.warn("修改密码业务异常",  bizException);
            isSuccess = false;
            response = new Response<>().fail("", bizException.getCode(), bizException.getMsg());
            throw bizException;

        } catch (Exception e) {

            log.warn("修改密码系统异常", e);
            isSuccess = false;
            response = new Response<>().fail("", "666", "系统异常");
            throw e;

        } finally {
            //上报安全
            log.info("修改密码上报安全,userId:{}", request.getUserId());
            securityService.report(request, isSuccess, response);
        }
    }
复制代码

修改pin的业务逻辑:

      public Response<?> modifyPinWithReportSafe(Request request) {
        
        boolean isSuccess = true;
        Response<?> response = null;

        try {
            //修改pin
            return modifyPinAdaptor.modifyPin();
        } catch (BizException bizException) {

            log.warn("修改pin业务异常", bizException);
            isSuccess = false;
            response = new Response<>().fail("", bizException.getCode(), bizException.getMsg());
            throw bizException;

        } catch (Exception e) {

            log.warn("修改pin系统异常", e);
            isSuccess = false;
            response = new Response<>().fail("", "666", "系统异常");
            throw e;

        } finally {
            //上报安全
            log.info("修改pin上报安全,userId:{}", request.getUserId());
            securityService.report(request, isSuccess, response);
        }
    }
复制代码

2. 如何抽取一个安全上报模板

大家观察以上优化前的代码,是否可以发现修改pin修改密码,都有一些重复的代码(我框起来的都是重复代码)

这个try-catch-finally中的代码块,除了try修改业务逻辑的代码日志打印是不一样的,其他地方几乎都是重复一样的。

2.1 抽取基础通用模板

所以我们可以抽取个try-catch-finally的通用模板,把这块相同的代码放进来。先定义一个SecurityReportTemplate的类,然后try-catch-finally的相同代码搬过来,如下:

@Component
@Slf4j
public class SecurityReportTemplate {

    @Resource
    protected SecurityService securityService;

    public Response<?> reportTemplate(Request req) {

        boolean isSuccess = true;
        Response<?> response = null;

        try {
             
        } catch (BizException bizException) {
          
            isSuccess = false;
            response = new Response<>().fail("", bizException.getCode(), bizException.getMsg());
            throw bizException;
        } catch (Exception e) {
            isSuccess = false;
            response = new Response<>().fail("", "666", "系统异常");
            throw e;

        } finally {
            securityService.report(req, isSuccess, response);
        }

        return response;
    }
}

复制代码

抽取完这个基础模板,我们还有两件事情需要做,那就是日志处理,和真正实现的业务逻辑如何接入进来。

2.2 处理日志差异化

因为原来的方法,try-catch-finally的分支都是有打印日志的,是不是直接把原来代码搬过来就可以了?不是的,因为原来每个业务场景(如修改pin和修改密码)的日志打印会有点不一样,即需要区分业务场景

因此,在模板里面,我没让你可以在请求参数Request新增个业务类型参数,然后打印日志时,把对用的参数类型打印出来,就可以啦:

2.3 函数式接口妙用

以上的模板抽得查不多啦,还剩下业务逻辑的方法,如何传进来呢?也就是说,修改密码、修改pin的逻辑,如何传到模板里面的。

我们以前通用的做法,就是让在模板方法里面,声明一个业务逻辑处理的方法,然后让修改密码、修改pin的处理类继承模板类,这样就可以了。但是田螺哥给大家介绍一个更优雅的实现,那就函数式接口。

因为函数式接口可以被隐式转换为lambda表达式,看起来也会更优雅,也比继承更轻量一点。我先声明一个函数式接口如下:

@FunctionalInterface
public interface RiskReportRunner {

    /**
     * 业务逻辑处理的函数式接口
     * @return Response<?>
     */
    Response<?> reportWithBizRunner();
}
复制代码

然后把函数式接口接入到模板里面,如下:

@Component
@Slf4j
public class SecurityReportTemplate {

    @Resource
    protected SecurityService securityService;

    public Response<?> reportTemplate(RiskReportRunner riskReportRunner, Request req) {

        boolean isSuccess = true;
        Response<?> response = null;

        try {
            response = riskReportRunner.reportWithBizRunner();
        } catch (BizException bizException) {
            
            log.warn("bizType :{}, operate BizException", req.getBizType(), bizException);
            isSuccess = false;
            response = new Response<>().fail("", bizException.getCode(), bizException.getMsg());
            throw bizException;
        } catch (Exception e) {
            
            log.warn("bizType :{}, operate system,Exception", req.getBizType(), e);
            isSuccess = false;
            response = new Response<>().fail("", "666", "系统异常");
            throw e;

        } finally {
            log.info("report security,bizType:{}", req.getBizType());
            securityService.report(req, isSuccess, response);
        }

        return response;
    }
}
复制代码

3. 优化后的代码

有了基础的上报模板,原来的修改pin,修改密码就可以优化成这样啦:

修改密码:

    @Resource
    private SecurityReportTemplate securityReportTemplate;

    public Response<?>  modifyPasswordWithReportSafeAfter(Request request) {
        return securityReportTemplate.reportTemplate(() -> modifyPasswordAdaptor.modifyPassword(), request);
    }
复制代码

修改pin:

    @Resource
    private SecurityReportTemplate securityReportTemplate;

    public Response<?>  modifyPinWithReportSafeAfter(Request request) {
        return securityReportTemplate.reportTemplate(() -> modifyPinAdaptor.modifyPin(), request);
    }
复制代码

如果未来接入修改一次性密码等等其他业务场景,都是直接用SecurityReportTemplate调一下就好,可以说非常优雅!

唠叨几句

本文大家学到了哪些知识呢?

为了写出更优雅、更简洁的代码,我们需要学会如何抽取一些通用的基础模板。包括一些try-catch-finally代码块,有时候也是有共性的,比如本文,就是try-catch-finally代码块都在处理为上报的逻辑服务,因此可以抽取个上报通用模板。

在工作中呢,我们想成为一名更优秀的程序员,就需要保持优化代码这种嗅觉,在恰当的开发阶段,把原有不好的代码优化掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114914.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

〖产品思维训练白宝书 - 产品思维认知篇⑤〗- 学习 [产品思维] 需要做哪些准备?

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

php wampserver的使用配置

php wampserver的使用配置wampserver1.php时区配置2.修改apache服务器端口号3.设置起始页4.设置web服务器主目录5.设置虚拟目录wampserver WampServer是Windows Apache Mysql PHP集成安装环境&#xff0c;在Windows操作系统下的apache、php和mysql的服务器软件。 1.php时区配…

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.2 Consumer Ack7.2.1 Consumer Ack7.2.2 Consumer Ack 小结7.2.3 消息可靠性总结第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack 7.2.…

12.25日周报

周报 代码行数&#xff1a; 周一 704 周二 481 周三 571 周四 589 周五 595 周六 520 周日 537 遇到的问题&#xff1a; 没用过的方法AtomicInteger Insert Proto currentTimeMillis RequestParam BufferedReader UriComponents RestTemplate OSS 不清楚在…

公众号开发(2) —— 盛派.net SDK + vue搭建微信公众号网页开发框架

需求&#xff1a;通过微信公众号菜单跳转到手机端网页&#xff0c;跳转后通过微信授权登录获取微信公众号用户的OpenId&#xff08;用户关注公众号后&#xff0c;用户在公众号的唯一凭证&#xff09;&#xff0c;通过OpenId和后台数据库用户信息绑定起来并实现一些业务逻辑。 技…

基于51单片机的电子闹钟设计

使用的单片机是 STC89C52 此设计可以 年 月 日 时 分 秒显示和闹钟功能 能通过8个按键自由调整 时 分 秒 闹钟响铃时间 带复位按键&#xff0c;要是模块抽风&#xff0c;摁复位按键即可&#xff01; 使用 LCD16020A 屏幕显示 屏幕电路设有电位器&#xff…

Tableau可视化设计案例-07 多边形地图和背景图地图

Tableau可视化设计案例 本文是Tableau的案例&#xff0c;为B站视频的笔记&#xff0c;B站视频 参考&#xff1a;https://www.bilibili.com/video/BV1E4411B7ef 参考&#xff1a;https://blog.csdn.net/lianjiabin/category_9826951.html 数据下载地址为&#xff1a;https://do…

Java项目:springboot药品管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目属于前后端分离的项目&#xff0c;分为两个角色药品管理员和取药处人员 药品管理员&#xff1a; 登录、退出、药品信息录入、药厂信息录入…

Huawei Certified ICT Professional work (一)

文章目录一&#xff0c; 要求二&#xff0c;搭建拓扑图三&#xff0c;配置接口IP和环回IP四&#xff0c;进行RIP版本的配置并且宣告网段五&#xff0c;实现不同版本的连通&#xff0c;在交界处配置对端的版本号六&#xff0c;R3访问R7的环回地址走R5&#xff0c;改变R4的度量值…

Java项目:SpringBoot+MyBatis送水公司管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 这个项目是一个基于SpringBootMyBatis的送水公司管理系统 管理员权限包括&#xff1a; 客户管理 送水工管理 送水历史管理 计算工资 统计送水数…

79页智慧应急指挥平台1 6 N体系建设方案

【版权声明】本资料来源网络&#xff0c;仅用于行业知识分享&#xff0c;供个人学习参考&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间进行删除&#xff01; 完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 行业专网解决…

ARM_SMMU_下

SMMU驱动代码分析 本文主要分析linux kernel中SMMUv3的代码(drivers/iommu/arm-smmu-v3.c) linux kernel版本是linux 5.7, 体系结构是aarch64 SMMU的作用是把CPU提交给设备的VA地址&#xff0c;直接作为设备发出的地址&#xff0c;变成正确的物理地址&#xff0c;访问到物理内…

五、传输层(一)传输层的功能

目录 1.1传输层的主要功能 1.2传输层的寻址与端口 1.2.1端口的作用 1.2.2端口号 1.2.3套接字 1.3无连接服务与面向连接服务 1.1传输层的主要功能 物理层、数据链路层和网络层共同解决了主机通过异构网络互联起来所面临的问题&#xff0c;实现了主机到主机的通信。然而在…

【iOS】CAlayer的认识与使用

什么是CALayer CALayer是UIView里的一个图层&#xff0c;其主要功能是负责显示视图与动画。CALayer和UIView 功能是一致的、 不过因为其 更加底层 所以 CALayer 有一些接口、 UIView 里面没有。 CALayer与UIView UIView&#xff1a;用于管理视图的容器。每次创建UIView对象时…

当我阳了之后是如何用Python来自动买药的

人生苦短&#xff0c;我用Python序言准备工作代码实战序言 哈喽兄弟们&#xff0c;我是郑再阳&#xff0c;马上要成杨过了&#xff01; 读者&#xff1a;在下羊了个羊&#xff01; 最近总是听说哪里哪里阳了&#xff0c;哪个公司又团灭了&#xff0c;emmm~ 于是乎看了几天后…

【exgcd】扩展欧几里得

主要介绍扩展欧几里的和总结一些常用性质 首先介绍裴蜀定理 对于任意整数a,b,存在一对整数x,y 满足 axbygcd(a,b) 即存在x0,y0使得ax0by0gcd(a,b) 扩展欧几里得可以求出x0,y0 从而当axbyc 可以求出其通解 设dgcd(a,b) 显然当c%d!0时无整数解 通解可以表示为 x(c/d)x0k…

Java项目:springboot访客管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 springboot搭建的访客管理系统&#xff0c;针对高端基地做严格把控来访人员信息管理&#xff0c;用户后端可以设置多个管理员帐号&#xff0c;给…

力扣(LeetCode)207. 课程表(C++)

拓扑排序 根据示例看出&#xff0c;课程表是否存在环&#xff0c;是问题的关键。这题的环&#xff0c;和数组、链表的环不一样&#xff0c;不好判&#xff0c;要转化成图判拓扑序列。 考虑向右和向左的方向&#xff0c;拓扑序列的所有边可以指向同一方向。 无环图进行重排序…

论文阅读Measuring Regularity of Individual Travel Patterns

这是一篇发表在IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS上的论文&#xff0c;论文主要描述了一种刻画出行规律性的方法。 1.论文概述 论文主要描述了一种刻画出行规律性的方法。首先&#xff0c;论文给出了对出行活动序列&#xff08;travel event&#xff…

因果推断3--DRNet(个人笔记)

目录 Learning Counterfactual Representations for Estimating Individual Dose-Response Curves 1介绍 2相关工作 3方法 4实验 5结果和讨论 6结论 7理解 论文标题 Learning Counterfactual Representations for Estimating Individual Dose-Response Curves 收录会…