«1. Обзор
Spring Web Flow основан на Spring MVC и позволяет реализовывать потоки внутри веб-приложения. Он используется для создания последовательности шагов, которые проводят пользователей через процесс или некоторую бизнес-логику.
В этом кратком руководстве мы рассмотрим простой пример процесса активации пользователя. Пользователю предоставляется страница, и он нажимает кнопку «Активировать», чтобы продолжить, или кнопку «Отмена», чтобы отменить активацию.
Здесь не предполагается, что у нас уже есть настроенное веб-приложение Spring MVC.
2. Настройка
Начнем с добавления зависимости Spring Web Flow в файл pom.xml:
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
Последнюю версию Spring Web Flow можно найти в центральном репозитории Maven.
3. Создание потока
Давайте теперь создадим простой поток. Как было сказано ранее, поток — это последовательность шагов, которая ведет пользователя через процесс. В настоящее время это можно сделать только с помощью конфигурации на основе XML.
Каждый шаг в потоке называется состоянием.
В этом простом примере мы будем использовать состояние просмотра. Состояние просмотра — это шаг в потоке, который отображает соответствующее представление. Состояние просмотра относится к странице в приложении (WEB-INF/представление), при этом идентификатором состояния просмотра является имя страницы, на которую оно ссылается.
Мы также будем использовать элемент перехода. Элемент перехода используется для обработки событий, происходящих в определенном состоянии.
Для этого примера потока мы настроим три состояния просмотра — активация, успех и неудача.
Процесс для этого потока довольно прост. Отправной точкой является представление активации. Если событие активации инициировано, оно должно перейти в представление успеха. Если событие отмены инициировано, оно должно перейти в представление отказа. Элемент перехода обрабатывает событие нажатия кнопки, которое происходит в состоянии просмотра:
<view-state id="activation">
<transition on="activate" to="success"/>
<transition on="cancel" to="failure"/>
</view-state>
<view-state id="success" />
<view-state id="failure" />
Начальная страница активации, на которую ссылается идентификатор активации и которая находится в WEB-INF/view/activation.jsp, представляет собой простая страница с двумя кнопками, активировать и отменить. Нажатие кнопок с инициирует наши переходы, чтобы отправить пользователя в состояние просмотра успеха (WEB-INF/view/success.jsp) или состояние просмотра отказа (WEB-INF/view/failure.jsp):
<body>
<h2>Click to activate account</h2>
<form method="post" action="${flowExecutionUrl}">
<input type="submit" name="_eventId_activate" value="activate" />
<input type="submit" name="_eventId_cancel" value="cancel" />
</form>
</body>
Мы используем flowExecutionUrl для доступа к контекстно-зависимому URI для текущего состояния представления выполнения потока.
4. Настройка потока
Далее мы настроим Spring Web Flow в нашей веб-среде. Мы сделаем это, настроив Flow Registry и Flow Builder Service.
Реестр потоков позволяет нам указать расположение наших потоков, а также указать службу построителя потоков, если она используется.
Служба Flow Builder помогает нам настраивать службы и параметры, используемые для создания потоков.
Одним из сервисов, которые мы можем настроить, является view-factory-creator. View-factory-creator позволяет нам настраивать ViewFactoryCreator, используемый Spring Web Flow. Поскольку мы используем Spring MVC, мы можем настроить Spring Web Flow для использования преобразователя представлений в наших конфигурациях Spring MVC.
Вот как мы настроим Spring Web Flow для нашего примера:
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private WebMvcConfig webMvcConfig;
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
.addFlowLocation("/WEB-INF/flows/activation-flow.xml", "activationFlow")
.build();
}
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true).build();
}
@Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(
Collections.singletonList(this.webMvcConfig.viewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
}
Мы также можем использовать XML для этой конфигурации:
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="activationFlowRegistry"/>
</bean>
<flow:flow-builder-services id="flowBuilderServices"
view-factory-creator="mvcViewFactoryCreator"/>
<bean id="mvcViewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="jspViewResolver"/>
</bean>
<flow:flow-registry id="activationFlowRegistry"
flow-builder-services="flowBuilderServices">
<flow:flow-location id="activationFlow" path="/WEB-INF/flows/activation-flow.xml"/>
</flow:flow-registry>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="activationFlowExecutor"/>
</bean>
<flow:flow-executor id="activationFlowExecutor"
flow-registry="activationFlowRegistry"/>
5. Навигация по потокам
Для навигации по потоки, запустите веб-приложение и перейдите по адресу http://localhost:8080/{context-path}/activationFlow. Чтобы запустить приложение, разверните его на сервере приложений, таком как Tomcat или Jetty.
Это отправляет нас на начальную страницу потока, которая является страницей активации, указанной в нашей конфигурации потока:
Вы можете нажать кнопку активации, чтобы перейти на страницу успеха:
Или отменить кнопка перехода на страницу отказа:
6. Заключение
«
In this article, we used a simple example as a guide on how to use Spring Web Flow.
You can find the complete source code and all code snippets for this article over on GitHub.