跳到主要内容

FlowContext

介绍

FlowContext 是业务框架 action 流程处理的上下文,生命周期存在于这一次的 action 请求。 如果你之前只接触过 web 开发,可以暂时将其理解为 Cookie。

FlowContext 功能包括但不限于如下:

  • userId 的获取。
  • 具备动态属性能力。
  • 提供通信能力,为各通信方式提供了同步、异步、异步回调 ...等便捷 api, 并具备全链路调用日志跟踪特性。
  • 支持元信息-附加信息的扩展(开发者可扩展用户数据的存储)。
  • 支持自定义扩展 (开发者可定制符合团队、符合业务的使用 API)。
  • 得到当前 FlowContext 对应的线程执行器,可轻松实现无锁高并发

由于 FlowContext 具备了通信能力,并且提供了同步、异步、异步回调 ...等便捷 api, 并具备全链路调用日志跟踪特性。 所以你可以使用简洁的代码编写跨服访问,或给自己发送数据。

业务框架流程简图

下图是关于 action 的处理流程 ,FlowContext 会经过图中的每个环节。

An

如何获取 FlowContext

只需要在 action 的方法参数中定义该变量即可,框架会自动识别。

@ActionController(1)
public class DemoAction {
@ActionMethod(1)
public void demo(FlowContext flowContext) {
}
}

userId

用户登录后,可以通过 flowContext 来获取 userId。

long userId = flowContext.getUserId();

自定义 FlowContext

框架提供了 FlowContext 的扩展,如果 FlowContext 现有的功能无法满足你现有的业务, 可以通过扩展的方式增强 FlowContext。 该小节我们自定义一个 FlowContext,并添加一些自定义的方法。

@Setter
public class MyFlowContext extends DefaultFlowContext {
public String getNickname() {
return "Michael Jackson";
}
}

设置自定义的 FlowContext

static void main() {
CoreGlobalConfig.setting.flowContextFactory = MyFlowContext::new;
}

在 action 中的使用

自定义的 MyFlowContext 与框架默认提供的 FlowContext 使用方式是一样的

@ActionController(MyCmd.cmd)
public class MyAction {
@ActionMethod(MyCmd.nickname)
private String getNickname(MyFlowContext flowContext) {
return flowContext.getNickname();
}
}

线程执行器 - 无锁高并发

FlowContext 提供了获取与用户所关联线程执行器,包括用户虚拟线程执行器和用户线程执行器。 框架提供了优雅、独特的线程执行器设计。通过该特性,开发者能轻易的编写出无锁高并发的代码。

具体可阅读线程相关内容。


UserThreadExecutorRegion 是用户线程执行器,也是消费 action 业务的线程执行器。 开发者可以将任务提交到该执行器中执行,能避免并发问题。

  • code 2,使用用户线程执行任务,该方法具备全链路调用日志跟踪。
  • code 6,提交任务到用户线程执行器中。
void executor() {
flowContext.execute(() -> {
// your code
});

flowContext.getExecutor().execute(() -> {
// your code
});
}

UserVirtualThreadExecutorRegion 是用户虚拟线程执行器, 开发者可以将带有 IO 或阻塞的任务提交到该执行器中执行。

  • code 2,使用虚拟线程执行任务,该方法具备全链路调用日志跟踪。
  • code 6,提交任务到虚拟线程执行器中。
void executeVirtual() {
flowContext.executeVirtual(() -> {
// your code
});

flowContext.getVirtualExecutor().execute(() -> {
// your code
});
}

通信能力

FlowContext 内部整合了通信模型, 并提供了同步、异步、异步回调的便捷使用方式。 更多使用示例,请阅读 Examples Communication

除了整合广播 API 外,还支持广播给自己,api 名字以 broadcastMe 打头。

@ActionController(FlowContextBroadcastCmd.cmd)
public class FlowContextBroadcastAction {
AtomicInteger inc = new AtomicInteger();

@ActionMethod(triggerBroadcastMe)
private void triggerBroadcastMe(FlowContext flowContext) {
// ---------- empty ----------
flowContext.broadcastMe(broadcastMeEmpty);

// ---------- int ----------
int dataInt = inc.getAndIncrement();
flowContext.broadcastMe(broadcastMeInt, dataInt);

// ---------- boolean ----------
boolean dataBool = inc.getAndIncrement() % 2 == 0;
flowContext.broadcastMe(broadcastMeBool, dataBool);

// ---------- long ----------
long dataLong = inc.getAndIncrement();
flowContext.broadcastMe(broadcastMeLong, dataLong);

// ---------- string ----------
String dataString = "ionet-" + inc.getAndIncrement();
flowContext.broadcastMe(broadcastMeString, dataString);

// ---------- object ----------
BookMessage dataObject = new BookMessage();
dataObject.authorName = "ionet";
dataObject.bookName = "book-" + inc.getAndIncrement();
flowContext.broadcastMe(broadcastMeObject, dataObject);

// ---------- list int ----------
List<Integer> dataListInt = List.of(inc.getAndIncrement(), inc.getAndIncrement());
flowContext.broadcastMeListInt(broadcastMeIntList, dataListInt);

// ---------- list boolean ----------
List<Boolean> dataListBool = List.of(
inc.getAndIncrement() % 2 == 0,
inc.getAndIncrement() % 2 == 0
);

flowContext.broadcastMeListBool(broadcastMeBoolList, dataListBool);

// ---------- list long ----------
List<Long> dataListLong = List.of(
(long) inc.getAndIncrement(),
(long) inc.getAndIncrement()
);

flowContext.broadcastMeListLong(broadcastMeLongList, dataListLong);

// ---------- list string ----------
List<String> dataListString = List.of(
"ionet-" + inc.getAndIncrement(),
"ionet-" + inc.getAndIncrement()
);

flowContext.broadcastMeListString(broadcastMeStringList, dataListString);

// ---------- list object ----------
BookMessage message1 = new BookMessage();
message1.authorName = "ionet";
message1.bookName = "book-" + inc.getAndIncrement();

BookMessage message2 = new BookMessage();
message2.authorName = "ionet";
message2.bookName = "book-" + inc.getAndIncrement();

List<BookMessage> dataList = List.of(message1, message2);
flowContext.broadcastMe(broadcastMeObjectList, dataList);
}
}

小结

FlowContext 是当前 action 的请求上下文,通过 FlowContext 几乎可以拿到当前逻辑服的所有信息,这些信息包括:逻辑服、业务框架等。 框架提供了 FlowContext 的扩展,如果 FlowContext 现有的功能无法满足你现有的业务,可以通过扩展的方式增强 FlowContext。

FlowContext 整合了一些常用的 api

  • 通信相关的有:
    • 内部请求时的同步、异步、异步回调的便捷使用方式。
    • Broadcast 广播。
    • EventBus。
    • OnExternal。
  • 元信息相关的有:
    • updateAttachment 同步更新。
    • updateAttachmentAsync 异步更新。
  • 线程执行器相关的有:
    • 用户虚拟线程执行器。
    • 用户线程执行器。