在电商系统中,订单的处理流程通常涉及多个步骤,每个步骤都可能有不同的业务逻辑。例如,当用户提交订单时,系统需要校验库存、验证优惠券、计算运费、处理支付、分配物流等。这些操作看似独立,但实际上具有一定的顺序依赖性。为了更好地管理这些业务逻辑,我们需要将这些流程模块化,并按需执行。
通常的做法是将所有逻辑写在一起,但这会导致代码冗长且难以维护。如果未来需要对某个步骤进行修改或者添加新的处理环节,代码变动的范围将会很大。为了避免这种情况,职责链模式提供了一个灵活、可扩展的kb88凯时官网登录的解决方案。
什么是职责链模式?
职责链模式(chain of responsibility)是一种行为设计模式,它允许多个对象都有机会处理请求,直到其中一个对象处理成功为止。职责链模式使多个处理对象通过链式关系链接在一起,每个处理对象知道它的下一个处理对象,并且在完成自身处理后,将请求传递给下一个对象。
职责链模式的优点:
- 解耦请求发送者和接收者:请求发送者不需要知道是谁在处理请求,避免了系统中各个模块的强耦合。
- 灵活扩展:通过调整链条中的处理器顺序,或者增加新的处理器,可以灵活地扩展业务逻辑。
- 动态组合:职责链的处理器可以动态组合,可以根据不同的需求创建不同的链条。
适用场景:
- 需要对请求进行一系列处理,并且请求处理者不明确或不固定时。
- 多个对象可以处理同一个请求,具体由运行时动态决定哪个对象来处理。
职责链模式在电商订单流程中的应用
在电商系统中,职责链模式可以将订单处理过程中的各个环节(如库存校验、优惠券核验、支付处理等)封装为独立的处理器,并通过职责链将这些处理器串联起来。每个处理器独立处理其对应的任务,处理完成后将请求传递给下一个处理器,直到所有处理环节完成或者中断。
运行效果:
本文将深入探讨如何通过职责链模式来处理电商订单流程,并结合 spring boot 3.3 和前后端代码示例,展示如何实现这一模式。同时,前端使用 jquery 调用后端 json 接口,并通过 bootstrap 提示用户订单处理的结果。
pom 文件配置
项目中我们需要使用 spring boot 和 thymeleaf 模板引擎,具体依赖配置如下:
4.0.0 org.springframework.boot spring-boot-starter-parent 3.3.3 com.icoderoad order-chain 0.0.1-snapshot order-chain demo project for spring boot 17 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-thymeleaf org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin
配置文件 application.yml
使用 @configurationproperties
读取订单处理链的配置步骤:
order: chain: steps: - "ordervalidationhandler" - "verifycouponhandler" - "shippingfeehandler" - "totalamounthandler" - "processpaymenthandler"
订单处理职责链实现
为了优化 handler
方法,可以结合订单的处理流程,对不同的 handler
进行职责分工,比如验证订单信息、处理优惠券、计算运费和最终结算等步骤。我们可以使用职责链模式(chain of responsibility)将这些不同的处理逻辑独立封装在各自的 handler
类中,并且每个 handler
负责处理其自身的逻辑,处理完后将处理流程交给下一个 handler
。
我们将实现以下几个 handler
:
- 订单验证处理器(
ordervalidationhandler
):负责验证订单的基本信息,比如商品是否存在、库存是否充足等。 - 优惠券处理器(
couponhandler
):负责处理优惠券的校验和折扣计算。 - 运费处理器(
shippingfeehandler
):负责计算订单的运费。 - 总金额处理器(
totalamounthandler
):负责计算订单的总金额。 - 支付处理器( paymenthandler`):负责订单支付功能。
每个 handler
类都遵循职责链的接口,将逻辑封装在 handler
中,最后调用下一个 handler
。
订单请求类 orderrequest.java
package com.icoderoad.orderchain.entity; import java.math.bigdecimal; import java.util.list; import lombok.data; @data public class orderrequest { // 商品列表 private listproductlist; // 用户使用的优惠券 private string couponcode; // 运费 private bigdecimal shippingfee; // 订单总金额 private bigdecimal totalamount; public orderrequest() {} // 构造方法 public orderrequest(list productlist, string couponcode, bigdecimal shippingfee, bigdecimal totalamount) { this.productlist = productlist; this.couponcode = couponcode; this.shippingfee = shippingfee; this.totalamount = totalamount; } // 计算订单总金额(含运费和扣除优惠) public bigdecimal calculatetotalamount() { bigdecimal producttotal = productlist.stream() .map(product -> product.getprice().multiply(bigdecimal.valueof(product.getquantity()))) .reduce(bigdecimal.zero, bigdecimal::add); // 简单模拟优惠金额 bigdecimal discount = (couponcode != null && !couponcode.isempty()) ? bigdecimal.valueof(10) : bigdecimal.zero; return producttotal.add(shippingfee).subtract(discount); } @data // 商品类 public static class product { private string productid; private string name; private int quantity; private bigdecimal price; // 构造方法 public product(string productid, string name, int quantity, bigdecimal price) { this.productid = productid; this.name = name; this.quantity = quantity; this.price = price; } } }
抽象处理器类 orderhandler.java
package com.icoderoad.orderchain.handler; import com.icoderoad.orderchain.entity.orderrequest; public abstract class orderhandler { protected orderhandler nexthandler; // 设置下一个处理器 public void setnexthandler(orderhandler nexthandler) { this.nexthandler = nexthandler; } // 抽象方法,处理订单 public abstract void handle(orderrequest request); }
具体处理器实现
库存校验处理器 ordervalidationhandler
package com.icoderoad.orderchain.handler; import org.springframework.stereotype.component; import com.icoderoad.orderchain.entity.orderrequest; @component public class ordervalidationhandler extends orderhandler { @override public void handle(orderrequest orderrequest) { // 验证商品列表是否为空 if (orderrequest.getproductlist() == null || orderrequest.getproductlist().isempty()) { throw new illegalargumentexception("订单中没有商品"); } // 验证每个商品的库存(此处为模拟逻辑) for (orderrequest.product product : orderrequest.getproductlist()) { if (product.getquantity() <= 0) { throw new illegalargumentexception("商品库存不足: " product.getname()); } } system.out.println("订单验证通过"); // 调用下一个处理器 if (nexthandler != null) { nexthandler.handle(orderrequest); } } }
优惠券核验处理器 verifycouponhandler.java
package com.icoderoad.orderchain.handler; import java.math.bigdecimal; import org.springframework.stereotype.component; import com.icoderoad.orderchain.entity.orderrequest; @component public class verifycouponhandler extends orderhandler { @override public void handle(orderrequest orderrequest) { string couponcode = orderrequest.getcouponcode(); // 简单模拟优惠券验证逻辑 if (couponcode != null && !couponcode.isempty()) { // 假设优惠券折扣金额为 10 bigdecimal discount = new bigdecimal("10.00"); system.out.println("使用优惠券: " couponcode ",折扣金额: " discount); } else { system.out.println("未使用优惠券"); } // 调用下一个处理器 if (nexthandler != null) { nexthandler.handle(orderrequest); } } }
运费处理器
package com.icoderoad.orderchain.handler; import java.math.bigdecimal; import org.springframework.stereotype.component; import com.icoderoad.orderchain.entity.orderrequest; @component public class shippingfeehandler extends orderhandler { @override public void handle(orderrequest orderrequest) { // 简单模拟运费计算逻辑 bigdecimal shippingfee = orderrequest.getshippingfee(); system.out.println("运费: " shippingfee); // 调用下一个处理器 if (nexthandler != null) { nexthandler.handle(orderrequest); } } }
总金额处理器
package com.icoderoad.orderchain.handler; import java.math.bigdecimal; import org.springframework.stereotype.component; import com.icoderoad.orderchain.entity.orderrequest; @component public class totalamounthandler extends orderhandler { @override public void handle(orderrequest orderrequest) { // 计算订单总金额 bigdecimal totalamount = orderrequest.calculatetotalamount(); orderrequest.settotalamount(totalamount); system.out.println("订单总金额: " totalamount); // 调用下一个处理器(如果有) if (nexthandler != null) { nexthandler.handle(orderrequest); } } }
支付处理器 processpaymenthandler.java
package com.icoderoad.orderchain.handler; import org.springframework.stereotype.component; import com.icoderoad.orderchain.entity.orderrequest; @component public class processpaymenthandler extends orderhandler { @override public void handle(orderrequest request) { // 支付处理逻辑 system.out.println("正在处理支付..."); // 支付完成,职责链结束 } }
初始化职责链 orderchainconfig.java
package com.icoderoad.orderchain.config; import java.util.hashmap; import java.util.list; import java.util.map; import org.springframework.boot.context.properties.configurationproperties; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import com.icoderoad.orderchain.handler.orderhandler; import com.icoderoad.orderchain.handler.ordervalidationhandler; import com.icoderoad.orderchain.handler.processpaymenthandler; import com.icoderoad.orderchain.handler.shippingfeehandler; import com.icoderoad.orderchain.handler.totalamounthandler; import com.icoderoad.orderchain.handler.verifycouponhandler; @configuration @configurationproperties(prefix = "order.chain") public class orderchainconfig { private liststeps; // 将处理器的映射存储在一个集合中 private final map handlermap = new hashmap<>(); public orderchainconfig(list handlers) { // 初始化处理器映射 handlermap.put("ordervalidationhandler", handlers.stream().filter(h -> h instanceof ordervalidationhandler).findfirst().orelse(null)); handlermap.put("verifycouponhandler", handlers.stream().filter(h -> h instanceof verifycouponhandler).findfirst().orelse(null)); handlermap.put("shippingfeehandler", handlers.stream().filter(h -> h instanceof shippingfeehandler).findfirst().orelse(null)); handlermap.put("totalamounthandler", handlers.stream().filter(h -> h instanceof totalamounthandler).findfirst().orelse(null)); handlermap.put("processpaymenthandler", handlers.stream().filter(h -> h instanceof processpaymenthandler).findfirst().orelse(null)); } @bean(name = "orderchain") public orderhandler orderchain() { if (steps == null || steps.isempty()) { throw new illegalargumentexception("处理链步骤不能为空"); } // 动态创建处理链 orderhandler firsthandler = null; orderhandler lasthandler = null; for (string step : steps) { orderhandler handler = handlermap.get(step); if (handler == null) { throw new illegalargumentexception("未找到处理器: " step); } if (firsthandler == null) { firsthandler = handler; } if (lasthandler != null) { lasthandler.setnexthandler(handler); } lasthandler = handler; } if (lasthandler != null) { lasthandler.setnexthandler(null); // 最后一个处理器的 nexthandler 设置为 null } return firsthandler; } public void setsteps(list steps) { this.steps = steps; } }
说明
- 处理器映射:使用
map
来存储处理器实例,通过handlers
列表动态注入。这允许我们在配置中使用字符串名称引用处理器实例。 - 动态创建处理链:在
orderchain
方法中,根据steps
配置的顺序动态创建处理链。每个处理器根据配置连接到下一个处理器。 - 配置检查:确保
steps
配置有效,不为空,并且在处理链创建时校验处理器是否存在。 - 处理器实例:在
orderchainconfig
的构造函数中初始化处理器映射。确保ordervalidationhandler
、verifycouponhandler
、shippingfeehandler
、totalamounthandler
和processpaymenthandler
被正确注入并配置。
控制器接口优化
在优化后的控制器中,前端调用时返回 json 数据,jquery 解析响应后通过 bootstrap 弹出提示。
package com.icoderoad.orderchain.controller; import java.math.bigdecimal; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import org.springframework.beans.factory.annotation.autowired; import org.springframework.beans.factory.annotation.qualifier; import org.springframework.web.bind.annotation.postmapping; import org.springframework.web.bind.annotation.restcontroller; import com.icoderoad.orderchain.entity.orderrequest; import com.icoderoad.orderchain.entity.orderrequest.product; import com.icoderoad.orderchain.handler.orderhandler; @restcontroller public class ordercontroller { private final orderhandler orderhandler; @autowired public ordercontroller(@qualifier("orderchain") orderhandler orderhandler) { this.orderhandler = orderhandler; } @postmapping("/processorder") public mapprocessorder() { map response = new hashmap<>(); try { orderrequest request = new orderrequest(); // 创建商品对象 product product = new product("10001", "手机", 2, new bigdecimal("20000.00")); // 创建商品列表并添加商品 list productlist = new arraylist<>(); productlist.add(product); request.setshippingfee(new bigdecimal("200.00")); // 将商品列表设置到 orderrequest 中 request.setproductlist(productlist); orderhandler.handle(request); response.put("status", "success"); response.put("message", "订单处理成功!"); } catch (exception e) { response.put("status", "error"); response.put("message", "订单处理失败:" e.getmessage()); } return response; } }
前端界面及 jquery 调用 json 接口
在前端,我们使用 jquery 发起 ajax 请求,并通过 bootstrap 提示处理结果。
在 src/main/resources/templates
目录下创建 index.html
文件:
订单处理 电商订单处理
总结
通过职责链模式,我们可以将复杂的订单处理流程解耦成多个独立的步骤,提升了代码的可维护性和扩展性。每个处理环节可以灵活配置和扩展,便于后续的功能迭代。同时,结合 spring boot 和前后端交互技术,进一步增强了系统的可用性与用户体验。
今天就讲到这里,如果有问题需要咨询,大家可以直接留言,我们会尽力为你解答。