dami - lpc 之本地(单体)过程调用
Lpc 是相对于 Rpc 的本地概念(本地过程调用)。为单体多模块项目提供解耦支持。
1、本地过程调用
通过总线,把本地没有关系的 “服务消费者” 和 “服务提供者” 实现接口调用。从而实现“解耦”。
//服务消费者
public interface UserService {
Long getUserId(String name);
}
//服务提供者(或实现)
public class UserServiceImpl {
public Long getUserId(String name) {
return 99L;
}
}
public class DemoApp {
public static void main(String[] args) throws Exception {
//注册服务提供者(监听事件)
Dami.lpc().registerProvider("demo", new UserServiceImpl());
//生成服务消费者(发送事件)
UserService userService = Dami.lpc().createConsumer("demo", UserService.class);
userService.getUserId("noear");
}
}
2、LPC 的内部处理
流事件的内部同样是“通用事件”(仅是一种体验简化)。改成“通用事件”。
- 把服务侧改为“通用事件”处理
LPC 默认编码处理,会把方法的参数编码成 Map 做为载核数据。注意主题的变化,要与方法名对应起来。
public class DemoApp {
public static void main(String[] args) throws Exception {
//注册服务提供者(监听事件)
//Dami.lpc().registerProvider("demo", new UserServiceImpl());
Dami.bus().<CallPayload<Map<String,Object>, Long>>listen("demo.getUserId", event -> {
//获取参数
String name = (String) event.getPayload().getData().get("name");
event.getPayload().getSink().complete(99L);
});
//生成服务消费者(发送事件)
UserService userService = Dami.lpc().createConsumer("demo", UserService.class);
userService.getUserId("noear");
}
}
- 把消费侧改为“通用事件”处理
注意主题的变化,要与方法名对应起来。
public class DemoApp {
public static void main(String[] args) throws Exception {
//注册服务提供者(监听事件)
Dami.lpc().registerProvider("demo", new UserServiceImpl());
//生成服务消费者(发送事件)
//UserService userService = Dami.lpc().createConsumer("demo", UserService.class);
//userService.getUserId("noear");
Long rst = Dami.bus().<CallPayload<Map<String,Object>, Long>>send("demo.getUserId", new CallPayload<>(Utils.asMap("name", "noear")))
.getPayload()
.getSink()
.get();
System.err.println(rst);
}
}
3、注意事项(参数变名)
java 编译时,默认会把参数名变掉(arg0
, arg1
...)。可能会造成 lpc 调用,参数名对不上的情况。解决方法有两个:
- 添加编译参考,让参数名保持不变。参考:《问题:编译保持参数名不变-parameters?》
- 给参数添加
@org.noear.dami2.annotation.Param(name)
指定参数名。
示例1:Demo33(模拟参数变名)
public class Demo33 {
static String topicMapping = "demo.user";
//定义实例,避免单测干扰 //开发时用:Dami.lpc()
@Test
public void main() throws Exception {
//用 lpc 调
Dami.lpc().registerProvider(topicMapping, new EventDemoImpl());
EventDemo eventDemo = Dami.lpc().createConsumer(topicMapping, EventDemo.class);
assert eventDemo.demo4(1, 0) == 5;
//用 bus 调
Integer rst = Dami.bus().<Map, Integer>call(topicMapping + ".demo4", CollUtil.asMap("b0", 1, "b1", 0)).get();
Assertions.assertEquals(4, rst);
}
public static interface EventDemo {
default int demo4(@Param("b1") Integer i, @Param("b0") Integer b) {
return 1 + i;
}
}
public static class EventDemoImpl {
public int demo4(@Param("b0") Integer b, @Param("b1") Integer i) {
return 4 + i;
}
}
}
示例2: Demo82(模拟参数变名,在 IOC 容器下)
@SolonTest
public class Demo82 {
static final Logger log = LoggerFactory.getLogger(Demo82.class);
@Inject
EventUserService eventUserService;
@Test
public void main() throws Throwable {
//用 lpc 调
User user = eventUserService.getUser(99);
Assertions.assertEquals(99, user.getUserId());
//用 bus 调
user = Dami.bus().<Map, User>call("demo82.event.user.getUser", CollUtil.asMap("uid", 99)).get();
Assertions.assertEquals(99, user.getUserId());
}
}
@DamiTopic("demo82.event.user")
public interface EventUserService {
User getUser(@Param("uid") long userId); //方法的主题 = topicMapping + "." + method.getName() //方法不能重名
}
@DamiTopic("demo82.event.user")
public class EventUserServiceImpl { // implements EventUserService // 它相当于是个实现类
public User getUser(@Param("uid") long userId) {
return new User(userId);
}
}
public class User {
private long userId;
private String name;
public User(long userId) {
this.userId = userId;
this.name = "user-" + userId;
}
public long getUserId() {
return userId;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", name='" + name + '\'' +
'}';
}
}