文章目录

1.责任链模式的应用

  • Apache Tomcat 对 Encoding 编码处理的处理
  • SpringBoot ⾥⾯的拦截器、过滤器链
  • netty 中的处理链
  • 支付风控的机制
  • ⽇志处理级别

2.责任链模式的代码实践

2.1 方式一

public class OrderContext {

/**
* 请求唯一序列ID
*/
private String seqId;

/**
* 用户ID
*/
private String userId;

/**
* 产品skuId
*/
private Long skuId;

/**
* 下单数量
*/
private Integer amount;

/**
* 用户收货地址ID
*/
private String userAddressId;

//..set、get
}

数据处理接口OrderHandleIntercept

public interface OrderHandleIntercept {

/**
* 指定执行顺序
* @return
*/
int sort();

/**
* 对参数进行处理
* @param context
* @return
*/
OrderAddContext handle(OrderAddContext context);
}

分别创建三个不同的接口实现类, 并指定顺序

  • RepeatOrderHandleInterceptService:用于重复下单的逻辑验证
  • ValidOrderHandleInterceptService:用于验证请求参数是否合法
  • BankOrderHandleInterceptService:用于检查客户账户余额是否充足
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {

@Override
public int sort() {
//用于重复下单的逻辑验证,在执行顺序为1
return 1;
}

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("通过seqId,检查客户是否重复下单");
return context;
}
}
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {


@Override
public int sort() {
//用于验证请求参数是否合法,执行顺序为2
return 2;
}

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
return context;
}
}
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {


@Override
public int sort() {
//用于检查客户账户余额是否充足,在执行顺序为3
return 3;
}

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
return context;
}
}

创建一个订单数据验证管理器OrderHandleChainService, 管理实现类

@Component
public class OrderHandleChainService implements ApplicationContextAware {

private List<OrderHandleIntercept> handleList = new ArrayList<>();


@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取指定的接口实现类,并按照sort进行排序,放入List中
Map<String, OrderHandleIntercept> serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
handleList = serviceMap.values().stream()
.sorted(Comparator.comparing(OrderHandleIntercept::sort))
.collect(Collectors.toList());
}

/**
* 执行处理
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
for (OrderHandleIntercept handleIntercept : handleList) {
context =handleIntercept.handle(context);
}
return context;
}
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

@Autowired
private OrderHandleChainService orderHandleChainService;

@Test
public void test(){
orderHandleChainService.execute(new OrderAddContext());
}
}
通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

也可以通过如下方式进行手动add排序。

@Component
public class OrderHandleChainService {

private List<OrderHandleIntercept> handleList = new ArrayList<>();

@Autowired
private ValidOrderHandleInterceptService validOrderHandleInterceptService;

@Autowired
private RepeatOrderHandleInterceptService repeatOrderHandleInterceptService;

@Autowired
private BankOrderHandleInterceptService bankOrderHandleInterceptService;

@PostConstruct
public void init(){
//依次手动add对象
handleList.add(repeatOrderHandleInterceptService);
handleList.add(validOrderHandleInterceptService);
handleList.add(bankOrderHandleInterceptService);
}

/**
* 执行处理
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
for (OrderHandleIntercept handleIntercept : handleList) {
context =handleIntercept.handle(context);
}
return context;
}
}

2.2 方式二

通过注解@Order来指定排序

/**
* 指定注入顺序为1
*
*/
@Order(1)
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {


//...省略
}
/**
* 指定注入顺序为2
*
*/
@Order(2)
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {


//...省略
}
/**
* 指定注入顺序为3
*
*/
@Order(3)
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {


//...省略
}

2.3 方式三

通过定义抽象类来实现责任链设计模式

AbstractOrderHandle.java

public abstract class AbstractOrderHandle {

/**
* 责任链,下一个链接节点
*/
private AbstractOrderHandle next;

/**
* 执行入口
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
context = handle(context);
// 判断是否还有下个责任链节点,没有的话,说明已经是最后一个节点
if(getNext() != null){
getNext().execute(context);
}
return context;
}

/**
* 对参数进行处理
* @param context
* @return
*/
public abstract OrderAddContext handle(OrderAddContext context);


public AbstractOrderHandle getNext() {
return next;
}

public void setNext(AbstractOrderHandle next) {
this.next = next;
}
}

创建三个处理类,并排好序号

@Order(1)
@Component
public class RepeatOrderHandle extends AbstractOrderHandle {

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("通过seqId,检查客户是否重复下单");
return context;
}
}
@Order(2)
@Component
public class ValidOrderHandle extends AbstractOrderHandle {

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
return context;
}
}
@Order(3)
@Component
public class BankOrderHandle extends AbstractOrderHandle {

@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
return context;
}
}

责任链管理器: OrderHandlerManager

@Component
public class OrderHandleManager {

@Autowired
private List<AbstractOrderHandle> orderHandleList;


@PostConstruct
public void init(){
//如果List没有按照@Order注解方式排序,可以通过如下方式手动排序
Collections.sort(orderHandleList, AnnotationAwareOrderComparator.INSTANCE);
int size = orderHandleList.size();
for (int i = 0; i < size; i++) {
if(i == size -1){
orderHandleList.get(i).setNext(null);
} else {
orderHandleList.get(i).setNext(orderHandleList.get(i + 1));
}
}

}

/**
* 执行处理
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
context = orderHandleList.get(0).execute(context);
return context;
}
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

@Autowired
private OrderHandleManager orderHandleManager;

@Test
public void test(){
orderHandleManager.execute(new OrderAddContext());
}

}
通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额