【设计模式】基于spring特性的责任链模式
业务场景:
业务场景:开发中,需要对返回进行一系列的策略过滤,直接在一个方法中进行,代码比较长,耦合也是比较深。所以用责任链的模式进行解耦,同时可以动态配置责任链,实现动态拔插。
设计:
定义一个过滤链接口:
public interface IFilterChain<ReqT,repD> {
void doFilter(ReqT req, repD rep);
}
实现接口:这就是一个过滤链的对象
public class LinkedFilterChain implements IFilterChain<RequestContext, RespondContext> ,Cloneable {
List<IWorkFilter<RequestContext,RespondContext>> filterChain;
@Override
public void doFilter(RequestContext req, RespondContext rep) {
// 循环执行责任链
for (IWorkFilter<RequestContext, RespondContext> filterChain : filterChain) {
filterChain.doFilter(req,rep);
}
}
public List<IWorkFilter<RequestContext, RespondContext>> getFilterChains() {
return filterChain;
}
public void setFilterChains(List<IWorkFilter<RequestContext, RespondContext>> filterChains) {
this.filterChain = filterChains;
}
@Override
protected LinkedFilterChain clone() throws CloneNotSupportedException {
return (LinkedFilterChain) super.clone();
}
}
通过doFilter
方法执行过滤,这只是一个简单的过滤链,你也可以按照业务需求实现更多的功能,比如:快速失败,等等。。
如何使用
1:定义一个过滤接口:
public interface IWorkFilter<ReqT,RepD> extends Cloneable {
void doFilter(ReqT req, RepD rep);
}
实现类为过滤节点,这里demo就建立两个过滤节点,通过@Order
实现注入链的顺序
@Component
@Order(1)
@Slf4j
public class FirstLevelWorkFilter implements IWorkFilter<RequestContext,RespondContext> {
@Override
public void doFilter(RequestContext req, RespondContext rep) {
log.info("一级处理器执行。。。");
}
}
@Component
@Order(2) // 可以通过order对注入责任链的顺序控制
@Slf4j
public class SecondLevelWorkFilter implements IWorkFilter<RequestContext,RespondContext> {
@Override
public void doFilter(RequestContext req, RespondContext rep) {
log.info("执行二级过滤器。。。。");
}
}
2:建立一个过滤链工厂
- 可以通过incloudChain 在配置文件中动态注入需要执行的过滤链
- 通过spring的特性注入所有的过滤链,按照过滤链类名和实现类存入map
- 提供获取实例的方法,返回过滤链对象
@Component
@Data
@Slf4j
public class FilterFactory {
private List<IWorkFilter<RequestContext, RespondContext>> filterList;
private Map<String, IWorkFilter<RequestContext, RespondContext>> filterMap = new HashMap<>();
private LinkedFilterChain linkedFilterChain;
//@Value("#{chain}")
List<String> incloudChain = new ArrayList<>(); // 配置执行链
// 可以有两种方法注入 1: @Autowired 2:构造器注入
@Autowired(required = false)
private List<IWorkFilter<RequestContext, RespondContext>> filters;
public FilterFactory(List<IWorkFilter<RequestContext, RespondContext>> filters) {
filterList = filters;
}
@PostConstruct
public void init() {
// 原始链集合 ,可以基于动态配置,对执行的链接灵活拔插
for (IWorkFilter filter : filterList) {
filterMap.put(filter.getClass().getSimpleName(), filter);
}
// 获取执行链
updateChain();
}
private void updateChain() {
LinkedFilterChain realChain = new LinkedFilterChain();
List<IWorkFilter<RequestContext, RespondContext>> filters = new ArrayList<>();
realChain.setFilterChains(filters);
this.linkedFilterChain = realChain;
if (CollectionUtils.isEmpty(incloudChain)) {
filters.addAll(filterList);
}
for (String filterName : incloudChain) {
IWorkFilter realFilter = filterMap.get(filterName);
filters.add(realFilter);
}
}
public LinkedFilterChain getInstance() {
LinkedFilterChain filterChain = null;
try{
filterChain = linkedFilterChain.clone();
}catch (Exception e){
log.error("get linkedFilterChain instance got error" ,e);
}
return filterChain;
}
}
测试
测试类
@Autowired
FilterFactory filterFactory;
@Test
void testFilteChain(){
LinkedFilterChain instance = filterFactory.getInstance();
RequestContext requestContext = new RequestContext();
RespondContext respondContext = new RespondContext();
instance.doFilter(requestContext,respondContext);
}
2021-03-14 16:43:06.679 INFO 22120 --- [ main] c.l.d.p.d.c.filter.FirstLevelWorkFilter : 一级处理器执行。。。
2021-03-14 16:43:06.680 INFO 22120 --- [ main] c.l.d.p.d.c.f.SecondLevelWorkFilter : 执行二级过滤器。。。。
总结:
责任链模式非常适合逻辑比较多的业务,按照每个业务特点拆分成一个个的节点,可以让代码更优雅。这是一个简单demo,实际在使用的时候,可以按照业务需求优化。
That is all~~