18. 系统设置

本章介绍如何设置 Web 流系统以在任何 Web 环境中使用。spring-doc.cn

18.1. Java 配置和 XML 命名空间

Web Flow 为基于 Java 和 XML 的配置提供专用配置支持。spring-doc.cn

要开始使用基于 XML 的配置,请声明 config XML 命名空间,如下所示:webflowspring-doc.cn

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:webflow="http://www.springframework.org/schema/webflow-config"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/webflow-config
           https://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">

    <!-- Setup Web Flow here -->

</beans>

要开始使用 Java 配置,请在类中扩展,如下所示:AbstractFlowConfiguration@Configurationspring-doc.cn

import org.springframework.context.annotation.Configuration;
import org.springframework.webflow.config.AbstractFlowConfiguration;

@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {

}

18.2. 基本系统配置

接下来的两节显示了在应用程序中设置 Web 流系统所需的最低配置:spring-doc.cn

18.2.1. 注册FlowRegistry

您可以在 XML 中注册您的流,如下所示:FlowRegistryspring-doc.cn

<webflow:flow-registry id="flowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

您可以在 Java 中注册您的流,如下所示:FlowRegistryspring-doc.cn

@Bean
public FlowDefinitionRegistry flowRegistry() {
    return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
        .build();
}

18.2.2. 部署FlowExecutor

您可以部署 ,这是用于在 XML 中执行流的中央服务,如下所示:FlowExecutorspring-doc.cn

<webflow:flow-executor id="flowExecutor" />

您可以部署一个 ,这是用于在 Java 中执行流的中央服务:FlowExecutorspring-doc.cn

@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry()).build();
}

有关如何将 Web 流系统与 MVC 和 JSF 环境分别集成的 Spring MVC 集成和 JSF 集成部分,请参阅本指南的 Spring MVC 集成和 JSF 集成部分。spring-doc.cn

18.3. 选项flow-registry

本节探讨 flow-registry 配置选项。spring-doc.cn

18.3.1. 指定流位置

您可以使用该元素指定要注册的流定义的路径。 默认情况下,除非定义了注册表基本路径,否则会为流程分配等于其文件名减去文件扩展名的注册表标识符(请参阅流程位置基本路径)。locationspring-doc.cn

以下示例在 XML 中指定流位置:spring-doc.cn

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />

以下示例在 Java 中指定流位置:spring-doc.cn

return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
        .build();

18.3.2. 分配自定义流标识符

您可以指定一个 ID 以将自定义注册表标识符分配给流。spring-doc.cn

以下示例显示如何在 XML 中分配自定义流标识符:spring-doc.cn

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" />

以下示例显示如何在 Java 中分配自定义流标识符:spring-doc.cn

return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml", "bookHotel")
        .build();

18.3.3. 分配 Flow 元属性

您可以使用该元素将自定义元属性分配给已注册的流。flow-definition-attributesspring-doc.cn

以下示例显示了如何在 XML 中分配流元属性:spring-doc.cn

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml">
    <webflow:flow-definition-attributes>
        <webflow:attribute name="caption" value="Books a hotel" />
    </webflow:flow-definition-attributes>
</webflow:flow-location>

以下示例显示了如何在 Java 中分配流元属性:spring-doc.cn

Map<String, Object> attrs = ... ;

return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml", null, attrs)
        .build();

18.3.4. 使用位置模式注册流

您可以使用该元素注册与特定资源位置模式匹配的流。flow-location-patternsspring-doc.cn

以下示例演示如何在 XML 中注册流:spring-doc.cn

<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" />

以下示例演示如何在 Java 中注册流:spring-doc.cn

