Содержание
Как и в предыдущей статье о Spring Web Flow, в данном примере используются вложенные flow. На этот раз их будет два: один отвечает за авторизацию пользователя, второй - за прохождение тестирования пользователем. Родительский flow управляет взаимодействием между вышеупомянутыми списками действий.
Листинг родительского tests-flow представлен ниже:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<on-start>
<evaluate expression="new com.seostella.swftests.domain.TestChecker()"
result="flowScope.testChecker" />
</on-start>
<subflow-state id="identifyUser" subflow="tests/user">
<output name="user" value="flowScope.testChecker.user"/>
<transition on="userReady" to="startTest" />
</subflow-state>
<subflow-state id="startTest" subflow="tests/test">
<output name="testList" value="flowScope.testChecker.testList"/>
<transition on="testsFinished" to="successResult" />
<transition on="testsFail" to="failResult" />
</subflow-state>
<view-state id="successResult">
<transition to="endState" />
</view-state>
<view-state id="failResult">
<transition to="endState" />
</view-state>
<end-state id="endState" />
</flow>
В предыдущих двух статьях о Spring Web Flow были рассмотренны все описанные в tests-flow.xml состояния, кроме одного - on-start. Как следует из названия, это состояние вызывается во время запуста test-flow.
Действие evaluate. Вы будете использовать его достаточно часто. Оно предназначено для выполнения выражения, указанного в атрибуте expression. Если Вас также интересует результат выполнения выражения, то необходимо указать атрибут result с названием переменной, в которую запишется результат. В нашем случае это flowScope.testChecker.
В вышеприведенном коде появилась "магическая" переменная flowScope. flowScope - это область видимости flow, в которую можно добавлять/изменять переменные. В Spring Web Flow есть еще несколько подобных сущностей: viewScope, requestScope, flashScope и др. Подробнее о них можно почитать на странице Spring Web Flow Reference Guide.
То есть, в flowScope будет записана вновь созданная переменная testChecker. Это мы делаем для того, чтобы у каждого нового пользователя при старте flow создавалось отдельное хранилище, отвечающее за информацию о пользователе и о проходимых им тестах.
Разберемся с первым subflow identifyUser:
<subflow-state id="identifyUser" subflow="tests/user">
<output name="user" value="flowScope.testChecker.user"/>
<transition on="userReady" to="startTest" />
</subflow-state>
Этот subflow предназначен для идентификации пользователя.
<output name="user" value="flowScope.testChecker.user"/>
- означает, что после того как пользователь будет идентифицирован (т.е., выполнение дочернего flow будет окончено), информация о нем запишется в переменную flowScope.testChecker.user.
<transition on="userReady" to="startTest" />
- по завершении выполнения identifyUser (достигнуто состояние userReady) управление передается состоянию startTest, которое отвечает за прохождение тестов пользователем.
<subflow-state id="startTest" subflow="tests/test">
<output name="testList" value="flowScope.testChecker.testList"/>
<transition on="testsFinished" to="successResult" />
<transition on="testsFail" to="failResult" />
</subflow-state>
Переходим к subflow под названием startTest. Его описание очень напоминает предыдущий identifyUser flow.
<output name="testList" value="flowScope.testChecker.testList"/>
- по окончании выполнения результат (а точнее, значение свойства testList) записывается в переменную flowScope.testChecker.testList.
<transition on="testsFinished" to="successResult" />
- по достижению конечного состояния testsFinished, управление передается состоянию successResult. Это успешное завершение тестирования, что означает, что было допущено меньше 3-х ошибок или ни одной ошибки.
<transition on="testsFail" to="failResult" />
- по достижению конечного состояния testsFail, управление передается состоянию failResult. В это состояние приложение переходит сразу же после третьего неправильного ответа.
В tests-flow осталось еще три состояния: два состояния-представления (successResult и failResult) и конечное состояние endState. Как стало известно из предыдущих статей о Spring Web Flow, для состояний-представлений должны быть одноименные jspx-файлы. Приведем исходники стриниц successResult.jspx и failResult.jspx:
<html xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:form="http://www.springframework.org/tags/form">
<jsp:output omit-xml-declaration="yes"/>
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<head><title>Tests - Spring Web Flow 2.x Tutorial | seostella.com</title></head>
<body>
<h1>Результыты тестов пользователя ${testChecker.user.name}</h1>
<p>Допущено ошибок: ${testChecker.testList.wrongAnswerCount}</p>
<c:forEach items="${testChecker.testList.tests}" var="test">
<li>${test.question} - ${test.userAnswerAsText}
<c:if test="${test.correctAnswer}">
(<font style="color: green">правильно</font>)
</c:if>
<c:if test="${!test.correctAnswer}">
(<font style="color: red">неправильно</font>)
</c:if>
</li>
</c:forEach>
</body>
</html>
<html xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:form="http://www.springframework.org/tags/form">
<jsp:output omit-xml-declaration="yes"/>
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<head><title>Tests - Spring Web Flow 2.x Tutorial | seostella.com</title></head>
<body>
<h1>Результыты тестов пользователя ${testChecker.user.name}</h1>
<p>Допущено ошибок: ${testChecker.testList.wrongAnswerCount}. Вы провалили тест.</p>
</body>
</html>
После успешного прохождения тестов пользователю отобразится страница successResult.jspx:
Рис 2. Успешное завершение тестирования
Если тесты будут провалены, то пользователь увидит страницу failResult.jspx:
Рис 3. Неуспешное завершение тестирования
< | Spring Web Flow. Тесты. Часть 2. Модель и Контроллер | Spring Web Flow. Тесты. Часть 4. Flow Авторизации | > |