设计模式——管道模式(二)

这个Java代码示例展示了一个供应商调用管道系统,包括步骤管理、上下文处理、异常处理和中断机制。Pipeline类用于构建和执行步骤序列,PipelineContextHolder用于存储和检查中断标志。此外,还包括具体的步骤实现,如查询订单和提交订单步骤,以及一个抽象步骤基类。整个系统通过SupplierRegistry进行注册和管理,确保流程的正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

管道配置:

package org.example.design.pipeline;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: 供应商调用管道
 *
 */
@Slf4j
public class Pipeline<S> {

    private List<Step<S>> steps = new ArrayList<>();

    /**
     * 增加步骤
     *
     * @param step 步骤
     * @return this
     */
    public Pipeline<S> next(Step<S> step) {
        steps.add(step);
        return this;
    }

    /**
     * 执行步骤
     *
     * @param context 执行内容
     */
    public void execute(ProcessContext context) {
        log.info("{}--管道执行开始--订单号:{}", context.getSupplierProcess(), context.getOrderNo());

        for (Step<S> step : steps) {
            step.next(context);

            if (PipelineContextHolder.getAndRemoveBreakFlag()) {
                break;
            }
        }
        log.info("管道执行结束");
    }
}
package org.example.design.pipeline;

import org.springframework.core.NamedThreadLocal;

/**
 * 管道上下文保持器
 *
 */
public class PipelineContextHolder {

    // 中断标识
    private static ThreadLocal<Boolean> breakFlag = new NamedThreadLocal<>("管道中断标识");

    public static void putBreakFlag(Boolean flagValue) {
        breakFlag.set(flagValue);
    }

    static boolean getAndRemoveBreakFlag() {
        try {
            Boolean result = breakFlag.get();
            if (result != null) {
                return result;
            }
            return false;
        } finally {
            breakFlag.remove();
        }
    }

}
package org.example.design.pipeline;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.design.pipeline.zhichong.OrderInfo;
import org.example.design.pipeline.zhichong.SupplierProcessEnum;

/**
 * Description:管道上下文
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProcessContext {

    /**
     * 订单
     */
    private OrderInfo orderInfo;

    /**
     * 流程标识
     */
    private SupplierProcessEnum supplierProcess;

    /**
     * 回调参数
     */
    private Object callback;

    public String getOrderNo() {
        return orderInfo.getOrderNo();
    }
}
package org.example.design.pipeline;

/**
 * Description: 步骤
 *
 */
public interface Step<S> {

    S getCur();

    /**
     * 转换到下一个状态
     *
     * @param context 下一步
     */
    void next(ProcessContext context);
}


package org.example.design.pipeline;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.zhichong.OrderInfo;
import org.example.exception.ServiceException;
import org.springframework.beans.factory.annotation.Value;

/**
 * Description: 查询订单步骤
 */
@Slf4j
public abstract class YCAbstractStep<S> implements Step<S> {

    @Value("${yuecheng.exe.num:3}")
    private int maxExeNum;

    @Override
    public void next(ProcessContext context) {
        log.info("步骤 {} 开始执行,context:{}", getClassName(), context.getOrderNo());
        OrderInfo orderInfo = context.getOrderInfo();
        try {
            //判断是否执行该步骤
            if (!verificationStatus(orderInfo)) {
                return;
            }
            //调用次数过多直接挂起
            if (null != orderInfo.getSupplierExeNum() && orderInfo.getSupplierExeNum() >= maxExeNum) {
                autoSuspend(orderInfo);
                return;
            }
            //核心处理
            handle(context, orderInfo);
        } catch (ServiceException e) {
            addExeNum(orderInfo);
            throw e;
        } catch (Exception e) {
            log.error("跃程调用供应商接口出现异常name:{},order:{}", getClassName(), context.getOrderNo(), e);
            throw e;
        }
        log.info("步骤 {} 执行执行完成", getClassName());
    }

    public abstract boolean verificationStatus(OrderInfo orderInfo);

    public abstract void autoSuspend(OrderInfo orderInfo);

    public abstract void handle(ProcessContext context, OrderInfo orderInfo);

    public abstract String getClassName();

    public abstract void addExeNum(OrderInfo orderInfo);
}

