Apache commons-chain

2018-01-19  本文已影响799人  茶铺里的水

在日常的工作中,我们经常会碰到一些业务流程比较复杂的场景,这些东西糅合到一个方法里就使得代码耦合度特别高,随着业务场景逻辑的越来越多,就会越来越复杂,难以维护。
如提交的订单的动作可能涉及到如下场景:

  1. 各种各样的校验
  2. 各类信息的补充
  3. 订单提交成功/失败后产品信息/库存的改变
  4. 订单提交成功/失败后支付信息/状态的改变
  5. 订单提交成功/失败后的各种推送
  6. 等等

还有一些更复杂的场景是要根据类型区分的,如不同的产品类型后续执行的动作是不一样的,假设某一类产品是不需要推送的,可能第5步就不需要

项目中用过这么一个东西,Apache commons chain,原理是责任链模式。大致实现方式是根据不同的业务场景,建立多个Command,每个Command处理各自的业务逻辑,每个Command执行完毕后,将处理后的处理传给下一个Command,直到所有执行完毕。

接口原理图

代码实现

  1. 建立ChainBase,可以根据不同的应用场景建立多个ChainBase,如下示例我使用了1、2、3三个Command,当然我也可以根据需要只使用1和2
package com.mk.chain;

import com.mk.chain.commands.Commands1;
import com.mk.chain.commands.Commands2;
import com.mk.chain.commands.Commands3;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.impl.ChainBase;

public class CommandChain extends ChainBase{
    public CommandChain() {
        addCommand(new Commands1());
        addCommand(new Commands2());
        addCommand(new Commands3());
    }
}
  1. 建立对应的Command,每个Command都是一个独立的类,需要实现Command接口

Commands1.java

package com.mk.chain.commands;

import com.alibaba.fastjson.JSONObject;
import io.swagger.models.auth.In;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Commands1 implements Command{

    private static final Logger logger = LoggerFactory.getLogger(Commands1.class);


    @Override
    public boolean execute(Context context) throws Exception {
        Object v1 = context.get("k1");
        logger.info("do something by Commands1... params is {}", JSONObject.toJSONString(context));
        if(v1 != null){
            int IntV1 = (Integer) v1;
            context.put("k1", IntV1+1);
        }
        return false;
    }
}

Commands2.java

package com.mk.chain.commands;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Commands2 implements Command{

    private static final Logger logger = LoggerFactory.getLogger(Commands2.class);


    @Override
    public boolean execute(Context context) throws Exception {
        Object v1 = context.get("k1");
        logger.info("do something by Commands2... params is {}", JSONObject.toJSONString(context));
        if(v1 != null){
            int IntV1 = (Integer) v1;
            context.put("k1", IntV1+1);
        }
        return false;
    }
}

Commands3.java

package com.mk.chain.commands;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Commands3 implements Command{

    private static final Logger logger = LoggerFactory.getLogger(Commands3.class);


    @Override
    public boolean execute(Context context) throws Exception {
        Object v1 = context.get("k1");
        logger.info("do something by Commands3... params is {}", JSONObject.toJSONString(context));
        if(v1 != null){
            int IntV1 = (Integer) v1;
            context.put("k1", IntV1+1);
        }
        return false;
    }
}
  1. 测试,建立测试类CommandTest.java
package com.my.test;

import com.mk.chain.CommandChain;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.impl.ContextBase;
import org.junit.Test;

public class CommandTest {

    @Test
    public void test() throws Exception {
        CommandChain commandChain = new CommandChain();
        Context context = new ContextBase();
        context.put("k1",1);
        commandChain.execute(context);
    }
}

执行结果如下

2018-01-19 10:20:54.356 [main] INFO  com.mk.chain.commands.Commands1 - do something by Commands1... params is {"k1":1}
2018-01-19 10:20:54.363 [main] INFO  com.mk.chain.commands.Commands2 - do something by Commands2... params is {"k1":2}
2018-01-19 10:20:54.363 [main] INFO  com.mk.chain.commands.Commands3 - do something by Commands3... params is {"k1":3}
上一篇下一篇

猜你喜欢

热点阅读