简介
Lattice 是一个强大的、轻量级的,面向业务定制高可扩展的业务管理框架。通过使用 Lattice 框架,可以对复杂的业务定制进行高效的组织与管理。这个框架的关键设计要点:
业务/平台分离插件化架构: 平台提供插件包注册机制,实现业务方插件包在运行期的注册。业务代码只允许存在于插件包中,与平台代码严格分离。业务包的代码配置库也与平台的代码库分离,通过二方包的方式,提供给容器加载。
统一业务身份: 平台需要能有按“业务身份”进行业务与业务之间逻辑隔离的能力,而不是传统 SPI 架构不区分业务身份,简单过滤的方式。如何设计这个业务身份,也成为业务与业务之间隔离架构的关键。
管理域与运行域分离: 业务逻辑不能依靠运行期动态计算,要能在静态期进行定义并可视化呈现。业务定义中出现的规则叠加冲突,也在静态器进行冲突决策。在运行期,严格按照静态器定义的业务规则、冲突决策策略执行。Lattice 项目地址:https://github.com/hiforce/lattice
快速开始
版本依赖
<dependency>
<groupId>org.hiforce.lattice</groupId>
<artifactId>lattice-model</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>org.hiforce.lattice</groupId>
<artifactId>lattice-runtime</artifactId>
<version>1.0.13</version>
</dependency>
复制代码
Step 1:定义 “自定义商品单价” 扩展点
定义一个“自定义商品单价”的扩展点,允许业务能够去实现该扩展点,返回商品的自定义单价。
public interface OrderLinePriceExt extends IBusinessExt {
String EXT_ORDER_LINE_CUSTOM_UNIT_PRICE =
"OrderLinePriceExt.EXT_ORDER_LINE_CUSTOM_UNIT_PRICE";
@Extension(
code = EXT_ORDER_LINE_CUSTOM_UNIT_PRICE,
name = "Custom the Item's unit price of OrderLine",
reduceType = ReduceType.FIRST
)
Long getCustomUnitPrice(OrderLine orderLine);
}
复制代码
扩展点用 @Extension 注解进行标识,并分配一个全局唯一的扩展点编码,同时申明该扩展点的 Reduce 策略为 FIRST。 (Reduce 策略本章大家参考:https://www.ryu.xin/2022/09/27/lattice-reduce-policy)
Step 2:定义 “子订单价格管理” 能力
@Ability(name = "OrderLine's Price Ability")
public class OrderLinePriceAbility extends BaseLatticeAbility<OrderLinePriceExt> {
......
public Long getCustomUnitPrice(OrderLine orderLine) {
return Optional.ofNullable(reduceExecute(
p -> p.getCustomUnitPrice(orderLine),
Reducers.firstOf(Objects::nonNull)))
.orElse(orderLine.getUnitPrice());
}
......
}
复制代码
能力的定义用 @Ability 注解进行标识,同时需要申明当前的能力管理的扩展点集合是 OrderLinePriceExt。 并且,通过 getDefaultRealization() 方法,提供一个默认实现。
能力通过 reduceExecute () 方法尝试去加载 业务 针对 “自定义商品单价” 扩展点的自定义实现逻辑。
Step 3:编写业务自定义实现逻辑
我们定义一个业务 A,用 @Business 注解标识,并定义该业务的编码为 "business.a",如下:
@Business(code = "business.a", name = "Business A")
public class BusinessA extends BusinessTemplate {
}
复制代码
然后,针对业务 A,定义它的商品自定义单价为 2000 (单位分)。
@Realization(codes = "business.a")
public class BusinessAExt extends BlankOrderLinePriceExt {
@Override
public Long getCustomUnitPrice(OrderLine orderLine) {
return 2000L;
}
}
复制代码
业务的自定义实现逻辑用 @Realization 标识,并且 业务编码 是 "business.a"
我们可以用类似的方法,再定义一个业务 B,同时业务 B 对商品单价没有做任何定制,如下:
@Business(code = "business.b", name = "Business B")
public class BusinessB extends BusinessTemplate {
}
@Realization(codes = "business.b")
public class BusinessBExt extends BlankOrderLinePriceExt {
//do nothing.
}
复制代码
Step 4:启动 Lattice,并执行扩展点
public class LatticeQuickStart {
public static void main(String[] args) {
Lattice.getInstance().setSimpleMode(true);
Lattice.getInstance().start();
doBusinessA();
doBusinessB();
}
private static void doBusinessA() {
OrderLine orderLine = new OrderLine();
orderLine.setUnitPrice(1000L);
orderLine.setBizCode("business.a");
OrderLinePriceAbility ability = new OrderLinePriceAbility(orderLine);
Long unitPrice = ability.getCustomUnitPrice(orderLine);
System.out.println("[Business A] unit price: " + unitPrice);
}
private static void doBusinessB() {
OrderLine orderLine = new OrderLine();
orderLine.setUnitPrice(1000L);
orderLine.setBizCode("business.b");
OrderLinePriceAbility ability = new OrderLinePriceAbility(orderLine);
Long unitPrice = ability.getCustomUnitPrice(orderLine);
System.out.println("[Business B] unit price: " + unitPrice);
}
}
复制代码
我们分别模拟两次业务调用,其中商品默认单价(数据库中商品发布后的默认价格)为 1000L。 因为业务 A 对商品单价有定制,最终返回值应该是被定制后的 2000L; 而业务 B 没有做任何定制,所以返回值依然应该是 1000L。 运行 org.hiforce.lattice.sample.LatticeQuickStart#main 的控制台打印结果如下:
[Business A] unit price: 2000
[Business B] unit price: 1000
复制代码
通以上例子,我们可以看到基于 Lattice 框架最简单的一个用法。通过这种方式,我们可以很好地做到业务定制逻辑插件化,业务定制逻辑与平台隔离。同时,在本样例中,有两个业务,他们的业务身份分别为 "business.a"和"business.b"。通过业务身份,我们进一步让不同业务的定制逻辑进行分离。通过这种方式,可以极大地保护平台代码不被业务定制逻辑侵入,同时业务定制也能做到插件化闭包。
本样例代码:https://github.com/hiforce/lattice-sample/tree/main/lattice-quick-start
评论