Apache commons-chain
2018-01-19 本文已影响799人
茶铺里的水
在日常的工作中,我们经常会碰到一些业务流程比较复杂的场景,这些东西糅合到一个方法里就使得代码耦合度特别高,随着业务场景逻辑的越来越多,就会越来越复杂,难以维护。
如提交的订单的动作可能涉及到如下场景:
- 各种各样的校验
- 各类信息的补充
- 订单提交成功/失败后产品信息/库存的改变
- 订单提交成功/失败后支付信息/状态的改变
- 订单提交成功/失败后的各种推送
- 等等
还有一些更复杂的场景是要根据类型区分的,如不同的产品类型后续执行的动作是不一样的,假设某一类产品是不需要推送的,可能第5步就不需要
项目中用过这么一个东西,Apache commons chain,原理是责任链模式。大致实现方式是根据不同的业务场景,建立多个Command,每个Command处理各自的业务逻辑,每个Command执行完毕后,将处理后的处理传给下一个Command,直到所有执行完毕。
接口原理图代码实现
- 建立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());
}
}
- 建立对应的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;
}
}
- 测试,建立测试类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}