跳到主要内容

OnExternal

介绍

访问对外服与扩展,是框架提供的通信方式之一,主要用于逻辑服与对外服的交互上。 本篇介绍如何从对外服中获取我们需要的数据, 开发者可以通过扩展 OnExternal 接口实现与对外服交互。 框架通过这一扩展,轻松实现了如下功能

现在,我们通过一个获取 userIp 的示例来学习如何扩展。

Example Source Code

see https://github.com/iohao/ionet-examples

path : ionet-cookbook-code

  • UserIpOnExternal
  • OnExternalAction

如何扩展

  • code 4: 获取当前用户。
  • code 7: 获取当前用户的 ip。
  • code 8: 设置响应值给请求端。
  • code 13: 设置扩展标记 ExternalTemplateId。
public class UserIpOnExternal implements OnExternal {
@Override
public void process(byte[] payload, int payloadLength, OnExternalContext context) {
UserSession userSession = context.getUserSession();
ActionErrorEnum.dataNotExist.assertNonNull(userSession);
// get userIp
String ip = userSession.getIp();
context.response().setPayload(ip);
}

@Override
public int getTemplateId() {
return MyOnExternalTemplateId.userIp;
}
}

public interface MyOnExternalTemplateId {
/** get userIp */
int userIp = 1;
}

配置

将实现类添加到 OnExternalManager 中。

class OneApplication {
static void main() {
OnExternalManager.register(new UserIpOnExternal());
...
new RunOne()
...
.startup();
}
}

如何使用

通过 callExternal 系列方法可以直接访问用户所在的对外服。

@ActionController(OnExternalCmd.cmd)
public final class OnExternalAction {
@ActionMethod(OnExternalCmd.userIp)
private String getIp(FlowContext flowContext) {
var externalResponse = flowContext.callExternal(MyOnExternalTemplateId.userIp);
return externalResponse.getPayloadAsString();
}
}

统计在线人数

通过上面的示例,我们知道了如何获取 userIp,但示例是访问单个对外服的,现在我们做一个统计在线用户的扩展。 如果我们启动了多个对外服,就需要知道每个对外服的当前在线人数,这个扩展功能会同时与多个对外服交互。

  • code 4: 获取当前对外服的 UserSessions。
  • code 6: 设置响应值给请求端。
  • code 11: 设置扩展标记 ExternalTemplateId。
  • code 23: 将实现类添加到 OnExternalManager 中。
public final class UserOnlineCountOnExternal implements OnExternal {
@Override
public void process(byte[] payload, int payloadLength, OnExternalContext context) {
UserSessions<?, ?> userSessions = context.userSessions();
int countOnline = userSessions.countOnline();
context.response().setPayload(countOnline);
}

@Override
public int getTemplateId() {
return MyOnExternalTemplateId.userOnlineCount;
}
}

public interface MyOnExternalTemplateId {
/** get userIp */
int userIp = 1;
int userOnlineCount = 2;
}

class OneApplication {
static void main() {
OnExternalManager.register(new UserIpOnExternal());
...
}
}

如何使用

  • code 7: 通过 callCollectExternal 系列方法可以直接访问所有对外服。
  • code 8: 遍历每个对外服的响应。
  • code 10: 获取在 UserOnlineCountOnExternal 中设置的值。
@ActionController(OnExternalCmd.cmd)
public final class OnExternalAction {
@ActionMethod(OnExternalCmd.userOnlineCount)
private int userOnlineCount(FlowContext flowContext) {
int onlineCount = 0;

var responseCollectExternal = flowContext.callCollectExternal(MyOnExternalTemplateId.userOnlineCount);
for (var externalResponse : responseCollectExternal.getResponseList()) {
int externalServerId = externalResponse.getExternalServerId();
int count = externalResponse.getPayloadAsInt();
log.info("externalServerId:{}, count:{}", externalServerId, count);

onlineCount += count;
}

return onlineCount;
}
}

如何设置请求参数

上面的两个扩展示例没有演示请求参数,但在实际业务中,我们可能会传一些请求参数给 OnExternal 扩展类。 callCollectExternal 和 callExternal 方法提供了重载,开发者可以通过重载传入请求参数,具体可参考源码 AttachmentUpdateOnExternal。


设置请求参数

...
void test() {
byte[] payload = ...
flowContext.callExternal(MyOnExternalTemplateId.xxx, payload);
}

获取请求参数

public final class AttachmentUpdateOnExternal implements OnExternal {
@Override
public void process(byte[] payload, int payloadLength, OnExternalContext context) {
var userSession = context.getUserSession();
if (userSession != null) {
userSession.setAttachment(ByteKit.getPayload(payload, payloadLength));
} else {
context.response().setError(ActionErrorEnum.dataNotExist);
}
}

...
}

小结

只要想象力足够,通过 OnExternal 接口可以做很多事。 通过扩展该接口,可以与对外服交互及获取数据。