springboot中使用责任链模式 - 设计模式(五)

参考链接: Java设计模式13:责任链模式.

什么是责任链模式

责任链设计模式(Chain of Responsibility Pattern)客户端发出⼀个请求,链上的对象都有机会来处理这⼀请求,⽽客户端不需要知道谁是具体的处理对象让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成⼀条调⽤链,并沿着这条链传递该请求,直到有⼀个对象处理它才终⽌

有两个核⼼⾏为:

  • 处理请求,
  • 将请求传递到下⼀节点

应⽤场景

  • Apache Tomcat 对 Encoding 编码处理的处理,
  • SpringBoot⾥⾯的拦截器、过滤器链
  • netty 中的处理链
  • 支付风控的机制
  • ⽇志处理级别
  • 在请求处理者不明确的情况下向多个对象中的⼀个提交 请求 如果有多个对象可以处理同⼀个请求,但是具体由哪个
  • 对象处理是由运⾏时刻动态决定的,这种对象就可以使 ⽤职责链模式

优缺点

优点

  • 客户只需要将请求发送到职责链上即可,⽆须关⼼请求
    的处理细节和请求的传递,所以职责链将请求的发送者
    和请求的处理者 降低了耦合度
  • 通过改变链内的调动它们的次序,允许动态地新增或者
    删除处理类,⽐较很⽅便维护
  • 增强了系统的可扩展性,可以根据需要增加新的请求处
    理类,满⾜开闭原则
    -每个类只需要处理⾃⼰该处理的⼯作,明确各类的责任
    范围,满⾜单⼀职责原则

缺点

  • 处理都分散到了单独的职责对象中,每个对象功能单
    ⼀,要把整个流程处理完,需要很多的职责对象,会产
    ⽣⼤量的细粒度职责对象
  • 不能保证请求⼀定被接收,可以将最终操作放在最后执行
  • 如果链路⽐较⻓,系统性能将受到⼀定影响,⽽且在进
    ⾏代码调试时不太⽅便

支付风控需求

实现:
金额小于200直接支付
200-400 请输入支付密码
400-1000 请发生短信验证码
1000以上 扫脸支付

代码实现

import java.math.BigDecimal;

/**
 * @author zhou
 * 参数对象
 */
public class MyParam {

    /**
     * 金额
     */
    private BigDecimal amount;


    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}
/**
 * @author zhou
 */
public interface PrepareFilter {

    Integer getShort();

    void doFilter(MyParam param, MyFilterChain filterChain,Integer index);

}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 责任链处理器
 */
@Service("MyFilterChain")
public class MyFilterChain implements PrepareFilter, ApplicationContextAware {

    private static List<PrepareFilter> prepareFilterList;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, PrepareFilter> serviceMap = applicationContext.getBeansOfType(PrepareFilter.class);
        prepareFilterList = new ArrayList<>(serviceMap.values());
        prepareFilterList = prepareFilterList.stream()
                .sorted(Comparator.comparing(PrepareFilter::getShort))
                .collect(Collectors.toList());
    }


    @Override
    public Integer getShort() {
        return 0;
    }

    @Override
    public void doFilter(MyParam param, MyFilterChain filterChain, Integer index) {
        index = index + 1;
        if (index < prepareFilterList.size()) {
            prepareFilterList.get(index).doFilter(param, filterChain, index);
        } else {
            System.out.println("直接支付");
        }
    }

}

import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service("Filter1")
public class Filter1 implements PrepareFilter {

    /**
     * 这些都可以进行数据库配置
     */
    public static final BigDecimal start = new BigDecimal("200");
    /**
     * 这些都可以进行数据库配置
     */
    public static final BigDecimal end = new BigDecimal("400");
    /**
     * 这些都可以进行数据库配置
     */
    @Override
    public Integer getShort() {
        return 1;
    }

    @Override
    public void doFilter(MyParam param, MyFilterChain filterChain, Integer index) {
        System.out.println("Filter1");
        if (param.getAmount().compareTo(start) > -1 && param.getAmount().compareTo(end) < 0) {
            System.out.println("请输入支付密码");
            return;
        }
        filterChain.doFilter(param, filterChain, index);
    }

}
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service("Filter2")
public class Filter2 implements PrepareFilter {

    public static final BigDecimal start = new BigDecimal("400");

    public static final BigDecimal end = new BigDecimal("1000");


    @Override
    public Integer getShort() {
        return 2;
    }

    @Override
    public void doFilter(MyParam param, MyFilterChain filterChain, Integer index) {
        System.out.println("Filter2");
        if (param.getAmount().compareTo(start) > -1 && param.getAmount().compareTo(end) < 0) {
            System.out.println("请发生短信验证码");
            return;
        }
        filterChain.doFilter(param, filterChain, index);
    }

}
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service("Filter3")
public class Filter3 implements PrepareFilter {

    public static final BigDecimal start = new BigDecimal("1000");

    @Override
    public Integer getShort() {
        return 3;
    }

    @Override
    public void doFilter(MyParam param, MyFilterChain filterChain, Integer index) {
        System.out.println("Filter3");
        if (param.getAmount().compareTo(start) > -1) {
            System.out.println("扫脸");
            return;
        }
        filterChain.doFilter(param, filterChain, index);
    }

}
import com.zm.demo01.test.MyFilterChain;
import com.zm.demo01.test.MyParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhou
 */
@Slf4j
@RestController
public class HelloController {

    @Autowired
    MyFilterChain myFilterChain;

    @GetMapping("hello")
    public String hello(MyParam param) {
        myFilterChain.doFilter(param,myFilterChain,0);
        log.info("1111111111111");
        return "hello word update!";
    }

}
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot,可以通过使用 `camunda-bpm-spring-boot-starter` 依赖来集成Camunda流程引擎。以下是配置Camunda的步骤: 1. 添加依赖 在 `pom.xml` 添加以下依赖: ```xml <dependency> <groupId>org.camunda.bpm.springboot</groupId> <artifactId>camunda-bpm-spring-boot-starter</artifactId> <version>7.15.0</version> </dependency> ``` 2. 配置数据库 在 `application.properties` 配置数据库连接信息: ```properties spring.datasource.url=jdbc:h2:mem:camunda spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect ``` 3. 配置Camunda 在 `application.properties` 添加以下Camunda配置: ```properties # Process engine configuration camunda.bpm: # Database configuration database: schema-update: true type: h2 table-prefix: camunda. # Metrics configuration metrics: enabled: false # Job executor configuration job-execution: enabled: true # REST API configuration api: enabled: true path: /rest # Admin User configuration admin-user: id: demo password: demo firstName: Demo lastName: User ``` 这些配置包括数据库配置、指定Camunda的表前缀、禁用指标、启用作业执行器、启用REST API和指定管理员用户身份验证信息。 4. 启动流程引擎 在Spring Boot应用程序,可以通过添加 `@EnableProcessApplication` 注释来启动流程引擎。示例代码如下: ```java @SpringBootApplication @EnableProcessApplication public class CamundaApplication { public static void main(String... args) { SpringApplication.run(CamundaApplication.class, args); } } ``` 这将以嵌入式模式启动Camunda流程引擎。现在,你可以使用Camunda的 REST API 或 Java API 来与引擎进行交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值