Ohhnews

分类导航

$ cd ..
DZone Java原文

Jakarta Faces 流作用域:无需会话状态管理多步骤用户体验

#jakarta faces#flowscoped#状态管理#多步骤流程#企业级java

多步骤流程在用户体验中很常见,包括引导流程、结账、账户设置、审批流程、配置向导和管理任务。这些流程要求用户经过多个屏幕,同时保持持续一致的工作状态。挑战在于让该状态在交互期间保持活跃,但不要超出这一范围。请求作用域太短,而会话作用域往往比业务流程所需的时间更长。Jakarta Faces 通过 @FlowScoped 处理这一问题,它根据流程的生命周期而非单个页面或整个会话来管理状态。本文使用客户细分应用程序来演示流程如何引导用户完成配置、预览和确认,同时在每一步之间保持状态。这种方法为向导式用户体验创建了更清晰的模型:作用域在用户进入流程时开始,在导航期间持续存在,并在退出时结束。

为什么 Jakarta Faces 依然重要

Jakarta Faces 仍然具有相关性,因为许多企业应用由具备深厚 Java 专业能力的团队开发和维护。在这些环境中,服务端 UI 框架可以减少上下文切换,让验证和导航紧贴应用模型,并允许团队在整个技术栈中复用相同的语言、依赖注入模型和企业级 API。从架构上看,如果团队精通 Java,且应用是表单驱动、面向工作流或侧重于后台办公,那么引入独立的前端技术栈未必有优势。

诸如 PrimeFaces 之类的组件库进一步支持了这种方法。团队无需从零构建表格、对话框、表单、图表、向导和验证,而是可以在 Jakarta EE 编程模型中使用可复用组件。这可以加速交付,并减少对自定义前端基础设施的需求。虽然决策应基于产品和团队背景,但对于以 Java 为重点的企业团队来说,Jakarta Faces 是一种务实的架构选择,而不仅仅是遗留选项。一些公开记录的使用过 Jakarta EE/JSF 或 PrimeFaces 的组织示例包括:

  • NASA
  • 沃尔玛实验室
  • 汉莎航空
  • 乐天
  • 德国商业银行
  • 联合国
  • 宾夕法尼亚州立大学
  • 哈佛大学
  • 西班牙电信
  • Big Lots
  • Comfortel(电信)
  • 多家商业银行和金融机构

Jakarta Faces 作用域概览

Jakarta Faces 应用会以不同时长维护托管 Bean 状态。选择正确的作用域是一项架构决策,并且必须与用户交互的生命周期相匹配。有些状态仅限于单个 HTTP 请求、单个页面、多步骤流程或整个用户会话。

  • @RequestScoped 是生命周期最短的作用域。它为每个 HTTP 请求创建一个 Bean 实例,并在请求完成时丢弃该实例。它适用于无状态操作、简单提交,以及不需要跨导航或 Ajax 交互持续存在的操作。
  • @ViewScoped 在用户停留在同一个 Faces 视图期间保留 Bean。它非常适合包含表单、表格、过滤、分页、对话框,或会多次更新同一页面的 Ajax 交互的页面。当用户导航到不同视图时,状态会被丢弃。
  • @FlowScoped 用于跨多个视图的业务交互,例如结账、引导流程、配置向导、审批工作流或客户细分。Bean 在整个流程中保持活跃,并在流程结束时被销毁。其生命周期介于视图作用域和会话作用域之间。
  • @SessionScoped 为整个用户会话维护状态。它适用于跨多个页面保留的信息,例如用户偏好或会话级上下文。避免将其用于临时工作流状态,因为这可能会不必要地延长状态的生命周期。
  • @ApplicationScoped 的生命周期最广,在整个应用和所有用户之间共享单个 Bean 实例。它适用于共享服务、缓存、配置或应用级状态,但不适用于按用户或按流程的数据,除非明确为共享和线程安全而设计。

[LOADING...]

使用 @FlowScoped 构建多步骤体验

本文重点介绍 Jakarta Faces 流程,它用于建模跨多个页面但短于完整 HTTP 会话的用户交互。在客户细分示例中,管理员配置阈值,预览其影响,审查配置,并启动操作。这些步骤构成一个单一业务流程,并且应共享同一状态。Jakarta Faces 通过流程定义和流程作用域托管 Bean 来表示这一过程。在此项目中,流程位于 customer-segmentation 目录中:

