spring boot 3.3 实现职责链模式轻松应对电商订单流程分析-kb88凯时官网登录

时间:2024-10-18
阅读:
免费资源网,https://freexyz.cn/

在电商系统中,订单的处理流程通常涉及多个步骤,每个步骤都可能有不同的业务逻辑。例如,当用户提交订单时,系统需要校验库存、验证优惠券、计算运费、处理支付、分配物流等。这些操作看似独立,但实际上具有一定的顺序依赖性。为了更好地管理这些业务逻辑,我们需要将这些流程模块化,并按需执行。

通常的做法是将所有逻辑写在一起,但这会导致代码冗长且难以维护。如果未来需要对某个步骤进行修改或者添加新的处理环节,代码变动的范围将会很大。为了避免这种情况,职责链模式提供了一个灵活、可扩展的kb88凯时官网登录的解决方案。

什么是职责链模式?

职责链模式(chain of responsibility)是一种行为设计模式,它允许多个对象都有机会处理请求,直到其中一个对象处理成功为止。职责链模式使多个处理对象通过链式关系链接在一起,每个处理对象知道它的下一个处理对象,并且在完成自身处理后,将请求传递给下一个对象。

职责链模式的优点:

  • 解耦请求发送者和接收者:请求发送者不需要知道是谁在处理请求,避免了系统中各个模块的强耦合。
  • 灵活扩展:通过调整链条中的处理器顺序,或者增加新的处理器,可以灵活地扩展业务逻辑。
  • 动态组合:职责链的处理器可以动态组合,可以根据不同的需求创建不同的链条。

适用场景:

  • 需要对请求进行一系列处理,并且请求处理者不明确或不固定时。
  • 多个对象可以处理同一个请求,具体由运行时动态决定哪个对象来处理。

职责链模式在电商订单流程中的应用

在电商系统中,职责链模式可以将订单处理过程中的各个环节(如库存校验、优惠券核验、支付处理等)封装为独立的处理器,并通过职责链将这些处理器串联起来。每个处理器独立处理其对应的任务,处理完成后将请求传递给下一个处理器,直到所有处理环节完成或者中断。

运行效果:

spring boot 3.3 实现职责链模式轻松应对电商订单流程分析

本文将深入探讨如何通过职责链模式来处理电商订单流程,并结合 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 list productlist;
    // 用户使用的优惠券
    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 list steps;
    // 将处理器的映射存储在一个集合中
    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 的构造函数中初始化处理器映射。确保 ordervalidationhandlerverifycouponhandlershippingfeehandlertotalamounthandler 和 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 map processorder() {
        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 和前后端交互技术,进一步增强了系统的可用性与用户体验。

今天就讲到这里,如果有问题需要咨询,大家可以直接留言,我们会尽力为你解答。

免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图