package org.example.design.pipeline;

import org.example.design.pipeline.zhichong.SupplierProcessEnum;

import java.util.HashMap;
import java.util.Map;

/**
 * Description: 供应商注册器
 */
public class SupplierRegistry {

    private static SupplierRegistry instance = new SupplierRegistry();

    private Map<String, Object> registry = new HashMap<>();

    private SupplierRegistry() {
    }

    public static SupplierRegistry getInstance() {
        return instance;
    }

    public void register(SupplierProcessEnum supplierProcess, Object process) {
        registry.put(getCapitalCode(supplierProcess), process);
    }

    @SuppressWarnings("unchecked")
    public <T> T getCallSupplierProcess(SupplierProcessEnum supplierProcess) {
        return (T) registry.get(getCapitalCode(supplierProcess));
    }


    private String getCapitalCode(SupplierProcessEnum supplierProcess) {
        return String.format("%s_%s", supplierProcess.getSupplierNo(), supplierProcess.getProcessName());
    }


}


package org.example.design.pipeline;

import org.example.design.pipeline.process.DirectRechargeProcess;
import org.example.design.pipeline.zhichong.SupplierProcessEnum;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 供应商注册
 */
@Component
public class YCStartup {

    @Resource
    private DirectRechargeProcess directRechargeProcess;
    //@Resource
    //private ReceiverCardProcess receiverCardProcess;
    //@Resource
    //private GameRechargeProcess gameRechargeProcess;

    @PostConstruct
    public void init() {
        SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_DR, directRechargeProcess);
        //SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_RC, receiverCardProcess);
        //SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_GR, gameRechargeProcess);
    }
}

处理器:

package org.example.design.pipeline.process;

import org.example.design.pipeline.ProcessContext;

/**
 * Description:调用供应商接口
 *
 */
public interface CallSupplierProcess {

    /**
     * 发货流程
     *
     * @param context 流程信息
     */
    void deliverGoods(ProcessContext context);
}




package org.example.design.pipeline.process;

import org.example.design.pipeline.Pipeline;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.zhichong.DRQueryOrderStep;
import org.example.design.pipeline.zhichong.DRSubmitOrderStep;
import org.example.design.pipeline.zhichong.OrderStatusEnum;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * Description:直冲
 *
 */
@Component
public class DirectRechargeProcess implements CallSupplierProcess {

    @Resource
    private DRSubmitOrderStep drSubmitOrderStep;
    @Resource
    private DRQueryOrderStep drQueryOrderStep;

    private Pipeline<OrderStatusEnum> pipeline;

    @PostConstruct
    public void init() {
        pipeline = new Pipeline<OrderStatusEnum>().next(drSubmitOrderStep).next(drQueryOrderStep);
    }

    @Override
    public void deliverGoods(ProcessContext context) {
        pipeline.execute(context);
    }
}

具体步骤:

package org.example.design.pipeline.zhichong;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.PipelineContextHolder;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.YCAbstractStep;
import org.springframework.stereotype.Component;

/**
 * Description: 查询订单步骤
 */
@Slf4j
@Component
public class DRQueryOrderStep extends YCAbstractStep<OrderStatusEnum> {


    @Override
    public OrderStatusEnum getCur() {
        return OrderStatusEnum.ING_SEND;
    }

    @Override
    public boolean verificationStatus(OrderInfo orderInfo) {
        return true;
    }

    @Override
    public void autoSuspend(OrderInfo orderInfo) {
        // 具体业务逻辑
        //中断管道
        PipelineContextHolder.putBreakFlag(true);
    }

    @Override
    public void handle(ProcessContext context, OrderInfo orderInfo) {
    }

    @Override
    public String getClassName() {
        return this.getClass().getName();
    }

    @Override
    public void addExeNum(OrderInfo orderInfo) {
    }
}
package org.example.design.pipeline.zhichong;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.PipelineContextHolder;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.YCAbstractStep;
import org.springframework.stereotype.Component;

/**
 * Description: 直冲类提交订单步骤
 */
@Slf4j
@Component
public class DRSubmitOrderStep extends YCAbstractStep<OrderStatusEnum> {