src/main/webapp/
└── customer-segmentation/
    ├── customer-segmentation-flow.xml
    ├── configure.xhtml
    ├── preview.xhtml
    └── review.xhtml

将目录、流程标识符和 Bean 名称保持一致,可以明确它们之间的关系。在这里,流程名称保持为 customer-segmentation,定义在 customer-segmentation/customer-segmentation-flow.xml 中,而 Java Bean 使用 @FlowScoped("customer-segmentation")。传递给 @FlowScoped 的值将 Bean 的生命周期绑定到相应的 Faces 流程。XML 文件定义流程的结构和导航边界,但不存储业务状态。在此示例中,configure 是起点,随后是 preview 和 review。每个视图都有一个标识符,并引用其对应的 XHTML 文档:

configure /customer-segmentation/configure.xhtml /customer-segmentation/preview.xhtml /customer-segmentation/review.xhtml /index?faces-redirect=true

start-node 指定交互从哪里开始。这些元素定义流程的页面,并决定应用如何退出。返回结果 home 会结束流程,将用户重定向到仪表板,并丢弃流程作用域状态。流程内的导航会保留状态,而退出流程则会结束对话。

在 Java 侧,CustomerSegmentationFlow 同时作为命名 Faces Bean 和流程作用域 Bean 管理对话状态:

$ java
@Named
@FlowScoped("customer-segmentation")
public class CustomerSegmentationFlow implements Serializable {
    @Inject
    private CustomerSegmentationFlowService flowService;
    private CustomerSegmentationFlowState state;

    @PostConstruct
    public void initialize() {
        state = flowService.initializeState();
    }

    // ...
}

@Named 使 Bean 可以通过表达式语言被 Faces 页面访问,而 @FlowScoped("customer-segmentation") 将其生命周期分配给特定流程。在 @PostConstruct 期间创建的状态会在流程期间的请求和页面转换之间保留,因此 CustomerSegmentationFlowState 在整个交互过程中始终可用。这一区别使 @FlowScoped 与 @ViewScoped 不同。使用视图作用域时,从 configure.xhtml 移动到 preview.xhtml 会开始一个新的对话。使用流程作用域时,两个视图仍属于同一个业务交互的一部分。作用域跟随的是对话,而不是单个页面。然后,Bean 上的导航方法会返回与流程定义的节点相对应的结果:

$ java
public String preview() {
    flowService.preview(state);
    return "preview";
}

public String review() {
    return "review";
}

返回 “preview” 会将用户移动到流程定义中的 preview 视图,而 “review” 会前进到下一个视图。由于两个目的地都在 customer-segmentation 内,因此同一个流程作用域 Bean 及其状态会保持活跃。最后一个操作展示了生命周期的另一面:

$ java
public String execute() {
    long executionId = flowService.start(state);
    // message handling omitted
    return "home";
}

Home 不是向导中的页面。它对应 XML 定义中的 <flow-return> 元素。当该结果发生时,Faces 会退出流程,将用户重定向到仪表板,并丢弃关联的状态。

@FlowScoped 非常适合结账、引导流程、注册、审批、配置和管理向导等过程。它提供的作用域比单个页面更广,但比会话更窄。与其将 @SessionScoped 用于临时工作流数据,不如让状态仅在工作流持续期间存在。

本文涵盖 Faces 流程:页面如何连接、状态如何在页面之间持久化,以及进入和退出流程如何管理 Java Bean 的生命周期。完整应用还包括 MongoDB 持久化、仪表板服务、预览计算和 Jakarta Batch 处理。完整源代码可在 https://github.com/soujava/mongodb-jakarta-batch 获取。这里的重点仍然是由 Configure → Preview → Review → Exit 所表示的用户交互。

结论

@FlowScoped 为 Jakarta Faces 提供了一种有效方式,将多步骤用户体验建模为单个业务对话。流程不会将临时工作流状态存储在 @SessionScoped 中,也不会在视图之间重建状态,而只在用户逐步完成已定义步骤期间维护状态,并在流程结束时释放它。

对于以 Java 为重点的企业团队,这种方法通过使导航、状态和生命周期与用户体验保持一致,简化了向导、引导流程、审批、结账流程和配置过程。

DZone 贡献者表达的观点仅代表他们自己。