# 简历 **Repository Path**: shenghuada/biographical-notes ## Basic Information - **Project Name**: 简历 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-15 - **Last Updated**: 2025-04-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 面试官你好,。 我是香港中文大学自动化专业的毕业生,绩点是3.7,是年级的前百分之5, 本科阶段在重庆大学学习车辆工程,在大学的学习期间,积累了扎实的java编程基础,并且做过一些与java后台开发相关的项目。然后我有两次实习,最近的一次实习,是在杭州的速新家政公司做java后端工程师,参与开发类似天鹅到家的家政平台,能为客户提供各种服务,我在这个项目中主要负责设计和开发订单管理模块,目前该项目已成功上线。还有一次是在香港的莽荡公司做机器人运动控制工程师,负责设计一些机器人的动作,并实现与机器人的交互, 我擅长Spring Boot、Spring Cloud、MyBatis、MyBatis Plus、若依框架。在日常开发中,我经常使用MySQL和Redis作为主要的数据库。我也有在Spring Cloud Alibaba微服务项目中开发的经验,比较熟悉一些热门组件,比如Nacos服务注册与发现、Seata分布式事务、Feign调用、GateWay网关、Sentinel服务保护。此外,我也使用过RabbitMQ作为消息中间件,并且对XXL-Job、ElasticSearch,Redisson技术有一定的了解。并且我在项目中使用过不同的设计模式,包括工厂模式和状态机模式对项目进行优化。 我对软件开发技术领域有着浓厚的兴趣,在以往的项目中,我通过自学和实践不断提升自己的技术水平。 订单父工程包括订单管理模块、抢单模块、历史订单模块、派单模块 **我负责的是订单工程的订单管理模块,主要包括订单表的设计、下单、订单状态跟踪、对接支付服务、取消服务、退款、订单查询优化** 业务流程:用户进入服务详情页选择数量,然后选择地址和预约时间,然后选择优惠券 然后服务端就会完成整个创建订单的过程 1.通过OpenFeign远程调用获取到下单用户的信息及服务信息 2.填充订单数据 3.判断是否选择了优惠券。是:要计算优惠金额和实付金额 4.创建订单。同时选择了优惠券需要远程核销优惠券 5.返回订单ID ##### 表设计 订单表设计:因为我们家政业务的需求:是专人负责专事,如修空调的师父的技能,其他家政人员不一定会。所以我们在设计下单功能时,只允许一个订单只能预约一个具体的服务。所以我们把订单表设计成了一张表,并没有设计订单详情表和购物车,里面的内容主要是五部分,(**这五部分的核心字段是需要说的**) #### image-20250403144047188 image-20250403144620475 **核心字段**:服务id,订单状态支付状态退款状态,单价件数总价,客户姓名手机地址服务开始时间,支付的交易单号,第三方交易单号,支付渠道 最重要的就是订单号,我们项目的订单号是这么设计的,订单类型 + 年月日 + 12位自增Redis值,一共19位,如果是用户下单,那就是1号类型订单,年月日是当前时间信息,剩下12位储存在redis中 **可以提一提的字段**:sortby 服务开始事件+订单后六位 #### 下单业务优化 还对代码进行了优化: **1.因为在下单的过程中,我们业务需要远程调用获取家政服务的具体信息和客户信息服务写入订单数据,但是,如果因为基础服务不可用或者网络波动,会影响我们的订单接口,可能会导致服务雪崩** 解决办法:所以采用阿里的组件sentinel,对远程调用的方法做了熔断和降级,加上了@SentinelResource注解,降级和熔断的时候,会返回一个空的订单对象,然后订单id设置为-1,然后在主程序内部做一个检测,当检测到id小于0的时候,抛出异常 **2.远程调用的接口可能因为网络波动,导致比较耗时,又因为整个service层有事务注解,会导致事务超时回滚,或者耗尽数据库连接池的资源** 解决办法:我把这个下单模块中和事务有关的方法,进行一个抽取,为方法加一个事务,去掉service层的事务注解 **3.会导致AOP问题,我用了this来调用抽取出来带事务的方法,但是事务方法底层是AOP是需要代理对象来调用的,而不是通过this,这个service实现类来调用,导致事务失效** 解决办法:把这个方法抽取到另一个业务类中来调用 **4.重复下单问题,下单抖动问题**(详情看redis的八股文) 解决办法:采用分布式锁来处理,自定义注解,自定义切面,分布式锁 分布式锁redis的id是如何设置的?**LOCK前缀+用户id+服务id+服务开始时间** 锁的过事件是10s ![image-20250406115954171](C:\Users\Friday\AppData\Roaming\Typora\typora-user-images\image-20250406115954171.png) ![.](C:\Users\Friday\AppData\Roaming\Typora\typora-user-images\image-20250406121139898.png) **5.下单的时候可以使用优惠券,需要远程调用优惠券的核销接口,为了保证分布式环境的事务问题,我使用了Seata的AT模式实现了分布式事务的保证** @GlobalTransactional 用户过微信小程序发起支付,请求订单管理服务,订单管理服务请求支付服务进行支付(为什么自己开发支付服务,因为公司有很多项目都需要对接三方支付接口,如果每个项目都自己去对接,那么这些工作都是很大的,并且重复的) ##### 项目的支付服务有哪些接口? 项目的支付服务对接了微信、支付宝的Native、jsapi等常用支付方法。 支付服务提供以下接口: 1. 支付接口:此接口请求第三方支付平台的下单接口,下单成功生成交易单数据写入数据库,并把(订单id,微信订单id,支付渠道)给订单模块 2. 支付结果查询接口:此接口请求第三方支付平台的支付结果查询接口,根据我们交易表的id去交易服务查询支付结果,并返回结果给订单模块 3. 退款接口:此接口请求第三方支付平台的退款接口,也是拿着交易id去查询,如果已退款,此接口会返回退款记录给业务系统。 4. 异步接收支付通知接口:此接口接收第三方支付平台的支付结果,支付服务获取支付结果通过MQ通知业务系统。 1. 支付渠道表:保存接入的三方支付平台信息(比如微信支付的参数,appId,回调地址,公钥私钥) 2. 交易表:支付服务维护的交易表,去第三方平台下单就会生成一条交易记录(订单号,支付单号,第三方支付单号,支付状态,支付金额) 3. 退款记录表:支付服务维护的退款记录表,根据退款记录表去退款(订单号,退款单号,第三方退款单号,支付状态,支付金额) 4. 订单取消表:订单取消之后,支付服务维护的一张表,记录订单取消的原因 ##### 业务流程 项目有统一的支付服务与第三方支付平台对接,我们的订单服务对接支付服务。 1.首先用户点击支付之后,订单服务会调用支付服务的**支付接口**(**把商户号,订单号,支付金额(为什么微信前端能知道要付多少钱,支付渠道**传给支付服务),支付服务会去调用微信小程序的下单接口,然后微信创建一个预支付订单,然后还会返回一个prepare_id然后传到前端调起支付的界面,用户可以选择余额或者银行卡支付,再给微信发支付请求的同时,支付服务会往交易表中写入一条交易数据,然后我们会更新我们订单(新增交易订单号和支付渠道) 2.在用户支付后用户点击“完成支付”,此时前端请求订单服务的查询支付结果接口,然后订单服务会拿着支付单的id去查询支付服务的**支付结果查询接口**,如果支付成功则跳转到支付成功界面,并且更新订单(订单状态该为“派单中”,支付状态改为“已支付”, 并且把orders里的第三方订单id赋值) 3.用户支付成功后支付服务,微信会把支付结果异步通知支付服务的**接收支付通知接口**,支付系统拿到支付结果,修改支付单状态,把支付结果发到MQ中(之前订单模块可以直接远程调用支付模块,而支付模块对接好几个模块,所以不能直接远程调用订单模块)和交换机连接的获取支付结果的有好几个队列,比如vip订单,优惠券订单,交换机会带着Product_app_id(业务系统的标识,支付模块之前写交易记录的时候就记载了Product_app_id, 然后支付模块制作发给别的模块的msg的时候,会把交易记录的ProId拿出来,写进msg里面)发给所有绑定的队列,订单收到支付结果后解析出product_app_id,判断是否属于自己的支付结果通知,如果是再进行处理,然后修改订单状态,支付状态,赋值id 4.设置了定时任务,支付服务也会自己轮询查询第三方平台支付结果,修改订单和交易单状态 取消订单,一种是订单未支付,更改订单状态为已取消,第二种是,订单已支付,更改订单状态为已关闭,然后自动退款 订单未支付:1.用户在订单详情界面可以点击取消订单,选择取消原因或者输入取消原因,然后发送到后端,后端修改订单状态为**已取消**(600),并且把取消信息写入取消订单表 2.订单超时未支付也会自动取消订单,针对这种情况,我们采取了两种措施, ​ 1.定时任务,我用的是xxl-job一个组件,每分钟查找订单状态为未支付并且超时的订单数据,并且修改订单状态为已取消,写入取消订单表 ​ 2.懒加载方式,产品的需求是用户能及时的看到支付状态,所以我们采用懒加载的方式,只有当用户点进订单详情界面的时候,才会发起请求,查询订单是否超时未支付,会去支付服务查询最新的支付结果,如果超时未支付,则修改订单状态,并且写入取消订单表 订单已支付:这个时候用户已经支付,所以不仅需要添加取消订单记录,更新订单状态为**已关闭**(700) 还要添加退款记录进退款记录表。因为请求第三方退款接口涉及远程调用,我们不想影响事务,所以我们设置了定时任务, 会根据退款记录表的数据,去请求第三方支付服务的退款接口,根据退款结果进行处理,如果退款成功将更新订单的退款状态为退款成功、然后把退款的订单号和第三方退款的账号写进订单中,最后删除退款记录。 后面又有需求,要让用户获得及时退款,我们会在修改订单状态的时候**开一个新的线程来**调用第三方退款接口,来获得更好的用户体验 ##### 项目的退款功能怎么实现的? 取消订单执行退款操作。 1、首先使用一个事务保存以下数据 更新订单状态。 保存取消订单记录,记录取消的原因等信息。 保存退款记录。 2、事务提交后先启动一个线程请求支付服务的退款接口 3、定时任务扫描退款记录表,对未退款的记录请求支付服务进行退款,退款成功更新订单的退款状态,并删除退款记录。 说明: 第2步的作用为了第一时间申请退款,因为定时任务会有一定的延迟。 第3步的作用是由定时任务去更新退款的状态,因为调用了退款接口只是申请退款了,退款结果可能还没有拿到,通过定时任务再次请求支付服务的退款接口,拿到退款结果,更新订单的退款状态,并删除退款记录。 取消订单,要根据不同的状态,做不同的逻辑判断 因为订单的状态很多,并且变更的地方很多,经常对订单状态做一些ifelse判断,不同的状态执行不同得动作,为了方便管理订单的状态,避免状态变更硬编码的问题。使用状态机设计模式来统一管理订单状态。 状态机:主要由四部分组成:现态、事件、动作、次态。现态:现在状态,次态:修改后的状态,事件:修改状态触发的事件,动作:把现态修改为次态的行为。 举例:用户支付成功,把订单状态由未支付修改成派单中。那么这里的现态就是未支付,次态就是派单中,事件就是用户支付成功,动作就是修改订单状态从未支付到派单中。 结合状态机模式,我们设计了接口与抽象类,用于提供状态机的规范,包括订单状态的枚举类、状态变更事件枚举类、订单变更动作类、订单快照类、状态机类(状态机名字order)等。 定义一个状态机类:用于管理状态包括三个核心方法 启动状态机:初始化订单状态 改变状态方法:把对应的订单ID、事件、订单的快照数据,传入对应事件方法。这个方法就可以统一修改订单的状态,以此来避免硬编码问题 后置方法:订单状态改变成功后,用于处理订单完成后收尾工作。