    @Override
    public OrderStatusEnum getCur() {
        return OrderStatusEnum.WAIT_SEND;
    }

    @Override
    public boolean verificationStatus(OrderInfo orderInfo) {
        return true;
    }

    @Override
    public void autoSuspend(OrderInfo orderInfo) {
        // 具体业务逻辑
        //中断管道
        PipelineContextHolder.putBreakFlag(true);
    }

    @Override
    public void handle(ProcessContext context, OrderInfo orderInfo) {

    }

    @Override
    public String getClassName() {
        return this.getClass().getName();
    }

    @Override
    public void addExeNum(OrderInfo orderInfo) {
        ;
    }
}

业务相关:

package org.example.design.pipeline.zhichong;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;

import java.math.BigDecimal;
import java.util.Date;

/**
 * <p>
 * 商品订单表
 * </p>
 * @author mybatis-plus-generator
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@TableName("demo_order_info")
@ApiModel(value = "OrderInfo对象", description = "商品订单表")
public class OrderInfo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "订单编号")
    @TableId("order_no")
    private String orderNo;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private Integer orderStatus;

    @ApiModelProperty(value = "每个流程子状态")
    @TableField("step_order_status")
    private Integer stepOrderStatus;

    @ApiModelProperty(value = "客户号")
    @TableField("cust_no")
    private String custNo;

    @ApiModelProperty(value = "商品ID")
    @TableField("goods_id")
    private String goodsId;

    @ApiModelProperty(value = "商品信息ID")
    @TableField("goods_info_id")
    private String goodsInfoId;

    @ApiModelProperty(value = "商品规格ID")
    @TableField("goods_spec_id")
    private String goodsSpecId;

    @ApiModelProperty(value = "规格参数,属性值ID逗号连接串")
    @TableField("spec_param")
    private String specParam;

    @ApiModelProperty(value = "商品名称")
    @TableField("goods_name")
    private String goodsName;

    @ApiModelProperty(value = "商品描述")
    @TableField("goods_desc")
    private String goodsDesc;

    @ApiModelProperty(value = "商品图片")
    @TableField("goods_pic")
    private String goodsPic;

    @ApiModelProperty(value = "商品类型")
    @TableField("goods_type")
    private String goodsType;

    @ApiModelProperty(value = "动态参数")
    @TableField("account_info")
    private String accountInfo;

    @ApiModelProperty(value = "动态返回结果")
    @TableField("return_info")
    private String returnInfo;

    @ApiModelProperty(value = "售价")
    @TableField("sale_price")
    private BigDecimal salePrice;

    @ApiModelProperty(value = "商品采购价")
    @TableField("goods_purchase_price")
    private BigDecimal goodsPurchasePrice;

    @ApiModelProperty(value = "购买数量")
    @TableField("purchase_num")
    private Integer purchaseNum;

    @ApiModelProperty(value = "商户号")
    @TableField("merchant_no")
    private String merchantNo;

    @ApiModelProperty(value = "外部订单号")
    @TableField("out_order_no")
    private String outOrderNo;

    @ApiModelProperty(value = "供应商商品id")
    @TableField("supplier_goods_id")
    private String supplierGoodsId;

    @ApiModelProperty(value = "调用供应商接口次数")
    @TableField("supplier_exe_num")
    private Integer supplierExeNum;

    @ApiModelProperty(value = "提交订单时间")
    @TableField("submit_datetime")
    private Date submitDatetime;

    @ApiModelProperty(value = "关闭订单时间")
    @TableField("close_datetime")
    private Date closeDatetime;

    @ApiModelProperty(value = "退款原因")
    @TableField("refund_reason")
    private String refundReason;

    @ApiModelProperty(value = "收货地址")
    @TableField("receive_address")
    private String receiveAddress;

    @ApiModelProperty(value = "收货人")
    @TableField("receive_name")
    private String receiveName;

    @ApiModelProperty(value = "手机号码")
    @TableField("receive_mobile")
    private String receiveMobile;

    @ApiModelProperty(value = "发货时间")
    @TableField("deliver_datetime")
    private Date deliverDatetime;

    @ApiModelProperty(value = "发货方式")
    @TableField("deliver_type")
    private String deliverType;

    @ApiModelProperty(value = "支付流水id")
    @TableField("pay_log_id")
    private String payLogId;


    @ApiModelProperty(value = "修改时间")
    @TableField("update_datetime")
    private Date updateDatetime;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_datetime")
    private Date createDatetime;


    public static final String ORDER_NO = "order_no";

    public static final String ORDER_STATUS = "order_status";

    public static final String STEP_ORDER_STATUS = "step_order_status";

    public static final String CUST_NO = "cust_no";

    public static final String GOODS_ID = "goods_id";

    public static final String GOODS_INFO_ID = "goods_info_id";

    public static final String GOODS_SPEC_ID = "goods_spec_id";

    public static final String SPEC_PARAM = "spec_param";

    public static final String GOODS_NAME = "goods_name";

    public static final String GOODS_DESC = "goods_desc";

    public static final String GOODS_PIC = "goods_pic";

    public static final String GOODS_TYPE = "goods_type";

    public static final String ACCOUNT_INFO = "account_info";

    public static final String RETURN_INFO = "return_info";

    public static final String SALE_PRICE = "sale_price";

    public static final String GOODS_PURCHASE_PRICE = "goods_purchase_price";

    public static final String PURCHASE_NUM = "purchase_num";

    public static final String MERCHANT_NO = "merchant_no";

    public static final String OUT_ORDER_NO = "out_order_no";

    public static final String SUPPLIER_GOODS_ID = "supplier_goods_id";

    public static final String SUPPLIER_EXE_NUM = "supplier_exe_num";

    public static final String SUBMIT_DATETIME = "submit_datetime";

    public static final String CLOSE_DATETIME = "close_datetime";

    public static final String REFUND_REASON = "refund_reason";

    public static final String RECEIVE_ADDRESS = "receive_address";

    public static final String RECEIVE_NAME = "receive_name";

    public static final String RECEIVE_MOBILE = "receive_mobile";

    public static final String DELIVER_DATETIME = "deliver_datetime";

    public static final String DELIVER_TYPE = "deliver_type";

    public static final String UPDATE_DATETIME = "update_datetime";

    public static final String CREATE_DATETIME = "create_datetime";

}


@AllArgsConstructor
@Getter
public enum OrderStatusEnum {
    WAIT_PAY(10, "待付款"),
    WAIT_SEND(20, "待发货"),
    ING_SEND(21, "发货中"),
    FINISH(30, "已完成"),
    CLOSED(31, "已关闭"),
    WAIT_REFUND(40, "待退款"),
    REFUND_PROCESS(41, "退款中"),
    REFUND_SUCCESS(42, "退款成功"),
    AUTO_SUSPEND(90, "自动挂起"),
    ;

    private Integer code;
    private String msg;

    public static OrderStatusEnum getEnum(Integer code) {
        for (OrderStatusEnum value : OrderStatusEnum.values()) {
            if (value.getCode().equals(code)) {
                return value;
            }
        }
        throw new IllegalArgumentException("枚举值不存在");
    }
}


@AllArgsConstructor
@Getter
public enum SupplierProcessEnum {

    YC_DR("yuecheng", "yc_dr", "DirectRechargeProcess", "跃程", "跃程直充类"),
    YC_RC("yuecheng", "yc_rc", "ReceiverCardProcess", "跃程", "跃程提卡类"),
    YC_GR("yuecheng", "yc_gr", "GameRechargeProcess", "跃程", "跃程游戏充值类"),
    ;

    private String supplierNo;
    private String code;
    private String processName;
    private String supplierName;
    private String msg;

    public static SupplierProcessEnum getEnum(String code) {
        for (SupplierProcessEnum value : SupplierProcessEnum.values()) {
            if (value.getCode().equals(code)) {
                return value;
            }
        }
        throw new IllegalArgumentException("枚举不存在");
    }

    public static SupplierProcessEnum getEnum(String supplierNo, String processName) {
        for (SupplierProcessEnum value : SupplierProcessEnum.values()) {
            if (value.getSupplierNo().equals(supplierNo)
                    && value.getProcessName().equals(processName)) {
                return value;
            }
        }
        throw new IllegalArgumentException("枚举不存在");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值