管道配置:
package org.example.design.pipeline;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
/**
* Description: 供应商调用管道
*
*/
@Slf4j
public class Pipeline {
private List> steps = new ArrayList<>();
/**
* 增加步骤
*
* @param step 步骤
* @return this
*/
public Pipeline next(Step step) {
steps.add(step);
return this;
}
/**
* 执行步骤
*
* @param context 执行内容
*/
public void execute(ProcessContext context) {
log.info("{}--管道执行开始--订单号:{}", context.getSupplierProcess(), context.getOrderNo());
for (Step 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 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 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 implements Step {
@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 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 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 pipeline;
@PostConstruct
public void init() {
pipeline = new Pipeline().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 {
@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 {
@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;
/**
*
* 商品订单表
*
* @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("枚举不存在");
}
}