return getFlowDefinitionRegistryBuilder()
        .addFlowLocationPattern("/WEB-INF/flows...
        .build();

18.3.5. 流位置基本路径

您可以使用该属性为应用程序中的所有流定义基本位置。 然后,所有流位置都相对于基本路径。 基本路径可以是资源路径(例如 )或类路径上的位置(例如 )。base-path/WEB-INFclasspath:org/springframework/webflow/samplesspring-doc.cn

以下示例演示如何在 XML 中设置基本路径:spring-doc.cn

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location path="/hotels/booking/booking.xml" />
</webflow:flow-registry>

以下示例演示如何在 Java 中设置基本路径:spring-doc.cn

return getFlowDefinitionRegistryBuilder()
        .setBasePath("/WEB-INF")
        .addFlowLocationPattern("/hotels/booking/booking.xml")
        .build();

定义基本路径后,分配流标识符的算法会略有变化。 现在,为流分配了注册表标识符,该标识符等于其基本路径和文件名之间的路径段。 例如,如果流定义位于 且基本路径为 ,则此流的剩余路径为 ,该路径将成为流 ID。/WEB-INF/hotels/booking/booking-flow.xml/WEB-INFhotels/bookingspring-doc.cn

每个流定义的目录
最佳实践是将每个流定义打包到一个唯一的目录中。 这提高了模块化,让依赖资源与流定义打包在一起。 它还可以防止两个流在使用约定时具有相同的标识符。

如果未指定基本路径,或者流定义直接位于基本路径上,则使用文件名(不包括扩展名)中的流 ID 分配。 例如,如果流定义文件为 ,则流标识符仅为 。booking.xmlbookingspring-doc.cn

位置模式在与注册表基路径结合使用时特别强大。 流标识符不是变成 ,而是基于目录路径。 以下示例将基本路径与 XML 中的流位置模式组合在一起:*-flowspring-doc.cn

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>

以下示例将基本路径与 Java 中的流位置模式相结合:spring-doc.cn

return getFlowDefinitionRegistryBuilder()
        .setBasePath("/WEB-INF")
        .addFlowLocationPattern("...
        .build();

在前面的示例中,假设您的流位于 、 、 和 目录中。 您最终将分别得到 、、 和 的流 ID。/user/login/user/registration/hotels/booking/flights/bookingWEB-INFuser/loginuser/registrationhotels/bookingflights/bookingspring-doc.cn

18.3.6. 配置层次结构FlowRegistry

您可以使用该属性将层次结构中的两个流注册表链接在一起。 查询子注册表时,如果找不到请求的流,则会委托给其父注册表。parentspring-doc.cn

以下示例在 XML 中为两个流注册表建立父关系:spring-doc.cn

<!-- my-system-config.xml -->
<webflow:flow-registry id="flowRegistry" parent="sharedFlowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<!-- shared-config.xml -->
<webflow:flow-registry id="sharedFlowRegistry">
    <!-- Global flows shared by several applications -->
</webflow:flow-registry>

以下示例为 Java 中的两个流注册表建立父关系:spring-doc.cn

@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {

    @Autowired
    private SharedConfig sharedConfig;

    @Bean
    public FlowDefinitionRegistry flowRegistry() {
        return getFlowDefinitionRegistryBuilder()
                .setParent(this.sharedConfig.sharedFlowRegistry())
                .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
                .build();
    }
}

@Configuration
public class SharedConfig extends AbstractFlowConfiguration {

    @Bean
    public FlowDefinitionRegistry sharedFlowRegistry() {
        return getFlowDefinitionRegistryBuilder()
                .addFlowLocation("/WEB-INF/flows/shared.xml")
                .build();
    }
}

18.3.7. 配置自定义服务FlowBuilder

您可以使用属性(在 XML 中)或对象(在 Java 中)来自定义用于在流注册表中构建流的服务和设置。 如果未指定 element,则使用默认服务实现。 指定元素后,您只需引用要自定义的服务。flow-builder-servicesFlowBuilderServicesflow-builder-servicesspring-doc.cn

以下示例显示如何在 XML 中创建自定义流生成器服务:spring-doc.cn

<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<webflow:flow-builder-services id="flowBuilderServices" />

以下示例显示了如何在 Java 中创建自定义流构建器服务:spring-doc.cn

@Bean
public FlowDefinitionRegistry flowRegistry() {
	return getFlowDefinitionRegistryBuilder(flowBuilderServices())
            .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
            .build();
}

@Bean
public FlowBuilderServices flowBuilderServices() {
    return getFlowBuilderServicesBuilder().build();
}

可配置的服务是 、 和 元素(在 XML 中)和 、 和 接口(在 Java 中)。 这些服务是通过引用必须定义的自定义 bean 来配置的。conversion-serviceexpression-parserview-factory-creatorConversionServiceExpressionParserViewFactoryCreatorspring-doc.cn

以下示例显示了如何在 XML 中定义可配置服务:spring-doc.cn

<webflow:flow-builder-services id="flowBuilderServices"
    conversion-service="conversionService"
    expression-parser="expressionParser"
    view-factory-creator="viewFactoryCreator" />

<bean id="conversionService" class="..." />
<bean id="expressionParser" class="..." />
<bean id="viewFactoryCreator" class="..." />

以下示例演示如何在 Java 中定义可配置服务:spring-doc.cn

@Bean
public FlowBuilderServices flowBuilderServices() {
    return getFlowBuilderServicesBuilder()
            .setConversionService(conversionService())
            .setExpressionParser(expressionParser)
            .setViewFactoryCreator(mvcViewFactoryCreator())
            .build();
}

@Bean
public ConversionService conversionService() {
    // ...
}

@Bean
public ExpressionParser expressionParser() {
    // ...
}

@Bean
public ViewFactoryCreator viewFactoryCreator() {
    // ...
}
使用 Conversion Service

您可以使用属性(在 XML 中)或接口(在 Java 中)来自定义 Web 流系统使用的 。 类型转换用于在流程执行期间需要时(例如在处理请求参数、调用操作等)时从一种类型转换为另一种类型。 支持许多常见的对象类型(例如数字、类和枚举)。 但是,您可能需要为自定义数据类型提供自己的类型转换和格式设置逻辑。 有关如何提供自定义类型转换逻辑的重要信息,请参阅执行类型转换conversion-serviceConversionServiceConversionServicespring-doc.cn

使用 Expression Parser

您可以使用属性(在 XML 中)或接口(在 Java 中)来自定义 Web 流系统使用的 。 默认情况下,如果 Classpath 上可用,则使用 Unified Expression Language。 否则,它使用 Spring 表达式语言。expression-parserExpressionParserExpressionParserExpressionParserspring-doc.cn

使用 View Factory Creator

您可以使用属性(在 XML 中)或接口(在 Java 中)来自定义 Web 流系统使用的 。 默认生成能够渲染 JSP、Velocity 和 Freemarker 视图的 Spring MVC 视图工厂。view-factory-creatorViewFactoryCreatorViewFactoryCreatorViewFactoryCreatorspring-doc.cn

可配置的设置包括 。 这些设置是您可以在流程构建过程中应用的全局配置属性。developmentspring-doc.cn

启用开发模式

创建 Flow Builder 服务对象时,您可以开启开发模式。 开发模式会启用流定义更改的热重载,包括对依赖流资源(如消息包)的更改。spring-doc.cn

要在 XML 中打开开发模式,请将元素上的属性设置为 。 要在 Java 中打开开发模式,请在对象上使用。developmentflow-builder-servicestruesetDevelopment(true)FlowBuilderServicesspring-doc.cn

18.4. 设置 Flow Executor 选项

本节探讨 Flow Executor 配置选项。spring-doc.cn

18.4.1. 附加流执行侦听器

您可以使用 element (在 XML 中) 或 method (在 Java 中) 来注册观察流执行生命周期的侦听器。flow-execution-listenersaddFlowExecutionListenerspring-doc.cn

以下示例显示如何在 XML 中创建流执行侦听器:spring-doc.cn

<webflow:flow-execution-listeners>
    <webflow:listener ref="securityListener"/>
    <webflow:listener ref="persistenceListener"/>
</webflow:flow-execution-listeners>

以下示例显示了如何在 Java 中创建流执行侦听器:spring-doc.cn

@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .addFlowExecutionListener(securityListener())
            .addFlowExecutionListener(persistenceListener())
            .build();
}

您还可以将侦听器配置为仅观察某些流。spring-doc.cn

以下示例说明如何将侦听器配置为仅监控 XML 中的两个流:spring-doc.cn

<webflow:listener ref="securityListener" criteria="securedFlow1,securedFlow2"/>

以下示例说明如何将侦听器配置为仅监控 Java 中的两个流:spring-doc.cn

@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .addFlowExecutionListener(securityListener(), "securedFlow1,securedFlow2")
            .build();
}

18.4.2. 调整 Flow 执行持久性

您可以使用元素(在 XML 中)或接口(在 Java 中)来调整流执行持久性设置。flow-execution-repositoryFlowExecutorspring-doc.cn

以下示例调整 XML 中的流执行:spring-doc.cn

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    <webflow:flow-execution-repository max-executions="5" max-execution-snapshots="30" />
</webflow:flow-executor>

以下示例调整 Java 中的流执行:spring-doc.cn

@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .setMaxFlowExecutions(5)
            .setMaxFlowExecutionSnapshots(30)
            .build();
}
调音max-executions

您可以调整属性(在 XML 中),以限制每个用户会话可创建的流程执行数。 当超过最大执行次数时,将删除最早的执行。max-executionsspring-doc.cn

该属性是按用户会话的。 也就是说,它适用于任何流定义的实例。max-executions
调音max-execution-snapshots

您可以优化该属性,以限制每次流程执行可拍摄的历史记录快照的数量。 要禁用快照,请将此值设置为 0。 要启用无限数量的快照,请将此值设置为 -1。max-execution-snapshotsspring-doc.cn

历史记录快照支持浏览器后退按钮。 禁用快照后,按浏览器后退按钮不起作用。 这样做会导致使用指向尚未记录的快照的执行键。