Solon v3.6.0

dami - lpc 之本地(单体)过程调用

</> markdown

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 调用,参数名对不上的情况。解决方法有两个:

示例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 + '\'' +
                '}';
    }
}