提交 947ab7df 编写于 作者: 茶陵後's avatar 茶陵後 👍

#23 spring web fliow

上级 955531a6
# 6. Executing actions
## [](#actions-introduction)6.1. Introduction
## 6.1. Introduction
This chapter shows you how to use the `action-state` element to control the execution of an action at a point within a flow.
It will also show how to use the `decision-state` element to make a flow routing decision.
Finally, several examples of invoking actions from the various points possible within a flow will be discussed.
## [](#action-state)6.2. Defining action states
## 6.2. Defining action states
Use the `action-state` element when you wish to invoke an action, then transition to another state based on the action's outcome:
......@@ -65,7 +65,7 @@ state.
Note also that an action-state just like any other state can have one more on-entry actions
that are executed as a list from start to end.
## [](#decision-state)6.3. Defining decision states
## 6.3. Defining decision states
Use the `decision-state` element as an alternative to the action-state to make a routing decision using a convenient if/else syntax.
The example below shows the `moreAnswersNeeded` state above now implemented as a decision state instead of an action-state:
......@@ -77,14 +77,14 @@ The example below shows the `moreAnswersNeeded` state above now implemented as a
```
## [](#action-outcome-events)6.4. Action outcome event mappings
## 6.4. Action outcome event mappings
Actions often invoke methods on plain Java objects.
When called from action-states and decision-states, these method return values can be used to drive state transitions.
Since transitions are triggered by events, a method return value must first be mapped to an Event object.
The following table describes how common return value types are mapped to Event objects:
[](#event-mapping-table)
**Table 6.1. Action method return value to event id mappings**
......@@ -106,7 +106,7 @@ This is illustrated in the example action state below, which invokes a method th
```
## [](#action-implementations)6.5. Action implementations
## 6.5. Action implementations
While writing action code as POJO logic is the most common, there are several other action implementation options.
Sometimes you need to write action code that needs access to the flow context.
......@@ -115,7 +115,7 @@ Alternatively, you may implement the `Action` interface or extend from the `Mult
These options provide stronger type safety when you have a natural coupling between your action code and Spring Web Flow APIs.
Examples of each of these approaches are shown below.
### [](#d5e1045)6.5.1. Invoking a POJO action
### 6.5.1. Invoking a POJO action
```
<evaluate expression="pojoAction.method(flowRequestContext)" />
......@@ -131,7 +131,7 @@ public class PojoAction {
```
### [](#d5e1049)6.5.2. Invoking a custom Action implementation
### 6.5.2. Invoking a custom Action implementation
```
<evaluate expression="customAction" />
......@@ -147,7 +147,7 @@ public class CustomAction implements Action {
```
### [](#d5e1053)6.5.3. Invoking a MultiAction implementation
### 6.5.3. Invoking a MultiAction implementation
```
<evaluate expression="multiAction.actionMethod1" />
......@@ -170,12 +170,12 @@ public class CustomMultiAction extends MultiAction {
```
## [](#action-exceptions)6.6. Action exceptions
## 6.6. Action exceptions
Actions often invoke services that encapsulate complex business logic.
These services may throw business exceptions that the action code should handle.
### [](#d5e1060)6.6.1. Handling a business exception with a POJO action
### 6.6.1. Handling a business exception with a POJO action
The following example invokes an action that catches a business exception, adds a error message to the context, and returns a result event identifier.
The result is treated as a flow event which the calling flow can then respond to.
......@@ -202,7 +202,7 @@ public String makeBooking(Booking booking, RequestContext context) {
```
### [](#d5e1065)6.6.2. Handling a business exception with a MultiAction
### 6.6.2. Handling a business exception with a MultiAction
The following example is functionally equivlant to the last, but implemented as a MultiAction instead of a POJO action.
The MultiAction requires its action methods to be of the signature `Event ${methodName}(RequestContext)`, providing stronger type safety, while a POJO action allows for more freedom.
......@@ -230,16 +230,16 @@ public Event makeBooking(RequestContext context) {
```
### [](#d5e1071)6.6.3. Using an exception-handler element
### 6.6.3. Using an exception-handler element
In general it is recommended to catch exceptions in actions and return result
events that drive standard transitions, it is also possible to add an`exception-handler` sub-element to any state type with a`bean` attribute referencing a bean of type`FlowExecutionExceptionHandler`. This is an advanced
option that if used incorrectly can leave the flow execution in an invalid state.
Consider the build-in `TransitionExecutingFlowExecutionExceptionHandler`as example of a correct implementation.
## [](#action-examples)6.7. Other Action execution examples
## 6.7. Other Action execution examples
### [](#action-on-start)6.7.1. on-start
### 6.7.1. on-start
The following example shows an action that creates a new Booking object by invoking a method on a service:
......@@ -260,7 +260,7 @@ The following example shows an action that creates a new Booking object by invok
```
### [](#action-on-state-entry)6.7.2. on-entry
### 6.7.2. on-entry
The following example shows a state entry action that sets the special `fragments` variable that causes the view-state to render a partial fragment of its view:
......@@ -273,7 +273,7 @@ The following example shows a state entry action that sets the special `fragment
```
### [](#action-on-state-exit)6.7.3. on-exit
### 6.7.3. on-exit
The following example shows a state exit action that releases a lock on a record being edited:
......@@ -293,7 +293,7 @@ The following example shows a state exit action that releases a lock on a record
```
### [](#on-end)6.7.4. on-end
### 6.7.4. on-end
The following example shows the equivalent object locking behavior using flow start and end actions:
......@@ -324,7 +324,7 @@ The following example shows the equivalent object locking behavior using flow st
```
### [](#action-on-render)6.7.5. on-render
### 6.7.5. on-render
The following example shows a render action that loads a list of hotels to display before the view is rendered:
......@@ -341,7 +341,7 @@ The following example shows a render action that loads a list of hotels to displ
```
### [](#action-on-transition)6.7.6. on-transition
### 6.7.6. on-transition
The following example shows a transition action adds a subflow outcome event attribute to a collection:
......@@ -354,7 +354,7 @@ The following example shows a transition action adds a subflow outcome event att
```
### [](#named-actions)6.7.7. Named actions
### 6.7.7. Named actions
The following example shows how to execute a chain of actions in an action-state.
The name of each action becomes a qualifier for the action's result event.
......@@ -374,7 +374,7 @@ The name of each action becomes a qualifier for the action's result event.
In this example, the flow will transition to `showResults` when `thingTwo`completes successfully.
### [](#streaming-actions)6.7.8. Streaming actions
### 6.7.8. Streaming actions
Sometimes an Action needs to stream a custom response back to the client.
An example might be a flow that renders a PDF document when handling a print event.
......@@ -405,7 +405,7 @@ public class PrintBoardingPassAction extends AbstractAction {
In this example, when the print event is raised the flow will call the printBoardingPassAction.
The action will render the PDF then mark the response as complete.
### [](#file-upload)6.7.9. Handling File Uploads
### 6.7.9. Handling File Uploads
Another common task is to use Web Flow to handle multipart file uploads in combination with Spring MVC's`MultipartResolver`. Once the resolver is set up correctly [as described here](http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html#mvc-multipart) and the submitting
HTML form is configured with `enctype="multipart/form-data"`, you can easily handle the file upload in a
......
# 3. Defining Flows
## [](#defining-flows-introduction)3.1. Introduction
## 3.1. Introduction
This chapter begins the Users Section.
It shows how to implement flows using the flow definition language.
By the end of this chapter you should have a good understanding of language constructs, and be capable of authoring a flow definition.
## [](#flow-overview)3.2. What is a flow?
## 3.2. What is a flow?
A flow encapsulates a reusable sequence of steps that can execute in different contexts.
Below is a [Garrett Information Architecture](http://www.jjg.net/ia/visvocab/) diagram illustrating a reference to a flow that encapsulates the steps of a hotel booking process:
......@@ -15,7 +15,7 @@ Below is a [Garrett Information Architecture](http://www.jjg.net/ia/visvocab/) d
Site Map illustrating a reference to a flow
## [](#flow-makeup)3.3. What is the makeup of a typical flow?
## 3.3. What is the makeup of a typical flow?
In Spring Web Flow, a flow consists of a series of steps called "states".
Entering a state typically results in a view being displayed to the user.
......@@ -28,14 +28,14 @@ The example below shows the structure of the book hotel flow referenced in the p
Flow diagram
## [](#flow-authoring)3.4. How are flows authored?
## 3.4. How are flows authored?
Flows are authored by web application developers using a simple XML-based flow definition language.
The next steps of this guide will walk you through the elements of this language.
## [](#essential-flow-elements)3.5. Essential language elements
## 3.5. Essential language elements
### [](#flow-element)3.5.1. flow
### 3.5.1. flow
Every flow begins with the following root element:
......@@ -53,7 +53,7 @@ Every flow begins with the following root element:
All states of the flow are defined within this element.
The first state defined becomes the flow's starting point.
### [](#view-state-element)3.5.2. view-state
### 3.5.2. view-state
Use the `view-state` element to define a step of the flow that renders a view:
......@@ -65,7 +65,7 @@ Use the `view-state` element to define a step of the flow that renders a view:
By convention, a view-state maps its id to a view template in the directory where the flow is located.
For example, the state above might render `/WEB-INF/hotels/booking/enterBookingDetails.xhtml`if the flow itself was located in the `/WEB-INF/hotels/booking` directory.
### [](#transition-element)3.5.3. transition
### 3.5.3. transition
Use the `transition` element to handle events that occur within a state:
......@@ -78,7 +78,7 @@ Use the `transition` element to handle events that occur within a state:
These transitions drive view navigations.
### [](#end-state-element)3.5.4. end-state
### 3.5.4. end-state
Use the `end-state` element to define a flow outcome:
......@@ -89,7 +89,7 @@ Use the `end-state` element to define a flow outcome:
When a flow transitions to a end-state it terminates and the outcome is returned.
### [](#checkpoint-essential-language-elements)3.5.5. Checkpoint: Essential language elements
### 3.5.5. Checkpoint: Essential language elements
With the three elements `view-state`, `transition`, and `end-state`, you can quickly express your view navigation logic.
Teams often do this before adding flow behaviors so they can focus on developing the user interface of the application with end users first.
......@@ -119,7 +119,7 @@ Below is a sample flow that implements its view navigation logic using these ele
```
## [](#flow-actions)3.6. Actions
## 3.6. Actions
Most flows need to express more than just view navigation logic.
Typically they also need to invoke business services of the application or other actions.
......@@ -141,7 +141,7 @@ Within a flow, there are several points where you can execute actions. These poi
Actions are defined using a concise expression language. Spring Web Flow uses the Unified EL by default.
The next few sections will cover the essential language elements for defining actions.
### [](#evaluate-element)3.6.1. evaluate
### 3.6.1. evaluate
The action element you will use most often is the `evaluate` element.
Use the `evaluate` element to evaluate an expression at a point within your flow.
......@@ -153,7 +153,7 @@ For example:
```
#### [](#evaluate-element-result)Assigning an evaluate result
#### Assigning an evaluate result
If the expression returns a value, that value can be saved in the flow's data model called `flowScope`:
......@@ -162,7 +162,7 @@ If the expression returns a value, that value can be saved in the flow's data mo
```
#### [](#evaluate-element-result-type)Converting an evaluate result
#### Converting an evaluate result
If the expression returns a value that may need to be converted, specify the desired type using the `result-type` attribute:
......@@ -172,7 +172,7 @@ If the expression returns a value that may need to be converted, specify the des
```
### [](#checkpoint-actions)3.6.2. Checkpoint: flow actions
### 3.6.2. Checkpoint: flow actions
Now review the sample booking flow with actions added:
......@@ -210,7 +210,7 @@ Now review the sample booking flow with actions added:
This flow now creates a Booking object in flow scope when it starts.
The id of the hotel to book is obtained from a flow input attribute.
## [](#flow-inputoutput)3.7. Input/Output Mapping
## 3.7. Input/Output Mapping
Each flow has a well-defined input/output contract.
Flows can be passed input attributes when they start, and can return output attributes when they end.
......@@ -231,7 +231,7 @@ public interface FlowOutcome {
```
### [](#input-element)3.7.1. input
### 3.7.1. input
Use the `input` element to declare a flow input attribute:
......@@ -243,7 +243,7 @@ Use the `input` element to declare a flow input attribute:
Input values are saved in flow scope under the name of the attribute.
For example, the input above would be saved under the name `hotelId`.
#### [](#input-element-type)Declaring an input type
#### Declaring an input type
Use the `type` attribute to declare the input attribute's type:
......@@ -254,7 +254,7 @@ Use the `type` attribute to declare the input attribute's type:
If an input value does not match the declared type, a type conversion will be attempted.
#### [](#input-element-value)Assigning an input value
#### Assigning an input value
Use the `value` attribute to specify an expression to assign the input value to:
......@@ -265,7 +265,7 @@ Use the `value` attribute to specify an expression to assign the input value to:
If the expression's value type can be determined, that metadata will be used for type coersion if no `type` attribute is specified.
#### [](#input-element-required)Marking an input as required
#### Marking an input as required
Use the `required` attribute to enforce the input is not null or empty:
......@@ -274,7 +274,7 @@ Use the `required` attribute to enforce the input is not null or empty:
```
### [](#output-element)3.7.2. output
### 3.7.2. output
Use the `output` element to declare a flow output attribute.
Output attributes are declared within end-states that represent specific flow outcomes.
......@@ -289,7 +289,7 @@ Output attributes are declared within end-states that represent specific flow ou
Output values are obtained from flow scope under the name of the attribute.
For example, the output above would be assigned the value of the `bookingId` variable.
#### [](#output-element-value)Specifying the source of an output value
#### Specifying the source of an output value
Use the `value` attribute to denote a specific output value expression:
......@@ -298,7 +298,7 @@ Use the `value` attribute to denote a specific output value expression:
```
### [](#checkpoint-input-output)3.7.3. Checkpoint: input/output mapping
### 3.7.3. Checkpoint: input/output mapping
Now review the sample booking flow with input/output mapping:
......@@ -338,13 +338,13 @@ Now review the sample booking flow with input/output mapping:
The flow now accepts a `hotelId` input attribute and returns a `bookingId` output attribute
when a new booking is confirmed.
## [](#flow-variables)3.8. Variables
## 3.8. Variables
A flow may declare one or more instance variables.
These variables are allocated when the flow starts.
Any `@Autowired` transient references the variable holds are also rewired when the flow resumes.
### [](#var-element)3.8.1. var
### 3.8.1. var
Use the `var` element to declare a flow variable:
......@@ -355,31 +355,31 @@ Use the `var` element to declare a flow variable:
Make sure your variable's class implements `java.io.Serializable`, as the instance state is saved between flow requests.
## [](#scopes)3.9. Variable Scopes
## 3.9. Variable Scopes
Web Flow can store variables in one of several scopes:
### [](#d5e398)3.9.1. Flow Scope
### 3.9.1. Flow Scope
Flow scope gets allocated when a flow starts and destroyed when the flow ends.
With the default implementation, any objects stored in flow scope need to be Serializable.
### [](#d5e401)3.9.2. View Scope
### 3.9.2. View Scope
View scope gets allocated when a `view-state` enters and destroyed when the state exits.
View scope is *only* referenceable from within a `view-state`. With the
default implementation, any objects stored in view scope need to be Serializable.
### [](#d5e407)3.9.3. Request Scope
### 3.9.3. Request Scope
Request scope gets allocated when a flow is called and destroyed when the flow returns.
### [](#d5e410)3.9.4. Flash Scope
### 3.9.4. Flash Scope
Flash scope gets allocated when a flow starts, cleared after every view render, and destroyed when the
flow ends. With the default implementation, any objects stored in flash scope need to be Serializable.
### [](#d5e413)3.9.5. Conversation Scope
### 3.9.5. Conversation Scope
Conversation scope gets allocated when a top-level flow starts and destroyed when the top-level flow ends.
Conversation scope is shared by a top-level flow and all of its subflows. With the default
......@@ -392,11 +392,11 @@ a view state (view scope), etc. In other cases, for example in EL expressions an
Java code, it needs to be specified explicitly. Subsequent sections explain
how this is done.
## [](#calling-subflows)3.10. Calling subflows
## 3.10. Calling subflows
A flow may call another flow as a subflow. The flow will wait until the subflow returns, then respond to the subflow outcome.
### [](#subflow-state-element)3.10.1. subflow-state
### 3.10.1. subflow-state
Use the `subflow-state` element to call another flow as a subflow:
......@@ -413,7 +413,7 @@ Use the `subflow-state` element to call another flow as a subflow:
The above example calls the `createGuest` flow, then waits for it to return.
When the flow returns with a `guestCreated` outcome, the new guest is added to the booking's guest list.
#### [](#subflow-state-element-input)Passing a subflow input
#### Passing a subflow input
Use the `input` element to pass input to the subflow:
......@@ -425,7 +425,7 @@ Use the `input` element to pass input to the subflow:
```
#### [](#subflow-state-element-output)Mapping subflow output
#### Mapping subflow output
When a subflow completes, its end-state id is returned to the calling flow as
the event to use to continue navigation.
......@@ -442,7 +442,7 @@ within an outcome transition as follows:
In the above example, `guest` is the name of an output attribute returned by the `guestCreated` outcome.
### [](#checkpoint-subflow)3.10.2. Checkpoint: calling subflows
### 3.10.2. Checkpoint: calling subflows
Now review the sample booking flow calling a subflow:
......
# 4. Expression Language (EL)
## [](#el-introduction)4.1. Introduction
## 4.1. Introduction
Web Flow uses EL to access its data model and to invoke actions.
This chapter will familiarize you with EL syntax, configuration, and special EL variables you can reference from your flow definition.
......@@ -18,11 +18,11 @@ EL is used for many things within a flow including:
EL is also used to bind form parameters to model objects and reversely to render formatted form fields from the properties of a model object.
That however does not apply when using Web Flow with JSF in which case the standard JSF component lifecyle applies.
### [](#el-types)4.1.1. Expression types
### 4.1.1. Expression types
An important concept to understand is there are two types of expressions in Web Flow: standard expressions and template expressions.
#### [](#el-types-eval)Standard Expressions
#### Standard Expressions
The first and most common type of expression is the *standard expression*.
Such expressions are evaluated directly by the EL and need not be enclosed in delimiters like `#{}`.
......@@ -38,7 +38,7 @@ If you attempt to enclose this expression in a special delimiter like `#{}` you
In this context the delimiter is seen as redundant.
The only acceptable value for the `expression` attribute is an single expression string.
#### [](#el-types-template)Template expressions
#### Template expressions
The second type of expression is a *template expression*.
A template expression allows mixing of literal text with one or more standard expressions.
......@@ -58,15 +58,15 @@ As you can see, explicit delimiters are necessary here to demarcate standard exp
|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|See the Web Flow XML schema for a complete listing of those XML attributes that accept standard expressions and those that accept template expressions.<br/>You can also use F2 in Eclipse (or equivalent shortcut in other IDEs) to access available documentation when typing out specific flow definition attributes.| |
## [](#el-language-choices)4.2. EL Implementations
## 4.2. EL Implementations
### [](#el-spring-el)4.2.1. Spring EL
### 4.2.1. Spring EL
Web Flow uses the [Spring Expression Language](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html) (Spring EL).
Spring EL was created to provide a single, well-supported expression language for use across all the products in the Spring portfolio.
It is distributed as a separate jar `org.springframework.expression` in the Spring Framework.
### [](#el-unified-el)4.2.2. Unified EL
### 4.2.2. Unified EL
Use of [Unified EL](https://en.wikipedia.org/wiki/Unified_Expression_Language)also implies a dependency on `el-api` although that is typically *provided*by your web container.
Although Spring EL is the default and recommended expression language to use,
......@@ -100,7 +100,7 @@ Note that if your application is registering custom converters it's important to
```
## [](#el-portability)4.3. EL portability
## 4.3. EL portability
In general, you will find Spring EL and Unified EL to have a very similar syntax.
......@@ -119,7 +119,7 @@ There are some minor changes to keep in mind when upgrading to Spring EL from Un
For more information on Spring EL syntax please refer to the [Language Reference](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-language-ref) section in the Spring Documentation.
## [](#el-variables)4.4. Special EL variables
## 4.4. Special EL variables
There are several implicit variables you may reference from within a flow.
These variables are discussed in this section.
......@@ -165,7 +165,7 @@ However when setting an existing variable such as "searchCriteria" in the exampl
The following is the list of implicit variables you can reference within a flow definition:
### [](#el-variable-flowScope)4.4.1. flowScope
### 4.4.1. flowScope
Use `flowScope` to assign a flow variable.
Flow scope gets allocated when a flow starts and destroyed when the flow ends. With the default
......@@ -176,7 +176,7 @@ implementation, any objects stored in flow scope need to be Serializable.
```
### [](#el-variable-viewScope)4.4.2. viewScope
### 4.4.2. viewScope
Use `viewScope` to assign a view variable.
View scope gets allocated when a `view-state` enters and destroyed when the state exits.
......@@ -191,7 +191,7 @@ default implementation, any objects stored in view scope need to be Serializable
```
### [](#el-variable-requestScope)4.4.3. requestScope
### 4.4.3. requestScope
Use `requestScope` to assign a request variable.
Request scope gets allocated when a flow is called and destroyed when the flow returns.
......@@ -201,7 +201,7 @@ Request scope gets allocated when a flow is called and destroyed when the flow r
```
### [](#el-variable-flashScope)4.4.4. flashScope
### 4.4.4. flashScope
Use `flashScope` to assign a flash variable.
Flash scope gets allocated when a flow starts, cleared after every view render, and destroyed when the
......@@ -212,7 +212,7 @@ flow ends. With the default implementation, any objects stored in flash scope ne
```
### [](#el-variable-conversationScope)4.4.5. conversationScope
### 4.4.5. conversationScope
Use `conversationScope` to assign a conversation variable.
Conversation scope gets allocated when a top-level flow starts and destroyed when the top-level flow ends.
......@@ -225,7 +225,7 @@ Serializable to account for typical session replication.
```
### [](#el-variable-requestParameters)4.4.6. requestParameters
### 4.4.6. requestParameters
Use `requestParameters` to access a client request parameter:
......@@ -234,7 +234,7 @@ Use `requestParameters` to access a client request parameter:
```
### [](#el-variable-currentEvent)4.4.7. currentEvent
### 4.4.7. currentEvent
Use `currentEvent` to access attributes of the current `Event`:
......@@ -243,7 +243,7 @@ Use `currentEvent` to access attributes of the current `Event`:
```
### [](#el-variable-currentUser)4.4.8. currentUser
### 4.4.8. currentUser
Use `currentUser` to access the authenticated `Principal`:
......@@ -253,7 +253,7 @@ Use `currentUser` to access the authenticated `Principal`:
```
### [](#el-variable-messageContext)4.4.9. messageContext
### 4.4.9. messageContext
Use `messageContext` to access a context for retrieving and creating flow execution messages, including error and success messages.
See the `MessageContext` Javadocs for more information.
......@@ -263,7 +263,7 @@ See the `MessageContext` Javadocs for more information.
```
### [](#el-variable-resourceBundle)4.4.10. resourceBundle
### 4.4.10. resourceBundle
Use `resourceBundle` to access a message resource.
......@@ -272,21 +272,21 @@ Use `resourceBundle` to access a message resource.
```
### [](#el-variable-requestContext)4.4.11. flowRequestContext
### 4.4.11. flowRequestContext
Use `flowRequestContext` to access the `RequestContext` API, which is a representation of the current flow request.
See the API Javadocs for more information.
### [](#el-variable-flowExecutionContext)4.4.12. flowExecutionContext
### 4.4.12. flowExecutionContext
Use `flowExecutionContext` to access the `FlowExecutionContext` API, which is a representation of the current flow state.
See the API Javadocs for more information.
### [](#el-variable-flowExecutionUrl)4.4.13. flowExecutionUrl
### 4.4.13. flowExecutionUrl
Use `flowExecutionUrl` to access the context-relative URI for the current flow execution view-state.
### [](#el-variable-externalContext)4.4.14. externalContext
### 4.4.14. externalContext
Use `externalContext` to access the client environment, including user session attributes.
See the `ExternalContext` API JavaDocs for more information.
......@@ -297,7 +297,7 @@ See the `ExternalContext` API JavaDocs for more information.
```
## [](#el-scope-searching)4.5. Scope searching algorithm
## 4.5. Scope searching algorithm
As mentioned earlier in this section when assigning a variable in one of the flow scopes, referencing that scope is required.
For example:
......
......@@ -5,7 +5,7 @@ This is a listing of the language elements in the 1.0 release, and how they map
While most of the changes are semantic, there are a few structural changes.
Please see the upgrade guide for more details about changes between Web Flow 1.0 and 2.0.
[](#field-mappings-table)
**Table A.1. Mappings**
......
# 9. Flow Inheritance
## [](#flow-inheritance-introduction)9.1. Introduction
## 9.1. Introduction
Flow inheritance allows one flow to inherit the configuration of another flow.
Inheritance can occur at both the flow and state levels.
......@@ -8,7 +8,7 @@ A common use case is for a parent flow to define global transitions and exceptio
In order for a parent flow to be found, it must be added to the `flow-registry` just like any other flow.
## [](#flow-inheritance-java-comparison)9.2. Is flow inheritance like Java inheritance?
## 9.2. Is flow inheritance like Java inheritance?
Flow inheritance is similar to Java inheritance in that elements defined in a parent are exposed via the child, however, there are key differences.
......@@ -19,9 +19,9 @@ Unique elements in the parent flow will be added to the child.
A child flow can inherit from multiple parent flows.
Java inheritance is limited to a single class.
## [](#flow-inheritance-levels)9.3. Types of Flow Inheritance
## 9.3. Types of Flow Inheritance
### [](#flow-inheritance-level-flow)9.3.1. Flow level inheritance
### 9.3.1. Flow level inheritance
Flow level inheritance is defined by the `parent` attribute on the `flow` element.
The attribute contains a comma separated list of flow identifiers to inherit from.
......@@ -33,7 +33,7 @@ The resulting flow from the first merge will be considered the child in the seco
```
### [](#flow-inheritance-level-state)9.3.2. State level inheritance
### 9.3.2. State level inheritance
State level inheritance is similar to flow level inheritance, except only one state inherits from the parent, instead of the entire flow.
......@@ -53,7 +53,7 @@ For instance a view-state cannot inherit from an end-state, only another view-st
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|The intent for flow-level inheritance is to define common states to be<br/>added to and shared among multiple flow definitions while the intent<br/>for state-level inheritance is to extend from and merge with a single<br/>parent state. Flow-level inheritance is a good fit for composition<br/>and multiple inheritance but at the state level you can still only<br/>inherit from a single parent state.| |
## [](#flow-inheritance-abstract)9.4. Abstract flows
## 9.4. Abstract flows
Often parent flows are not designed to be executed directly.
In order to protect these flows from running, they can be marked as `abstract`.
......@@ -64,7 +64,7 @@ If an abstract flow attempts to run, a `FlowBuilderException` will be thrown.
```
## [](#flow-inheritance-algorithm)9.5. Inheritance Algorithm
## 9.5. Inheritance Algorithm
When a child flow inherits from it's parent, essentially what happens is that the parent and child are merged together to create a new flow.
There are rules for every element in the Web Flow definition language that govern how that particular element is merged.
......@@ -78,7 +78,7 @@ They will not be modified as part of the merge process.
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|Paths to external resources in the parent flow should be absolute.<br/>Relative paths will break when the two flows are merged unless the parent and child flow are in the same directory.<br/>Once merged, all relative paths in the parent flow will become relative to the child flow.| |
### [](#flow-inheritance-algorithm-mergeable)9.5.1. Mergeable Elements
### 9.5.1. Mergeable Elements
If the elements are of the same type and their keyed attribute are identical, the content of the parent element will be merged with the child element.
The merge algorithm will continue to merge each sub-element of the merging parent and child.
......@@ -124,7 +124,7 @@ Mergeable elements are:
* view-state: id
### [](#flow-inheritance-nonmergeable)9.5.2. Non-mergeable Elements
### 9.5.2. Non-mergeable Elements
Non-mergeable elements are:
......
# 7. Flow Managed Persistence
## [](#flow-managed-persistence-introduction)7.1. Introduction
## 7.1. Introduction
Most applications access data in some way.
Many modify data shared by multiple users and therefore require transactional data access properties.
......@@ -12,7 +12,7 @@ Apart from flow-managed persistence, there is the pattern of fully encapsulating
In that case, the web layer does not get involved with persistence, instead it works entirely with detached objects that are passed to and returned by your service layer.
This chapter will focus on the flow-managed persistence, exploring how and when to use this feature.
## [](#flowScopedPersistenceContext)7.2. FlowScoped PersistenceContext
## 7.2. FlowScoped PersistenceContext
This pattern creates a `PersistenceContext` in `flowScope` on flow startup,
uses that context for data access during the course of flow execution, and commits changes made to persistent entities at the end.
......@@ -67,7 +67,7 @@ Reference this EntityManager at anytime from within your flow by using the speci
In addition, any data access that occurs using a Spring managed data access object will use this EntityManager automatically.
Such data access operations should always execute non transactionally or in read-only transactions to maintain isolation of intermediate edits.
## [](#flow-managed-persistence-propagation)7.3. Flow Managed Persistence And Sub-Flows
## 7.3. Flow Managed Persistence And Sub-Flows
A flow managed `PersistenceContext` is automatically extended
(propagated) to subflows assuming the subflow also has the `<perstistence-context/>`variable. When a subflow re-uses the `PersistenceContext` started by its parent it ignores
......
# 8. Securing Flows
## [](#flow-security-introduction)8.1. Introduction
## 8.1. Introduction
Security is an important concept for any application.
End users should not be able to access any portion of a site simply by guessing the URL.
......@@ -8,7 +8,7 @@ Areas of a site that are sensitive must ensure that only authorized requests are
Spring Security is a proven security platform that can integrate with your application at multiple levels.
This section will focus on securing flow execution.
## [](#flow-security-how-to)8.2. How do I secure a flow?
## 8.2. How do I secure a flow?
Securing flow execution is a three step process:
......@@ -20,7 +20,7 @@ Securing flow execution is a three step process:
Each of these steps must be completed or else flow security rules will not be applied.
## [](#flow-security-secured-element)8.3. The secured element
## 8.3. The secured element
The secured element designates that its containing element should apply the authorization check before fully entering.
This may not occur more then once per stage of the flow execution that is secured.
......@@ -38,7 +38,7 @@ For example, to secure a state the secured element occurs directly inside that s
```
### [](#flow-security-secured-element-attributes)8.3.1. Security attributes
### 8.3.1. Security attributes
The `attributes` attribute is a comma separated list of Spring Security authorization attributes.
Often, these are specific security roles.
......@@ -52,7 +52,7 @@ The attributes are compared against the user's granted attributes by a Spring Se
By default, a role based access decision manager is used to determine if the user is allowed access.
This will need to be overridden if your application is not using authorization roles.
### [](#flow-security-secured-element-match)8.3.2. Matching type
### 8.3.2. Matching type
There are two types of matching available: `any` and `all`.
Any, allows access if at least one of the required security attributes is granted to the user.
......@@ -68,7 +68,7 @@ If not defined, the default value is `any`.
The `match` attribute will only be respected if the default access decision manager is used.
## [](#flow-security-listener)8.4. The SecurityFlowExecutionListener
## 8.4. The SecurityFlowExecutionListener
Defining security rules in the flow by themselves will not protect the flow execution.
A `SecurityFlowExecutionListener` must also be defined in the webflow configuration and applied to the flow executor.
......@@ -89,7 +89,7 @@ If access is denied to a portion of the application an `AccessDeniedException` w
This exception will later be caught by Spring Security and used to prompt the user to authenticate.
It is important that this exception be allowed to travel up the execution stack uninhibited, otherwise the end user may not be prompted to authenticate.
### [](#flow-security-listener-adm)8.4.1. Custom Access Decision Managers
### 8.4.1. Custom Access Decision Managers
If your application is using authorities that are not role based, you will need to configure a custom `AccessDecisionManager`.
You can override the default decision manager by setting the `accessDecisionManager` property on the security listener.
......@@ -103,7 +103,7 @@ Please consult the [Spring Security reference documentation](http://static.sprin
```
## [](#flow-security-configuration)8.5. Configuring Spring Security
## 8.5. Configuring Spring Security
Spring Security has robust configuration options available.
As every application and environment has its own security requirements, the [Spring Security reference documentation](http://static.springframework.org/spring-security/site/reference.html) is the best place to learn the available options.
......@@ -111,7 +111,7 @@ As every application and environment has its own security requirements, the [Spr
Both the `booking-faces` and `booking-mvc` sample applications are configured to use Spring Security.
Configuration is needed at both the Spring and web.xml levels.
### [](#flow-security-configuration-spring)8.5.1. Spring configuration
### 8.5.1. Spring configuration
The Spring configuration defines `http` specifics (such as protected URLs and login/logout mechanics) and the `authentication-provider`.
For the sample applications, a local authentication provider is configured.
......@@ -141,7 +141,7 @@ For the sample applications, a local authentication provider is configured.
```
### [](#flow-security-configuration-web)8.5.2. web.xml Configuration
### 8.5.2. web.xml Configuration
In the `web.xml` file, a `filter` is defined to intercept all requests.
This filter will listen for login/logout requests and process them accordingly.
......
# 1. Introduction
## [](#manual-overview)1.1. What this guide covers
## 1.1. What this guide covers
This guide covers all aspects of Spring Web Flow.
It covers implementing flows in end-user applications and working with the feature set.
It also covers extending the framework and the overall architectural model.
## [](#system-requirements)1.2. What Web Flow requires to run
## 1.2. What Web Flow requires to run
Java 1.8 or higher.
Spring 5.0 or higher.
## [](#resources)1.3. Resources
## 1.3. Resources
You can ask questions and interact on StackOverflow using the designated tags,
see [Spring at StackOverflow](https://spring.io/questions).
......@@ -22,7 +22,7 @@ Report bugs and make requests using the[Spring Issue Tracker](https://jira.sprin
Submit pull requests and work with the source code ,
see [Web Flow on Github](https://github.com/spring-projects/spring-webflow).
## [](#jars-mvn-central)1.4. How to access Web Flow artifacts from Maven Central
## 1.4. How to access Web Flow artifacts from Maven Central
Each jar in the Web Flow distribution is available in the [Maven Central Repository](https://search.maven.org).
This allows you to easily integrate Web Flow into your application if you are already using Maven as the
......@@ -53,12 +53,12 @@ If using JavaServer Faces, declare the following dependency in your pom
```
## [](#d5e66)1.5. How to access nightly builds and milestone releases
## 1.5. How to access nightly builds and milestone releases
Nightly snapshots of Web Flow development branches are available using Maven.
These snapshot builds are useful for testing out fixes you depend on in advance of the next release, and provide a convenient way for you to provide feedback about whether a fix meets your needs.
### [](#d5e69)1.5.1. Accessing snapshots and milestones with Maven
### 1.5.1. Accessing snapshots and milestones with Maven
For milestones and snapshots you'll need to use the SpringSource repository.
Add the following repository to your Maven pom.xml:
......
# 13. JSF Integration
## [](#spring-faces-introduction)13.1. Introduction
## 13.1. Introduction
Spring Web Flow provides a JSF integration that lets you use the JSF UI
Component Model with Spring Web Flow controllers. Web Flow also provides
......@@ -9,7 +9,7 @@ see [Section 13.9, “Using the Spring Security Facelets Tag Library”](spring
Spring Web Flow 2.5 requires JSF 2.2 or higher.
## [](#spring-faces-config-web.xml)13.2. Configuring web.xml
## 13.2. Configuring web.xml
The first step is to route requests to the`DispatcherServlet` in the `web.xml` file. In this
example, we map all URLs that begin with `/spring/` to the
......@@ -68,7 +68,7 @@ web.xml:
```
## [](#spring-faces-webflow-config)13.3. Configuring Web Flow for use with JSF
## 13.3. Configuring Web Flow for use with JSF
This section explains how to configure Web Flow with JSF.
Both Java and XML style configuration are supported.
......@@ -171,7 +171,7 @@ initializes itself with a `JsfAjaxHandler` instead of the`SpringJavaSciprtAjaxHa
When using Java config, the `AbstractFacesFlowConfiguration`base class automatically registers `JsfResourceRequestHandler`so there is nothing further to do.
## [](#spring-faces-managed-beans)13.4. Replacing the JSF Managed Bean Facility
## 13.4. Replacing the JSF Managed Bean Facility
When using JSF with Spring Web Flow you can completely replace the
JSF managed bean facility with a combination of Web Flow managed variables
......@@ -195,7 +195,7 @@ flow, and conversation scopes. These scopes are seamlessly integrated
through JSF variable resolvers and work the same in all JSF
applications.
### [](#spring-faces-flow-variables)13.4.1. Using Flow Variables
### 13.4.1. Using Flow Variables
The easiest and most natural way to declare and manage the model
is through the use of [flow
......@@ -237,7 +237,7 @@ To define a view instance variable, you can use the`var` element inside a `view-
```
### [](#spring-faces-spring-beans)13.4.2. Using Scoped Spring Beans
### 13.4.2. Using Scoped Spring Beans
Though defining autowired flow instance variables provides nice
modularization and readability, occasions may arise where you want to
......@@ -255,7 +255,7 @@ be fully initialized until it is first accessed via an EL expression.
This sort of lazy instantiation via EL is quite similar to how JSF
managed beans are typically allocated.
### [](#faces-manipulating-model)13.4.3. Manipulating The Model
### 13.4.3. Manipulating The Model
The need to initialize the model before view rendering (such as by
loading persistent entities from a database) is quite common, but JSF by
......@@ -296,7 +296,7 @@ component:
```
### [](#faces-data-model-implementations)13.4.4. Data Model Implementations
### 13.4.4. Data Model Implementations
In the example above result-type="dataModel" results in the
wrapping of List\<Booking\> with custom`DataModel` type. The custom`DataModel` provides extra conveniences such as
......@@ -325,7 +325,7 @@ causes the `DataModelConverter` to be used. The
converter then wraps the given List with an instance of`OneSelectionTrackingListDataModel`. To use the`ManySelectionTrackingListDataModel` you will need
to register your own custom converter.
## [](#spring-faces-event-handling)13.5. Handling JSF Events With Spring Web Flow
## 13.5. Handling JSF Events With Spring Web Flow
Spring Web Flow allows you to handle JSF action events in a
decoupled way, requiring no direct dependencies in your Java code on JSF
......@@ -336,7 +336,7 @@ manipulated in wiring up events (JSF view templates and SWF flow
definitions) are instantly refreshable without requiring a build and
re-deploy of the whole application.
### [](#spring-faces-in-page-events)13.5.1. Handling JSF In-page Action Events
### 13.5.1. Handling JSF In-page Action Events
A simple but common case in JSF is the need to signal an event
that causes manipulation of the model in some way and then redisplays
......@@ -389,7 +389,7 @@ results to be loaded into the DataModel. The same view is re-rendered
since there was no `to` attribute on the`transition` element, and the changes in the model are
reflected in the view.
### [](#spring-faces-action-events)13.5.2. Handling JSF Action Events
### 13.5.2. Handling JSF Action Events
The next logical level beyond in-page events are events that
require navigation to another view, with some manipulation of the model
......@@ -432,7 +432,7 @@ Here the "select" event is handled by pushing the currently
selected hotel instance from the DataTable into flow scope, so that it
may be referenced by the "reviewHotel" `view-state` .
### [](#spring-faces-model-validation)13.5.3. Performing Model Validation
### 13.5.3. Performing Model Validation
JSF provides useful facilities for validating input at field-level
before changes are applied to the model, but when you need to then
......@@ -467,7 +467,7 @@ validation method on the booking instance, passing the generic`MessageContext` i
The messages can then be displayed along with any other JSF messages
with the `h:messages` component,
### [](#spring-faces-ajax-events-jsf2)13.5.4. Handling Ajax Events In JSF
### 13.5.4. Handling Ajax Events In JSF
JSF provides built-in support for sending Ajax requests and
performing partial processing and rendering on the server-side. You can
......@@ -492,7 +492,7 @@ action:
```
## [](#spring-faces-embedded-mode)13.6. Embedding a Flow On a Page
## 13.6. Embedding a Flow On a Page
By default when a flow enters a view state, it executes a
client-side redirect before rendering the view. This approach is known as
......@@ -540,7 +540,7 @@ mvn package
The specific example you need to look at is under the "Advanced Ajax"
tab and is called "Top Flow with Embedded Sub-Flow".
## [](#spring-faces-redirect-in-same-state)13.7. Redirect In Same State
## 13.7. Redirect In Same State
By default Web Flow does a client-side redirect even it it remains in the same view state as long as the current request is not an Ajax request.
This is quite useful after form validation failures for example.
......@@ -563,7 +563,7 @@ However if you experience this issue you can disable client-side redirects withi
```
## [](#spring-faces-file-upload)13.8. Handling File Uploads with JSF
## 13.8. Handling File Uploads with JSF
Most JSF component providers include some form of 'file upload' component. Generally when working
with these components JSF must take complete control of parsing multi-part requests and Spring MVC's`MultipartResolver` cannot be used.
......@@ -571,7 +571,7 @@ with these components JSF must take complete control of parsing multi-part reque
Spring Web Flow has been tested with file upload components from PrimeFaces. Check the
documentation of your JSF component library for other providers to see how to configure file upload.
### [](#d5e1950)13.8.1. File Uploads with PrimeFaces
### 13.8.1. File Uploads with PrimeFaces
PrimeFaces provides a `<p:fileUpload>` component for uploading files. In order
to use the component you need to configure the `org.primefaces.webapp.filter.FileUploadFilter`servlet filter. The filter needs to be configured against Spring MVC's`DispatcherServlet` in your `web.xml`:
......@@ -595,7 +595,7 @@ to use the component you need to configure the `org.primefaces.webapp.filter.Fil
For more details refer to the[PrimeFaces documentation](http://primefaces.org/documentation.html).
## [](#spring-faces-security-taglib)13.9. Using the Spring Security Facelets Tag Library
## 13.9. Using the Spring Security Facelets Tag Library
To use the library you'll need to create a `.taglib.xml`file and register it in `web.xml`.
......@@ -699,7 +699,7 @@ other attribute of any JSF component:
```
## [](#spring-faces-component-libraries)13.10. Third-Party Component Library Integration
## 13.10. Third-Party Component Library Integration
The Spring Web Flow JSF integration strives to be compatible with
any third-party JSF component library. By honoring all of the standard
......
# 12. Spring JavaScript Quick Reference
## [](#spring-js-introduction)12.1. Introduction
## 12.1. Introduction
The *spring-js-resources* module is a legacy module that is no longer recommended for use
but is provided still as an optional module for backwards compatibility. Its original aim is to provide a
......@@ -8,7 +8,7 @@ client-side programming model for progressively enhancing a web page with behavi
Use of the Spring JS API is demonstrated in the[samples repository](https://github.com/spring-projects/spring-webflow-samples).
## [](#spring-js-resource-servlet)12.2. Serving Javascript Resources
## 12.2. Serving Javascript Resources
The Spring Framework provides a mechanism for serving static resources.
See the[Spring Framework documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-static-resources)).
......@@ -80,7 +80,7 @@ will be delegated back to the Servlet container.
```
## [](#spring-js-includes)12.3. Including Spring Javascript in a Page
## 12.3. Including Spring Javascript in a Page
Spring JS is designed such that an implementation of its API can be built for any of the popular Javascript toolkits.
The initial implementation of Spring.js builds on the Dojo toolkit.
......@@ -104,7 +104,7 @@ For the booking-mvc reference application, Dojo's `tundra.css` is included:
```
## [](#spring-js-decorations)12.4. Spring Javascript Decorations
## 12.4. Spring Javascript Decorations
A central concept in Spring Javascript is the notion of applying decorations to existing DOM nodes.
This technique is used to progressively enhance a web page such that the page will still be functional in a less capable browser.
......@@ -192,7 +192,7 @@ The following example decorates a set of checkbox elements as Dojo Checkbox widg
```
## [](#spring-js-ajax)12.5. Handling Ajax Requests
## 12.5. Handling Ajax Requests
Spring Javascript's client-side Ajax response handling is built upon the notion of receiving "fragments" back from the server.
These fragments are just standard HTML that is meant to replace portions of the existing page.
......@@ -208,7 +208,7 @@ Spring Javascript's Ajax remoting functionality is built upon the notion that th
Ajax request should not differ from a standard browser request, thus no special knowledge of an Ajax request
is needed directly in the code and the same hanlder can be used for both styles of request.
### [](#custom-ajax-handler)12.5.1. Providing a Library-Specific AjaxHandler
### 12.5.1. Providing a Library-Specific AjaxHandler
The key interface for integrating various Ajax libraries with the Ajax-aware behavior of Web Flow (such as not redirecting for a
partial page update) is `org.springframework.js.AjaxHandler`. A `SpringJavascriptAjaxHandler` is configured by default that is able to
......@@ -216,7 +216,7 @@ detect an Ajax request submitted via the Spring JS client-side API and can respo
order to integrate a different Ajax library (be it a pure JavaScript library, or a higher-level abstraction such as an Ajax-capable JSF
component library), a custom `AjaxHandler` can be injected into the `FlowHandlerAdapter` or `FlowController`.
### [](#spring-js-ajax-mvc)12.5.2. Handling Ajax Requests with Spring MVC Controllers
### 12.5.2. Handling Ajax Requests with Spring MVC Controllers
In order to handle Ajax requests with Spring MVC controllers, all that is needed is the configuration of
the provided Spring MVC extensions in your Spring application context for rendering the partial response
......@@ -247,7 +247,7 @@ The fragments correspond to individual attributes of a Tiles view definition. Fo
An Ajax request could specify the "body", "hotelSearchForm" or "bookingsTable" to be rendered as fragments in the request.
### [](#spring-js-ajax-mvc-webflow)12.5.3. Handling Ajax Requests with Spring MVC + Spring Web Flow
### 12.5.3. Handling Ajax Requests with Spring MVC + Spring Web Flow
Spring Web Flow handles the optional rendering of fragments directly in the flow definition language through use of the `render` element.
The benefit of this approach is that the selection of fragments is completely decoupled from client-side code, such that no special parameters need to be passed with the request the way they
......
# 11. Spring MVC Integration
## [](#spring-mvc-introduction)11.1. Introduction
## 11.1. Introduction
This chapter shows how to integrate Web Flow into a Spring MVC web
application. The `booking-mvc` sample application is a good
reference for Spring MVC with Web Flow. This application is a simplified
travel site that allows users to search for and book hotel rooms.
## [](#spring-mvc-config-web.xml)11.2. Configuring web.xml
## 11.2. Configuring web.xml
The first step to using Spring MVC is to configure the`DispatcherServlet` in `web.xml`. You typically do
this once per web application.
......@@ -31,12 +31,12 @@ configuration file for the web application.
</servlet-mapping>
```
## [](#spring-mvc-config-spring-url-mapping)11.3. Dispatching to flows
## 11.3. Dispatching to flows
The `DispatcherServlet` maps requests for application
resources to handlers. A flow is one type of handler.
### [](#d5e1532)11.3.1. Registering the FlowHandlerAdapter
### 11.3.1. Registering the FlowHandlerAdapter
The first step to dispatching requests to flows is to enable flow
handling within Spring MVC. To this, install the`FlowHandlerAdapter`:
......@@ -49,7 +49,7 @@ handling within Spring MVC. To this, install the`FlowHandlerAdapter`:
```
### [](#d5e1537)11.3.2. Defining flow mappings
### 11.3.2. Defining flow mappings
Once flow handling is enabled, the next step is to map specific
application resources to your flows. The simplest way to do this is to
......@@ -73,7 +73,7 @@ found with that id, that flow will handle the request. If no flow is
found, the next handler mapping in the Dispatcher's ordered chain will
be queried or a "noHandlerFound" response will be returned.
### [](#d5e1545)11.3.3. Flow handling workflow
### 11.3.3. Flow handling workflow
When a valid flow mapping is found, the`FlowHandlerAdapter` figures out whether to start a new
execution of that flow or resume an existing execution based on
......@@ -97,7 +97,7 @@ Consult the API documentation for `FlowHandlerAdapter`for more information. You
by implementing your own FlowHandler, discussed in the next
section.
## [](#spring-mvc-config-flow-handlers)11.4. Implementing custom FlowHandlers
## 11.4. Implementing custom FlowHandlers
`FlowHandler` is the extension point that can be used to
customize how flows are executed in a HTTP servlet environment. A`FlowHandler` is used by the `FlowHandlerAdapter`and is responsible for:
......@@ -158,7 +158,7 @@ methods that you need. Specifically:
expired flow execution. Any other exception is rethrown to the Spring
MVC ExceptionResolver infrastructure by default.
### [](#spring-mvc-flow-handler-example)11.4.1. Example FlowHandler
### 11.4.1. Example FlowHandler
A common interaction pattern between Spring MVC And Web Flow is
for a Flow to redirect to a @Controller when it ends. FlowHandlers allow
......@@ -185,7 +185,7 @@ a custom manner, nothing else is overridden. The`bookingConfirmed` outcome will
the new booking. Any other outcome will redirect back to the hotels
index page.
### [](#d5e1600)11.4.2. Deploying a custom FlowHandler
### 11.4.2. Deploying a custom FlowHandler
To install a custom FlowHandler, simply deploy it as a bean. The
bean name must match the id of the flow the handler should apply
......@@ -200,7 +200,7 @@ With this configuration, accessing the resource`/hotels/booking` will launch the
the FlowHandler will process the flow execution outcome and redirect to
the appropriate controller.
### [](#spring-mvc-flow-handler-redirects)11.4.3. FlowHandler Redirects
### 11.4.3. FlowHandler Redirects
A FlowHandler handling a FlowExecutionOutcome or FlowException
returns a `String` to indicate the resource to redirect to
......@@ -231,7 +231,7 @@ These same redirect prefixes are also supported within a flow
definition when using the `externalRedirect:` directive in
conjunction with a view-state or end-state; for example,`view="externalRedirect:http://springframework.org"`
## [](#spring-mvc-config-spring-view-resolution)11.5. View Resolution
## 11.5. View Resolution
Web Flow 2 maps selected view identifiers to files located within
the flow's working directory unless otherwise specified. For existing
......@@ -260,7 +260,7 @@ Spring MVC's native BeanWrapper by setting the`useSpringBinding` flag to true. T
using the Unified EL for view-to-model data binding. See the
JavaDoc API of this class for more information.
## [](#spring-mvc-resuming-on-event)11.6. Signaling an event from a View
## 11.6. Signaling an event from a View
When a flow enters a view-state it pauses, redirects the user to its
execution URL, and waits for a user event to resume. Events are generally
......@@ -270,7 +270,7 @@ use. This section shows how to trigger events from HTML-based views
generated by templating engines such as JSP, Velocity, or
Freemarker.
### [](#webflow-event-named-html-button)11.6.1. Using a named HTML button to signal an event
### 11.6.1. Using a named HTML button to signal an event
The example below shows two buttons on the same form that signal`proceed` and `cancel` events when clicked,
respectively.
......@@ -287,7 +287,7 @@ as the event id. So in this example, submitting`_eventId_proceed` becomes `proce
should be considered when there are several different events that can be
signaled from the same form.
### [](#webflow-event-hidden-parameter)11.6.2. Using a hidden HTML form parameter to signal an event
### 11.6.2. Using a hidden HTML form parameter to signal an event
The example below shows a form that signals the`proceed` event when submitted:
......@@ -301,7 +301,7 @@ Here, Web Flow simply detects the special `_eventId`parameter and uses its value
considered when there is one event that can be signaled on the
form.
### [](#webflow-event-link)11.6.3. Using a HTML link to signal an event
### 11.6.3. Using a HTML link to signal an event
The example below shows a link that signals the`cancel` event when activated:
......@@ -318,7 +318,7 @@ implementation simply looks for a request parameter named`_eventId`. If no `_eve
the view will look for a parameter that starts with`_eventId_` and will use the remaining substring as the event
id. If neither cases exist, no flow event is triggered.
## [](#spring-mvc-embedded-flow)11.7. Embedding A Flow On A Page
## 11.7. Embedding A Flow On A Page
By default when a flow enters a view state, it executes a
client-side redirect before rendering the view. This approach is known as
......@@ -352,7 +352,7 @@ only needs to be passed when launching the flow. Your only other concern is
to use Ajax requests and to render only the content required to update
the portion of the page displaying the flow.
### [](#spring-mvc-embedded-flow-alternatives)11.7.1. Embedded Mode Vs Default Redirect Behavior
### 11.7.1. Embedded Mode Vs Default Redirect Behavior
By default Web Flow does a client-side redirect upon entering every view state.
However if you remain in the same view state -- for example a transition without a "to" attribute -- during an Ajax request there will not be a client-side redirect.
......@@ -362,7 +362,7 @@ However transitions to a new view state are always followed with a client-side r
That makes it impossible to embed a flow on a page or within a modal dialog and execute more than one view state without causing a full-page refresh.
Hence if your use case requires embedding a flow you can launch it in "embedded" mode.
### [](#spring-mvc-embedded-flow-examples)11.7.2. Embedded Flow Examples
### 11.7.2. Embedded Flow Examples
If you'd like to see examples of a flow embedded on a page and within
a modal dialog please refer to the webflow-showcase project. You can check out
......@@ -377,7 +377,7 @@ mvn package
# import into Eclipse
```
## [](#spring-mvc-flash-output)11.8. Saving Flow Output to MVC Flash Scope
## 11.8. Saving Flow Output to MVC Flash Scope
Flow output can be automatically saved to MVC flash scope when an `end-state`performs an internal redirect. This is particularly useful when displaying a summary
screen at the end of a flow. For backwards compatibility this feature is disabled by
......
# 10. System Setup
## [](#system-setup-introduction)10.1. Introduction
## 10.1. Introduction
This chapter shows you how to setup the Web Flow system for use in any web environment.
## [](#system-config-options)10.2. Java Config and XML Namespace
## 10.2. Java Config and XML Namespace
Web Flow provides dedicated configuration support for both Java and
XML-based configuration.
......@@ -40,11 +40,11 @@ public class WebFlowConfig extends AbstractFlowConfiguration {
```
## [](#system-config-basic)10.3. Basic system configuration
## 10.3. Basic system configuration
The next section shows the minimal configuration required to set up the Web Flow system in your application.
### [](#basic-setup-flow-registry)10.3.1. FlowRegistry
### 10.3.1. FlowRegistry
Register your flows in a `FlowRegistry` in XML:
......@@ -67,7 +67,7 @@ public FlowDefinitionRegistry flowRegistry() {
```
### [](#basic-setup-flow-executor)10.3.2. FlowExecutor
### 10.3.2. FlowExecutor
Deploy a FlowExecutor, the central service for executing flows in XML:
......@@ -88,11 +88,11 @@ public FlowExecutor flowExecutor() {
See the Spring MVC and Spring Faces sections of this guide on how to integrate the Web Flow system with the MVC and JSF environment, respectively.
## [](#flow-registry)10.4. flow-registry options
## 10.4. flow-registry options
This section explores flow-registry configuration options.
### [](#flow-registry-location)10.4.1. Specifying flow locations
### 10.4.1. Specifying flow locations
Use the `location` element to specify paths to flow definitions to register.
By default, flows will be assigned registry identifiers equal to their filenames minus
......@@ -114,7 +114,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-location-id)10.4.2. Assigning custom flow identifiers
### 10.4.2. Assigning custom flow identifiers
Specify an id to assign a custom registry identifier to a flow in XML:
......@@ -132,7 +132,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-location-attributes)10.4.3. Assigning flow meta-attributes
### 10.4.3. Assigning flow meta-attributes
Use the `flow-definition-attributes` element to assign custom meta-attributes to a registered flow.
......@@ -158,7 +158,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-patterns)10.4.4. Registering flows using a location pattern
### 10.4.4. Registering flows using a location pattern
Use the `flow-location-patterns` element to register flows that match a specific resource location pattern:
......@@ -178,7 +178,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-base-path)10.4.5. Flow location base path
### 10.4.5. Flow location base path
Use the `base-path` attribute to define a base location for all flows in the application.
All flow locations are then relative to the base path.
......@@ -238,7 +238,7 @@ return getFlowDefinitionRegistryBuilder()
In the above example, suppose you had flows located in `/user/login`, `/user/registration`, `/hotels/booking`, and `/flights/booking` directories within `WEB-INF`,
you'd end up with flow ids of `user/login`, `user/registration`, `hotels/booking`, and `flights/booking`, respectively.
### [](#flow-registry-parent)10.4.6. Configuring FlowRegistry hierarchies
### 10.4.6. Configuring FlowRegistry hierarchies
Use the `parent` attribute to link two flow registries together in a hierarchy.
When the child registry is queried, if it cannot find the requested flow it will delegate to its parent.
......@@ -289,7 +289,7 @@ public class SharedConfig extends AbstractFlowConfiguration {
```
### [](#flow-registry-builder-services)10.4.7. Configuring custom FlowBuilder services
### 10.4.7. Configuring custom FlowBuilder services
Use the `flow-builder-services` attribute to customize the services and settings used to build flows in a flow-registry.
If no flow-builder-services tag is specified, the default service implementations are used.
......@@ -369,7 +369,7 @@ public ViewFactoryCreator viewFactoryCreator() {
```
#### [](#builder-service-conversion)conversion-service
#### conversion-service
Use the `conversion-service` attribute to customize the `ConversionService` used by the Web Flow system.
Type conversion is used to convert from one type to another when required during flow execution such as when processing request parameters, invoking actions, and so on.
......@@ -377,12 +377,12 @@ Many common object types such as numbers, classes, and enums are supported.
However you'll probably need to provide your own type conversion and formatting logic for custom data types.
Please read [Section 5.7, “Performing type conversion”](views.html#view-type-conversion) for important information on how to provide custom type conversion logic.
#### [](#builder-service-expression-parser)expression-parser
#### expression-parser
Use the `expression-parser` attribute to customize the `ExpressionParser` used by the Web Flow system.
The default ExpressionParser uses the Unified EL if available on the classpath, otherwise Spring EL is used.
#### [](#builder-service-view-factory-creator)view-factory-creator
#### view-factory-creator
Use the `view-factory-creator` attribute to customize the `ViewFactoryCreator` used by the Web Flow system.
The default ViewFactoryCreator produces Spring MVC ViewFactories capable of rendering JSP, Velocity, and Freemarker views.
......@@ -390,16 +390,16 @@ The default ViewFactoryCreator produces Spring MVC ViewFactories capable of rend
The configurable settings are `development`.
These settings are global configuration attributes that can be applied during the flow construction process.
#### [](#builder-development)development
#### development
Set this to `true` to switch on flow *development mode*.
Development mode switches on hot-reloading of flow definition changes, including changes to dependent flow resources such as message bundles.
## [](#flow-executor)10.5. flow-executor options
## 10.5. flow-executor options
This section explores flow-executor configuration options.
### [](#flow-executor-execution-listeners)10.5.1. Attaching flow execution listeners
### 10.5.1. Attaching flow execution listeners
Use the `flow-execution-listeners` element to register listeners that observe the lifecycle
of flow executions. For example in XML:
......@@ -444,7 +444,7 @@ public FlowExecutor flowExecutor() {
```
### [](#tuning-flow-execution-repository)10.5.2. Tuning FlowExecution persistence
### 10.5.2. Tuning FlowExecution persistence
Use the `flow-execution-repository` element to tune flow execution persistence settings.
For example in XML:
......@@ -469,7 +469,7 @@ public FlowExecutor flowExecutor() {
```
#### [](#repository-max-executions)max-executions
#### max-executions
Tune the `max-executions` attribute to place a cap on the number of flow executions that can be created per user session.
When the maximum number of executions is exceeded, the oldest execution is removed.
......@@ -478,7 +478,7 @@ When the maximum number of executions is exceeded, the oldest execution is remov
|:--------------------------------------------------------------------------------------------------------:|:---|
|The `max-executions` attribute is per user session, i.e. it works across instances of any flow definition.| |
#### [](#repository-max-snapshots)max-execution-snapshots
#### max-execution-snapshots
Tune the `max-execution-snapshots` attribute to place a cap on the number of history snapshots that can be taken per flow execution.
To disable snapshotting, set this value to 0. To enable an unlimited number of snapshots, set this value to -1.
......
# 14. Testing flows
## [](#testing-introduction)14.1. Introduction
## 14.1. Introduction
This chapter shows you how to test flows.
## [](#extending-abstractflowexecutiontest)14.2. Extending AbstractXmlFlowExecutionTests
## 14.2. Extending AbstractXmlFlowExecutionTests
To test the execution of a XML-based flow definition, extend `AbstractXmlFlowExecutionTests`:
......@@ -15,7 +15,7 @@ public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests {
```
## [](#override-getResource)14.3. Specifying the path to the flow to test
## 14.3. Specifying the path to the flow to test
At a minimum, you must override `getResource(FlowDefinitionResourceFactory)` to return the path to the flow you wish to test:
......@@ -27,7 +27,7 @@ protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resou
```
## [](#override-configureFlowBuilderContext)14.4. Registering flow dependencies
## 14.4. Registering flow dependencies
If your flow has dependencies on externally managed services,
also override `configureFlowBuilderContext(MockFlowBuilderContext)` to register stubs or mocks of those services:
......@@ -53,7 +53,7 @@ return new FlowDefinitionResource[] {
```
## [](#testing-flowstartup)14.5. Testing flow startup
## 14.5. Testing flow startup
Have your first test exercise the startup of your flow:
......@@ -76,7 +76,7 @@ public void testStartBookingFlow() {
Assertions generally verify the flow is in the correct state you expect.
## [](#testing-flowevents)14.6. Testing flow event handling
## 14.6. Testing flow event handling
Define additional tests to exercise flow event handling behavior.
You goal should be to exercise all paths through the flow.
......@@ -98,7 +98,7 @@ public void testEnterBookingDetails_Proceed() {
```
## [](#testing-mockingsubflows)14.7. Mocking a subflow
## 14.7. Mocking a subflow
To test calling a subflow, register a mock implementation of the subflow that asserts input was passed in correctly and
returns the correct outcome for your test scenario.
......
# 5. Rendering views
## [](#views-introduction)5.1. Introduction
## 5.1. Introduction
This chapter shows you how to use the `view-state` element to render views within a flow.
## [](#view-convention)5.2. Defining view states
## 5.2. Defining view states
Use the `view-state` element to define a step of the flow that renders a view and waits for a user event to resume:
......@@ -24,11 +24,11 @@ Below is a sample directory structure showing views and other resources like mes
Flow Packaging
## [](#view-explicit)5.3. Specifying view identifiers
## 5.3. Specifying view identifiers
Use the `view` attribute to specify the id of the view to render explicitly.
### [](#view-explicit-flowrelative)5.3.1. Flow relative view ids
### 5.3.1. Flow relative view ids
The view id may be a relative path to view resource in the flow's working directory:
......@@ -37,7 +37,7 @@ The view id may be a relative path to view resource in the flow's working direct
```
### [](#view-explicit-absolute)5.3.2. Absolute view ids
### 5.3.2. Absolute view ids
The view id may be a absolute path to a view resource in the webapp root directory:
......@@ -46,7 +46,7 @@ The view id may be a absolute path to a view resource in the webapp root directo
```
### [](#view-explicit-logical)5.3.3. Logical view ids
### 5.3.3. Logical view ids
With some view frameworks, such as Spring MVC's view framework, the view id may also be a logical identifier resolved by the framework:
......@@ -57,14 +57,14 @@ With some view frameworks, such as Spring MVC's view framework, the view id may
See the Spring MVC integration section for more information on how to integrate with the MVC `ViewResolver` infrastructure.
## [](#view-scope)5.4. View scope
## 5.4. View scope
A view-state allocates a new `viewScope` when it enters.
This scope may be referenced within the view-state to assign variables that should live for the duration of the state.
This scope is useful for manipulating objects over a series of requests from the same view, often Ajax requests.
A view-state destroys its viewScope when it exits.
### [](#view-scope-var)5.4.1. Allocating view variables
### 5.4.1. Allocating view variables
Use the `var` tag to declare a view variable.
Like a flow variable, any `@Autowired` references are automatically restored when the view state resumes.
......@@ -74,7 +74,7 @@ Like a flow variable, any `@Autowired` references are automatically restored whe
```
### [](#view-scope-actions)5.4.2. Assigning a viewScope variable
### 5.4.2. Assigning a viewScope variable
Use the `on-render` tag to assign a variable from an action result before the view renders:
......@@ -85,7 +85,7 @@ Use the `on-render` tag to assign a variable from an action result before the vi
```
### [](#view-scope-ajax)5.4.3. Manipulating objects in view scope
### 5.4.3. Manipulating objects in view scope
Objects in view scope are often manipulated over a series of requests from the same view.
The following example pages through a search results list.
......@@ -110,7 +110,7 @@ Asynchronous event handlers modify the current data page, then request re-render
```
## [](#view-on-render)5.5. Executing render actions
## 5.5. Executing render actions
Use the `on-render` element to execute one or more actions before view rendering.
Render actions are executed on the initial render as well as any subsequent refreshes, including any partial re-renderings of the view.
......@@ -122,7 +122,7 @@ Render actions are executed on the initial render as well as any subsequent refr
```
## [](#view-model)5.6. Binding to a model
## 5.6. Binding to a model
Use the `model` attribute to declare a model object the view binds to.
This attribute is typically used in conjunction with views that render data controls, such as forms.
......@@ -145,13 +145,13 @@ Specifying a `model` triggers the following behavior when a view event occurs:
For a flow event to be generated that can drive a view state transition, model binding must complete successfully.
If model binding fails, the view is re-rendered to allow the user to revise their edits.
## [](#view-type-conversion)5.7. Performing type conversion
## 5.7. Performing type conversion
When request parameters are used to populate the model (commonly referred to as data binding), type conversion is required to parse String-based request parameter values before setting target model properties.
Default type conversion is available for many common Java types such as numbers, primitives, enums, and Dates.
Users also have the ability to register their own type conversion logic for user-defined types, and to override the default Converters.
### [](#converter-options)5.7.1. Type Conversion Options
### 5.7.1. Type Conversion Options
Starting with version 2.1 Spring Web Flow uses the [type conversion](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#core-convert) and [formatting](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#format) system introduced in Spring 3 for nearly all type conversion needs.
Previously Web Flow applications used a type conversion mechanism that was different from the one in Spring MVC, which relied on the `java.beans.PropertyEditor` abstraction.
......@@ -159,7 +159,7 @@ Spring 3 offers a modern type conversion alternative to PropertyEditors that was
Hence Web Flow users should find it natural to work with the new Spring 3 type conversion.
Another obvious and very important benefit of this change is that a single type conversion mechanism can now be used across Spring MVC And Spring Web Flow.
### [](#converter-upgrade-to-spring-3)5.7.2. Upgrading to Spring 3 Type Conversion And Formatting
### 5.7.2. Upgrading to Spring 3 Type Conversion And Formatting
What does this practically mean for existing applications?
Existing applications are likely registering their own converters of type `org.springframework.binding.convert.converters.Converter` through a sub-class of `DefaultConversionService` available in Spring Binding.
......@@ -199,7 +199,7 @@ Instead Web Flow now relies on the default type converters and formatters in Spr
In summary the Spring 3 type conversion and formatting is now used almost exclusively in Web Flow.
Although existing applications will work without any changes, we encourage moving towards unifying the type conversion needs of Spring MVC and Spring Web Flow parts of applications.
### [](#converter-configuration)5.7.3. Configuring Type Conversion and Formatting
### 5.7.3. Configuring Type Conversion and Formatting
In Spring MVC an instance of a `FormattingConversionService` is created automatically through the custom MVC namespace:
......@@ -299,7 +299,7 @@ Of course it is also possible to mix and match.
Register new Spring 3 `Formatter` types through the "applicationConversionService".
Register existing Spring Binding `Converter` types through the "defaultConversionService".
### [](#converter-working-with)5.7.4. Working With Spring 3 Type Conversion And Formatting
### 5.7.4. Working With Spring 3 Type Conversion And Formatting
An important concept to understand is the difference between type converters and formatters.
......@@ -315,14 +315,14 @@ Web developers will find the `Formatter` interface most relevant because it fits
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|An important point to be made is that Object-to-Object conversion is a generalization of the more specific Object-to-String conversion.<br/>In fact in the end `Formatters` are reigstered as `GenericConverter` types with Spring's `GenericConversionService` making them equal to any other converter.| |
### [](#converter-formatting-annotations)5.7.5. Formatting Annotations
### 5.7.5. Formatting Annotations
One of the best features of the new type conversion is the ability to use annotations for a better control over formatting in a concise manner.
Annotations can be placed on model attributes and on arguments of @Controller methods that are mapped to requests.
Out of the box Spring provides two annotations `NumberFormat` and `DateTimeFormat` but you can create your own and have them registered along with the associated formatting logic.
You can see examples of the `DateTimeFormat` annotation in the [Spring Travel](https://src.springframework.org/svn/spring-samples/travel) and in the [Petcare](https://src.springframework.org/svn/spring-samples/petcare) along with other samples in the [Spring Samples](https://src.springframework.org/svn/spring-samples) repository.
### [](#converter-dates)5.7.6. Working With Dates
### 5.7.6. Working With Dates
The `DateTimeFormat` annotation implies use of [Joda Time](http://joda-time.sourceforge.net/).
If that is present on the classpath the use of this annotation is enabled automatically.
......@@ -332,7 +332,7 @@ The `DateTimeFormat` annotation on the other hand provides more fine-grained con
For more information on working with Spring 3 type conversion and formatting please refer to the relevant sections of the [Spring documentation](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/index.html).
## [](#view-bind)5.8. Suppressing binding
## 5.8. Suppressing binding
Use the `bind` attribute to suppress model binding and validation for particular view events.
The following example suppresses binding when the `cancel` event occurs:
......@@ -345,7 +345,7 @@ The following example suppresses binding when the `cancel` event occurs:
```
## [](#view-binder)5.9. Specifying bindings explicitly
## 5.9. Specifying bindings explicitly
Use the `binder` element to configure the exact set of model properties to
apply data binding to. This is useful to restrict the set of "allowed fields" per view.
......@@ -414,13 +414,13 @@ if the user provided value is null on form postback:
In the example above, all of the bindings are required.
If one or more blank input values are bound, validation errors will be generated and the view will re-render with those errors.
## [](#view-validate)5.10. Validating a model
## 5.10. Validating a model
Model validation is driven by constraints specified against a model object.
Web Flow supports enforcing such constraints programatically as well as
declaratively with JSR-303 Bean Validation annotations.
### [](#view-validation-jsr303)5.10.1. JSR-303 Bean Validation
### 5.10.1. JSR-303 Bean Validation
Web Flow provides built-in support for the JSR-303 Bean Validation API
building on equivalent support available in Spring MVC.
......@@ -444,7 +444,7 @@ Note that JSR-303 bean validation and validation by convention
In other words Web Flow will apply all available validation
mechanisms.
#### [](#view-validation-jsr303-partial)Partial Validation
#### Partial Validation
JSR-303 Bean Validation supports partial validation through validation groups. For example:
......@@ -486,14 +486,14 @@ of the flow-builder-services element:
```
### [](#view-validation-programmatic)5.10.2. Programmatic validation
### 5.10.2. Programmatic validation
There are two ways to perform model validation programatically.
The first is to implement validation logic in your model object.
The second is to implement an external `Validator`.
Both ways provide you with a `ValidationContext` to record error messages and access information about the current user.
#### [](#view-validation-programmatic-validate-method)Implementing a model validate method
#### Implementing a model validate method
Defining validation logic in your model object is the simplest way to validate its state.
Once such logic is structured according to Web Flow conventions, Web Flow will automatically invoke that logic during the view-state postback lifecycle.
......@@ -536,7 +536,7 @@ An example of such a view-state is shown below:
Any number of validation methods are defined. Generally, a flow edits a model over a series of views. In that case, a validate method would be defined
for each view-state where validation needs to run.
#### [](#view-validation-programmatic-validator)Implementing a Validator
#### Implementing a Validator
The second way is to define a separate object, called a *Validator*, which validates your model object.
To do this, first create a class whose name has the pattern ${model}Validator, where `${model}` is the capitialized form of the model expression, such as `booking`.
......@@ -570,7 +570,7 @@ Validators must be registered as Spring beans employing the naming convention `$
In the example above, Spring 2.5 classpath-scanning would detect the `@Component` and automatically register it as a bean with the name `bookingValidator`.
Then, anytime the `booking` model needs to be validated, this `bookingValidator` instance would be invoked for you.
#### [](#default-validate-method)Default validate method
#### Default validate method
A *Validator* class can also define a method called `validate` not associated (by convention) with any specific view-state.
......@@ -603,14 +603,14 @@ public class BookingValidator {
In above code sample the method `validateEnterBookingDetails` will be called first.
The default `validate` method will be called next.
### [](#view-validation-context)5.10.3. ValidationContext
### 5.10.3. ValidationContext
A ValidationContext allows you to obtain a `MessageContext` to record messages during validation.
It also exposes information about the current user, such as the signaled `userEvent` and the current user's `Principal` identity.
This information can be used to customize validation logic based on what button or link was activated in the UI, or who is authenticated.
See the API Javadocs for `ValidationContext` for more information.
## [](#view-validation-suppression)5.11. Suppressing validation
## 5.11. Suppressing validation
Use the `validate` attribute to suppress model validation for particular view events:
......@@ -624,7 +624,7 @@ Use the `validate` attribute to suppress model validation for particular view ev
In this example, data binding will still occur on `back` but validation will be suppressed.
## [](#view-transitions)5.12. Executing view transitions
## 5.12. Executing view transitions
Define one or more `transition` elements to handle user events that may occur on the view.
A transition may take the user to another view, or it may simply execute an action and re-render the current view.
......@@ -633,7 +633,7 @@ Finally, "global" transitions that are shared across all views may also be defin
Implementing view transitions is illustrated in the following sections.
### [](#transition-actions)5.12.1. Transition actions
### 5.12.1. Transition actions
A view-state transition can execute one or more actions before executing.
These actions may return an error result to prevent the transition from exiting the
......@@ -675,7 +675,7 @@ remaining actions in the set will *not* be executed. If you need to ensure one
transition action's result cannot impact the execution of another, define a single transition
action that invokes a method that encapsulates all the action logic.
### [](#event-handlers-global)5.12.2. Global transitions
### 5.12.2. Global transitions
Use the flow's `global-transitions` element to create transitions that apply across all views.
Global-transitions are often used to handle global menu links that are part of the layout.
......@@ -688,7 +688,7 @@ Global-transitions are often used to handle global menu links that are part of t
```
### [](#simple-event-handlers)5.12.3. Event handlers
### 5.12.3. Event handlers
From a view-state, transitions without targets can also be defined. Such transitions are called "event handlers":
......@@ -702,7 +702,7 @@ From a view-state, transitions without targets can also be defined. Such transit
These event handlers do not change the state of the flow.
They simply execute their actions and re-render the current view or one or more fragments of the current view.
### [](#event-handlers-render)5.12.4. Rendering fragments
### 5.12.4. Rendering fragments
Use the `render` element within a transition to request partial re-rendering of the current view after handling the event:
......@@ -719,7 +719,7 @@ Specify multiple elements to re-render by separating them with a comma delimiter
Such partial rendering is often used with events signaled by Ajax to update a specific zone of the view.
## [](#view-messages)5.13. Working with messages
## 5.13. Working with messages
Spring Web Flow's `MessageContext` is an API for recording messages during the course of flow executions.
Plain text messages can be added to the context, as well as internationalized messages resolved by a Spring `MessageSource`.
......@@ -727,7 +727,7 @@ Messages are renderable by views and automatically survive flow execution redire
Three distinct message severities are provided: `info`, `warning`, and `error`.
In addition, a convenient `MessageBuilder` exists for fluently constructing messages.
### [](#plain-text-message)5.13.1. Adding plain text messages
### 5.13.1. Adding plain text messages
```
MessageContext context = ...
......@@ -741,7 +741,7 @@ context.addMessage(builder.info()
```
### [](#plain-text-message-intl)5.13.2. Adding internationalized messages
### 5.13.2. Adding internationalized messages
```
MessageContext context = ...
......@@ -753,7 +753,7 @@ context.addMessage(builder.info().code("reservationConfirmation").build());
```
### [](#message-bundles)5.13.3. Using message bundles
### 5.13.3. Using message bundles
Internationalized messages are defined in message bundles accessed by a Spring `MessageSource`.
To create a flow-specific message bundle, simply define `messages.properties` file(s) in your flow's directory.
......@@ -774,7 +774,7 @@ From within a view or a flow, you may also access message resources using the `r
```
### [](#message-generation)5.13.4. Understanding system generated messages
### 5.13.4. Understanding system generated messages
There are several places where Web Flow itself will generate messages to display to the user.
One important place this occurs is during view-to-model data binding.
......@@ -809,7 +809,7 @@ typeMismatch=The {0} field is of the wrong type.
```
## [](#view-popup)5.14. Displaying popups
## 5.14. Displaying popups
Use the `popup` attribute to render a view in a modal popup dialog:
......@@ -821,12 +821,12 @@ Use the `popup` attribute to render a view in a modal popup dialog:
When using Web Flow with the Spring Javascript, no client side code is necessary for the popup to display.
Web Flow will send a response to the client requesting a redirect to the view from a popup, and the client will honor the request.
## [](#view-backtracking)5.15. View backtracking
## 5.15. View backtracking
By default, when you exit a view state and transition to a new view state, you can go back to the previous state using the browser back button.
These view state history policies are configurable on a per-transition basis by using the `history` attribute.
### [](#history-discard)5.15.1. Discarding history
### 5.15.1. Discarding history
Set the history attribute to `discard` to prevent backtracking to a view:
......@@ -835,7 +835,7 @@ Set the history attribute to `discard` to prevent backtracking to a view:
```
### [](#history-invalidate)5.15.2. Invalidating history
### 5.15.2. Invalidating history
Set the history attribute to `invalidate` to prevent backtracking to a view as well all previously displayed views:
......
# 2. What's New
## [](#whatsnew-swf-250)2.1. Spring Web Flow 2.5
## 2.1. Spring Web Flow 2.5
This release provides an upgrade path to Spring Framework 5 that in turn requires
Java 8+, Servlet 3.1, Hibernate 5, Tiles 3. See the[Spring Framework wiki](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x)for more details. The [samples repository](https://github.com/spring-projects/spring-webflow-samples)has been upgraded to Spring Web Flow 2.5.
......@@ -12,56 +12,56 @@ must be included explicitly.
This release requires JSF 2.2 or higher.
## [](#whatsnew-swf-240)2.2. Spring Web Flow 2.4
## 2.2. Spring Web Flow 2.4
This release requires JDK 1.6.
### [](#whatsnew-swf-java-config)2.2.1. Java-based Configuration
### 2.2.1. Java-based Configuration
Web Flow now supports a Java-based alternative for its system configuration.
See the updated [Chapter 10, *System Setup*](system-setup.html).
Also see the[booking-mvc](https://github.com/spring-projects/spring-webflow-samples/tree/master/booking-mvc) and[booking-faces](https://github.com/spring-projects/spring-webflow-samples/tree/master/booking-faces)samples that have been updated to use all Java config.
### [](#whatsnew-swf-mvcflash)2.2.2. Spring MVC Flash Scope Integration
### 2.2.2. Spring MVC Flash Scope Integration
When a flow ends it can now redirect to a Spring MVC controller after saving
attributes in Spring MVC's flash scope for the controller to access.
See [Section 11.8, “Saving Flow Output to MVC Flash Scope”](spring-mvc.html#spring-mvc-flash-output).
### [](#whatsnew-partial-validation)2.2.3. Partial JSR-303 Bean Validation
### 2.2.3. Partial JSR-303 Bean Validation
A flow definition can apply partial validation on the model through the validation-hints
attribute supported on view state and transition elements.
See [the section called “Partial Validation”](views.html#view-validation-jsr303-partial).
### [](#whatsnew-hibernate4)2.2.4. Hibernate Support
### 2.2.4. Hibernate Support
The `HibernateFlowExecutionListener` now supports Hibernate 4 in addition to Hibernate 3.
As of 2.4.4 the `HibernateFlowExecutionListener` also works with Hibernate 5.
### [](#whatsnew-tiles3)2.2.5. Tiles 3 Support
### 2.2.5. Tiles 3 Support
The `AjaxTilesView` now supports Tiles 3 in addition to Tiles 2.2.
### [](#whatsnew-swf-jsf20)2.2.6. Minimum JSF 2.0 Requirement
### 2.2.6. Minimum JSF 2.0 Requirement
Java ServerFaces version 1.2 and earlier are no longer supported by Spring Web Flow, if you have not done so already you will need to upgrade to JSF 2.0 or above.
In addition the Spring Faces components that were previously provided with JSF 1.2 for progressive AJAX enhancements have been removed in this release.
See [???]().
### [](#whatsnew-swf-jsf20-portlet)2.2.7. Portlet API 2.0 and JSF 2.0 support
### 2.2.7. Portlet API 2.0 and JSF 2.0 support
The internal Portlet integration introduced in Spring Web Flow 2.2 has been upgraded for JSF 2.0 compatibility.
Some of the more advanced JSF 2.0 features, such as partial state saving, are not supported in a Portlet environment, however, existing application can now upgrade to the minimum required JSF version.
Upgraded projects will need to ensure that the `<faces:resources>` elements is
included as part of their Spring configuration.
### [](#whatsnew-deprecation)2.2.8. Deprecations
### 2.2.8. Deprecations
This release deprecates *Spring.js*. The deprecation includes the entire*spring-js-resources* module including *Spring.js* and*Spring-Dojo.js* and the bundled Dojo and CSS Framework.
Also deprecated is the `SpringJavascriptAjaxHandler`from the *spring-js* module. The rest of *spring-js*,
......@@ -70,9 +70,9 @@ folded into *spring-webflow* in a future release.
OGNL support is now deprecated.
## [](#whatsnew-swf-230)2.3. Spring Web Flow 2.3
## 2.3. Spring Web Flow 2.3
### [](#whatsnew-swf-embedded-flow)2.3.1. Embedding A Flow On A Page
### 2.3.1. Embedding A Flow On A Page
By default Web Flow does a client-side redirect upon entering every view state.
That makes it impossible to embed a flow on a page or within a modal dialog and execute more than one view state without causing a full-page refresh.
......@@ -80,28 +80,28 @@ Web Flow now supports launching a flow in "embedded" mode.
In this mode a flow can transition to other view states without a client-side redirect during Ajax requests.
See [Section 11.7, “Embedding A Flow On A Page”](spring-mvc.html#spring-mvc-embedded-flow) and [Section 13.6, “Embedding a Flow On a Page”](spring-faces.html#spring-faces-embedded-mode).
### [](#whatsnew-jsr303)2.3.2. Support For JSR-303 Bean Validation
### 2.3.2. Support For JSR-303 Bean Validation
Support for the JSR-303 Bean Validation API is now available building on equivalent support available in Spring MVC.
See [Section 5.10, “Validating a model”](views.html#view-validate) for more details.
### [](#whatsnew-pc-propagation)2.3.3. Flow-Managed Persistence Context Propagation
### 2.3.3. Flow-Managed Persistence Context Propagation
Starting with Web Flow 2.3 a flow managed `PersistenceContext` is automatically extended (propagated) to sub-flows assuming the subflow also has the feature enabled as well.
See [Section 7.3, “Flow Managed Persistence And Sub-Flows”](flow-managed-persistence.html#flow-managed-persistence-propagation).
### [](#whatsnew-portlet-resource-requests)2.3.4. Portlet 2.0 Resource Requests
### 2.3.4. Portlet 2.0 Resource Requests
Support for Portlet 2.0 resource requests has now been added enabling Ajax requests with partial rendering.
URLs for such requests can be prepared with the `<portlet:resourceURL>` tag in JSP pages.
Server-side processing is similar to a combined an action and a render requests but combined in a single request.
Unlike a render request, the response from a resource request includes content from the target portlet only.
### [](#whatsnew-conversation-manager)2.3.5. Custom ConversationManager
### 2.3.5. Custom ConversationManager
The `<flow-execution-repository>` element now provides a conversation-manager attribute accepting a reference to a ConversationManager instance.
### [](#whatsnew-redirect-in-same-state)2.3.6. Redirect In Same State
### 2.3.6. Redirect In Same State
By default Web Flow does a client-side redirect when remaining in the same view state as long as the current request is not an Ajax request.
This is useful after form validation failure.
......@@ -109,7 +109,7 @@ Hitting Refresh or Back won't result in browser warnings. Hence this behavior is
However a new flow execution attribute makes it possible to disable it and that may also be necessary in some cases specific to JSF applications.
See [Section 13.7, “Redirect In Same State”](spring-faces.html#spring-faces-redirect-in-same-state).
### [](#whatsnew-samples)2.3.7. Samples
### 2.3.7. Samples
The process for building the samples included with the distribution has been simplified.
Maven can be used to build all samples in one step.
......@@ -137,11 +137,11 @@ mvn package
```
## [](#whatsnew-swf-220)2.4. Spring Web Flow 2.2
## 2.4. Spring Web Flow 2.2
### [](#whatsnew-jsf2)2.4.1. JSF 2 Support
### 2.4.1. JSF 2 Support
#### [](#d5e180)Comprehensive JSF 2 Support
#### Comprehensive JSF 2 Support
Building on 2.1, Spring Web Flow version 2.2 adds support for core JSF 2 features
The following features that were not supported in 2.1 are now available:
......@@ -158,7 +158,7 @@ fact MyFaces was not as easy to customize with regards to how component state is
We will work with Apache MyFaces to provide this support. In the mean time you will need to use
the `javax.faces.PARTIAL_STATE_SAVING` context parameter in `web.xml`to disable partial state saving with Apache MyFaces.
#### [](#d5e187)Travel Sample With the PrimeFaces Components
#### Travel Sample With the PrimeFaces Components
The main Spring Travel sample demonstrating Spring Web Flow and JSF support
is now built on JSF 2 and components from the PrimeFaces component library.
......@@ -173,22 +173,22 @@ svn co https://src.springframework.org/svn/spring-samples/webflow-primefaces-sho
```
### [](#whatsnew-sec)2.4.2. Spring Security Facelets Tag Library
### 2.4.2. Spring Security Facelets Tag Library
A new Spring Security tag library is available for use with with JSF 2.0 or with JSF 1.2 Facelets views.
It provides an \<authorize\> tag as well as several EL functions.
See [Section 13.9, “Using the Spring Security Facelets Tag Library”](spring-faces.html#spring-faces-security-taglib) for more details.
### [](#whatsnew-versions)2.4.3. Spring JavaScript Updates
### 2.4.3. Spring JavaScript Updates
#### [](#d5e200)Deprecated ResourcesServlet
#### Deprecated ResourcesServlet
Starting with Spring 3.0.4, the Spring Framework includes
a replacement for the ResourcesServlet. Please see
the Spring Framework documentation for details on the custom mvc namespace,
specifically the new["resources"](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources)element.
#### [](#d5e204)Dojo 1.5 and dojox
#### Dojo 1.5 and dojox
The bundled custom Dojo build is upgraded to version 1.5. It now includes dojox.
......@@ -196,7 +196,7 @@ Note that applications are generally encouraged to prepare their own custom
Dojo build for optimized performance depending on what parts of Dojo are
commonly used together. For examples see the[scripts](https://src.springframework.org/svn/spring-webflow/branches/spring-webflow-2.2-maintenance/spring-js-resources/scripts/dojo)used by Spring Web Flow to prepare its own custom Dojo build.
#### [](#d5e209)Two Spring JS artifacts
#### Two Spring JS artifacts
The `spring-js` artifact has been split in two -- the new artifact
(`spring-js-resources`) contains client side resource (.js, .css, etc.) while
......@@ -205,7 +205,7 @@ the existing artifact (`spring-js`) contains server-side Java code only.
Applications preparing their own custom Dojo build have an option now to
avoid including `spring-js-resources` and put `Spring.js` and`Spring-Dojo.js` directly under the root of their web application.
#### [](#d5e219)Client resources moved into META-INF/web-resources
#### Client resources moved into META-INF/web-resources
Bundled client resources (.js, .css, etc.)
have been moved to `META-INF/web-resources` from their previous location
......@@ -213,9 +213,9 @@ under `META-INF`. This change is transparent for applications but will result
in simpler and safer configuration when using the new resource handling
mechanism available in Spring 3.0.4.
### [](#whatsnew-jsf-portlet)2.4.4. JSF Portlet Support
### 2.4.4. JSF Portlet Support
#### [](#d5e226)Portlet API 2.0 and JSF 1.2 support
#### Portlet API 2.0 and JSF 1.2 support
In previous versions of Spring Web Flow support for JSF Portlets relied on
a Portlet Bridge for JSF implementation and was considered experimental.
......
# 6. 执行动作
## [](#actions-introduction)6.1。导言
## 6.1.导言
本章向你展示了如何使用`action-state`元素来控制流中某个点上的动作的执行。它还将展示如何使用`decision-state`元素来做出流路由决策。最后,将讨论几个从流中可能的各个点调用操作的示例。
## [](#action-state)6.2。界定行动状态
## 6.2.界定行动状态
当你希望调用某个操作时,使用`action-state`元素,然后根据该操作的结果转换到另一个状态:
......@@ -56,7 +56,7 @@
还请注意,一个动作状态就像其他任何状态一样,可以有另外一个输入动作,这些动作从头到尾以列表的形式执行。
## [](#decision-state)6.3。决定状态的定义
## 6.3.决定状态的定义
使用`decision-state`元素作为 Action-State 的替代选项,以使用方便的 if/else 语法做出路由决策。下面的示例显示了上面的`moreAnswersNeeded`状态,该状态现在实现为一个决策状态,而不是一个动作状态:
......@@ -67,13 +67,13 @@
```
## [](#action-outcome-events)6.4。行动成果事件映射
## 6.4.行动成果事件映射
动作经常调用普通 Java 对象上的方法。当从动作状态和决策状态调用时,可以使用这些方法返回值来驱动状态转换。由于转换是由事件触发的,因此方法返回值必须首先映射到事件对象。下表描述了如何将常见的返回值类型映射到事件对象:
[](#event-mapping-table)
**表 6.1。动作方法将值返回到事件 ID 映射**
**表 6.1.动作方法将值返回到事件 ID 映射**
|Method return type|映射的事件标识符表达式|
|------------------|----------------------------------|
......@@ -93,11 +93,11 @@
```
## [](#action-implementations)6.5。动作实现
## 6.5.动作实现
虽然将动作代码编写为 POJO 逻辑是最常见的,但还有其他几种动作实现选项。有时你需要编写需要访问流上下文的动作代码。你总是可以调用 POJO 并将 FlowRequestContext 作为 EL 变量传递给它。或者,你可以实现`Action`接口或从`MultiAction`基类进行扩展。当你的操作代码和 Spring Web 流 API 之间具有天然的耦合时,这些选项提供了更强的类型安全性。下面是这些方法的示例。
### [](#d5e1045)6.5.1。调用 POJO 动作
### 6.5.1.调用 POJO 动作
```
<evaluate expression="pojoAction.method(flowRequestContext)" />
......@@ -113,7 +113,7 @@ public class PojoAction {
```
### [](#d5e1049)6.5.2。调用自定义操作实现
### 6.5.2.调用自定义操作实现
```
<evaluate expression="customAction" />
......@@ -129,7 +129,7 @@ public class CustomAction implements Action {
```
### [](#d5e1053)6.5.3。调用多操作实现
### 6.5.3.调用多操作实现
```
<evaluate expression="multiAction.actionMethod1" />
......@@ -152,11 +152,11 @@ public class CustomMultiAction extends MultiAction {
```
## [](#action-exceptions)6.6。动作例外
## 6.6.动作例外
动作通常调用封装复杂业务逻辑的服务。这些服务可能会抛出操作代码应该处理的业务异常。
### [](#d5e1060)6.6.1。使用 POJO 操作处理业务异常
### 6.6.1.使用 POJO 操作处理业务异常
下面的示例调用一个操作,该操作捕获业务异常,将错误消息添加到上下文中,并返回结果事件标识符。结果被视为一个流事件,然后调用流可以对其进行响应。
......@@ -182,7 +182,7 @@ public String makeBooking(Booking booking, RequestContext context) {
```
### [](#d5e1065)6.6.2。使用多操作处理业务异常
### 6.6.2.使用多操作处理业务异常
下面的示例在功能上与上一个示例相同,但实现为一个多操作,而不是一个 POJO 操作。多操作要求其操作方法的签名`Event ${methodName}(RequestContext)`,提供更强的类型安全性,而 POJO 操作允许更大的自由度。
......@@ -209,13 +209,13 @@ public Event makeBooking(RequestContext context) {
```
### [](#d5e1071)6.6.3。使用异常处理程序元素
### 6.6.3.使用异常处理程序元素
通常,建议在操作中捕获异常并返回驱动标准转换的结果事件,也可以向具有`bean`属性的任何状态类型添加`exception-handler`子元素,该属性引用类型`FlowExecutionExceptionHandler`的 Bean。这是一个高级选项,如果使用不正确,可能会使流执行处于无效状态。将内建`TransitionExecutingFlowExecutionExceptionHandler`作为一个正确实现的示例。
## [](#action-examples)6.7。其他动作执行示例
## 6.7.其他动作执行示例
### [](#action-on-start)6.7.1.启动
### 6.7.1.启动
下面的示例展示了一个操作,该操作通过调用服务上的一个方法来创建一个新的 Booking 对象:
......@@ -236,7 +236,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#action-on-state-entry)6.7.2.进入
### 6.7.2.进入
下面的示例显示了一个状态条目操作,该操作设置特殊的`fragments`变量,该变量使视图状态呈现其视图的部分片段:
......@@ -249,7 +249,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#action-on-state-exit)6.7.3.on-exit
### 6.7.3.on-exit
下面的示例显示了一个状态退出操作,该操作释放正在编辑的记录上的锁:
......@@ -269,7 +269,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#on-end)6.7.4.on-end
### 6.7.4.on-end
下面的示例展示了使用流开始和结束操作的等效对象锁定行为:
......@@ -300,7 +300,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#action-on-render)6.7.5.on-render
### 6.7.5.on-render
下面的示例展示了一个呈现操作,该操作加载要在呈现视图之前显示的酒店列表:
......@@ -317,7 +317,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#action-on-transition)6.7.6.on-transition
### 6.7.6.on-transition
下面的示例展示了一个转换操作,该操作将一个子流结果事件属性添加到一个集合中:
......@@ -330,7 +330,7 @@ public Event makeBooking(RequestContext context) {
```
### [](#named-actions)6.7.7。命名动作
### 6.7.7.命名动作
下面的示例展示了如何在动作状态下执行一系列动作。每个动作的名称成为动作结果事件的限定符。
......@@ -349,7 +349,7 @@ public Event makeBooking(RequestContext context) {
在此示例中,当`thingTwo`成功完成时,流将转换为`showResults`
### [](#streaming-actions)6.7.8。串流动作
### 6.7.8.串流动作
有时,一个动作需要将自定义响应流回客户端。一个例子可能是处理打印事件时呈现 PDF 文档的流。这可以通过使内容的动作流然后在 ExternalContext 上记录“响应完成”状态来实现。ResponseComplete 标志告诉暂停视图状态不要呈现响应,因为另一个对象已经处理了它。
......@@ -376,7 +376,7 @@ public class PrintBoardingPassAction extends AbstractAction {
在本例中,当打印事件被触发时,流将调用 printboardingpassAction。该操作将呈现 PDF,然后将响应标记为已完成。
### [](#file-upload)6.7.9。处理文件上传
### 6.7.9.处理文件上传
另一个常见的任务是使用 Web 流结合 Spring MVC 的`MultipartResolver`处理多部分文件上传。一旦正确设置了解析器[如此处所述](http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html#mvc-multipart),并且将提交的 HTML 表单配置为`enctype="multipart/form-data"`,你就可以在转换操作中轻松处理文件上传。
......
# 3. 定义流
## [](#defining-flows-introduction)3.1。导言
## 3.1.导言
本章从用户部分开始。它展示了如何使用流定义语言实现流。在本章结束时,你应该已经对语言结构有了很好的了解,并且能够编写流定义。
## [](#flow-overview)3.2。什么是流动?
## 3.2.什么是流动?
流封装了一个可重用的步骤序列,这些步骤可以在不同的上下文中执行。下面是[加勒特信息架构](http://www.jjg.net/ia/visvocab/)图,其中引用了一个流程,该流程封装了酒店预订过程的步骤:
......@@ -12,7 +12,7 @@
示出对流程的引用的站点地图
## [](#flow-makeup)3.3。一个典型的流的构成是什么?
## 3.3.一个典型的流的构成是什么?
在 Spring Web 流中,流由一系列称为“状态”的步骤组成。输入一个状态通常会导致向用户显示一个视图。在该视图中,会发生由状态处理的用户事件。这些事件可以触发向其他状态的转换,从而导致视图导航。
......@@ -22,13 +22,13 @@
流程图
## [](#flow-authoring)3.4。流程是如何编写的?
## 3.4.流程是如何编写的?
流是由 Web 应用程序开发人员使用一种简单的基于 XML 的流定义语言编写的。本指南的下一步将向你介绍这种语言的元素。
## [](#essential-flow-elements)3.5。基本语言要素
## 3.5.基本语言要素
### [](#flow-element)3.5.1.流量
### 3.5.1.流量
每个流都以以下根元素开始:
......@@ -45,7 +45,7 @@
流的所有状态都在这个元素中定义。定义的第一个状态成为流的起点。
### [](#view-state-element)3.5.2.view-state
### 3.5.2.view-state
使用`view-state`元素定义呈现视图的流的一个步骤:
......@@ -56,7 +56,7 @@
按照惯例,视图状态将其 ID 映射到流所在目录中的视图模板。例如,如果流本身位于`/WEB-INF/hotels/booking`目录中,则上面的状态可能呈现`/WEB-INF/hotels/booking/enterBookingDetails.xhtml`
### [](#transition-element)3.5.3.过渡
### 3.5.3.过渡
使用`transition`元素来处理在一个状态中发生的事件:
......@@ -69,7 +69,7 @@
这些转换驱动视图导航。
### [](#end-state-element)3.5.4.end-state
### 3.5.4.end-state
使用`end-state`元素来定义流结果:
......@@ -80,7 +80,7 @@
当一个流转换到一个结束状态时,它就会终止,并返回结果。
### [](#checkpoint-essential-language-elements)3.5.5。检查点:基本语言元素
### 3.5.5.检查点:基本语言元素
使用三个元素`view-state``transition``end-state`,你可以快速表示视图导航逻辑。团队通常在添加流行为之前就这样做了,这样他们就可以首先专注于与最终用户一起开发应用程序的用户界面。下面是一个样例流程,它使用以下元素实现了它的视图导航逻辑:
......@@ -108,7 +108,7 @@
```
## [](#flow-actions)3.6。行动
## 3.6.行动
大多数流需要表达的不仅仅是查看导航逻辑。通常,它们还需要调用应用程序的业务服务或其他操作。
......@@ -128,7 +128,7 @@
动作是用简洁的表达式语言定义的。 Spring 默认情况下,Web 流使用统一的 EL。接下来的几节将介绍用于定义操作的基本语言元素。
### [](#evaluate-element)3.6.1.评估
### 3.6.1.评估
你最常使用的动作元素是`evaluate`元素。使用`evaluate`元素在流中的某个点计算表达式。使用这个单一标记,你可以在 Spring bean 或任何其他流变量上调用方法。例如:
......@@ -137,7 +137,7 @@
```
#### [](#evaluate-element-result)分配评估结果
#### 分配评估结果
如果表达式返回一个值,该值可以保存在流的数据模型`flowScope`中:
......@@ -146,7 +146,7 @@
```
#### [](#evaluate-element-result-type)转换求值结果
#### 转换求值结果
如果表达式返回一个可能需要转换的值,请使用`result-type`属性指定所需的类型:
......@@ -156,7 +156,7 @@
```
### [](#checkpoint-actions)3.6.2。检查点:流操作
### 3.6.2.检查点:流操作
现在查看示例预订流程,并添加以下操作:
......@@ -193,7 +193,7 @@
这个流现在开始时在流范围内创建一个 Booking 对象。要预订的酒店的 ID 是从一个流输入属性获得的。
## [](#flow-inputoutput)3.7。输入/输出映射
## 3.7.输入/输出映射
每个流都有一个定义良好的输入/输出契约。流可以在开始时传递输入属性,在结束时返回输出属性。在这方面,调用流在概念上类似于调用具有以下签名的方法:
......@@ -212,7 +212,7 @@ public interface FlowOutcome {
```
### [](#input-element)3.7.1.输入
### 3.7.1.输入
使用`input`元素声明一个流输入属性:
......@@ -223,7 +223,7 @@ public interface FlowOutcome {
输入值以属性的名称保存在流作用域中。例如,上面的输入将以`hotelId`的名称保存。
#### [](#input-element-type)声明输入类型
#### 声明输入类型
使用`type`属性声明输入属性的类型:
......@@ -234,7 +234,7 @@ public interface FlowOutcome {
如果输入值与声明的类型不匹配,将尝试进行类型转换。
#### [](#input-element-value)分配一个输入值
#### 分配一个输入值
使用`value`属性指定一个表达式,将输入值分配给:
......@@ -245,7 +245,7 @@ public interface FlowOutcome {
如果表达式的值类型可以确定,那么如果没有指定`type`属性,则该元数据将用于类型强制。
#### [](#input-element-required)根据需要标记输入
#### 根据需要标记输入
使用`required`属性强制输入不为空或空:
......@@ -254,7 +254,7 @@ public interface FlowOutcome {
```
### [](#output-element)3.7.2.输出
### 3.7.2.输出
使用`output`元素声明一个流输出属性。输出属性在表示特定流结果的结束状态中声明。
......@@ -267,7 +267,7 @@ public interface FlowOutcome {
输出值是在属性的名称下从流作用域获得的。例如,上面的输出将被分配`bookingId`变量的值。
#### [](#output-element-value)指定输出值的源
#### 指定输出值的源
使用`value`属性表示特定的输出值表达式:
......@@ -276,7 +276,7 @@ public interface FlowOutcome {
```
### [](#checkpoint-input-output)3.7.3。检查点:输入/输出映射
### 3.7.3.检查点:输入/输出映射
现在查看带有输入/输出映射的样例预订流程:
......@@ -315,11 +315,11 @@ public interface FlowOutcome {
流现在接受`hotelId`输入属性,并在确认新预订时返回`bookingId`输出属性。
## [](#flow-variables)3.8。变量
## 3.8.变量
流可以声明一个或多个实例变量。这些变量在流开始时被分配。当流恢复时,变量持有的任何`@Autowired`瞬态引用也会重新布线。
### [](#var-element)3.8.1.var
### 3.8.1.var
使用`var`元素声明一个流变量:
......@@ -330,37 +330,37 @@ public interface FlowOutcome {
确保变量的类实现`java.io.Serializable`,因为实例状态在流请求之间被保存。
## [](#scopes)3.9。可变作用域
## 3.9.可变作用域
Web 流可以将变量存储在以下几个范围中的一个:
### [](#d5e398)3.9.1。流动范围
### 3.9.1.流动范围
流作用域在流开始时被分配,在流结束时被销毁。对于默认的实现,存储在流作用域中的任何对象都需要是可序列化的。
### [](#d5e401)3.9.2。视图作用域
### 3.9.2.视图作用域
`view-state`进入时,视图作用域被分配,而当状态退出时,视图作用域被销毁。视图作用域是*只有*可从`view-state`中引用的。对于默认实现,存储在视图作用域中的任何对象都需要是可序列化的。
### [](#d5e407)3.9.3。请求范围
### 3.9.3.请求范围
当一个流被调用时,请求作用域被分配,当流返回时,请求作用域被销毁。
### [](#d5e410)3.9.4。闪光范围
### 3.9.4.闪光范围
当一个流开始时,flash 作用域被分配,在每个视图呈现后被清除,当该流结束时被销毁。对于默认的实现,存储在 Flash 作用域中的任何对象都需要是可序列化的。
### [](#d5e413)3.9.5。会话范围
### 3.9.5.会话范围
对话范围在顶级流启动时被分配,在顶级流结束时被销毁。会话范围由顶级流及其所有子流共享。对于默认的实现,对话范围的对象存储在 HTTP会话中,并且通常应该是可序列化的,以考虑典型的会话复制。
要使用的范围通常是在上下文中确定的,例如,取决于定义变量的位置--在流定义的开始(流范围),在视图状态(视图范围)内,等等。在其他情况下,例如在 EL 表达式和 Java 代码中,需要显式地指定它。随后的章节解释了如何做到这一点。
## [](#calling-subflows)3.10。调用子流
## 3.10.调用子流
一个流可以调用另一个流作为子流。流将等待直到子流返回,然后对子流结果做出响应。
### [](#subflow-state-element)3.10.1.子流-状态
### 3.10.1.子流-状态
使用`subflow-state`元素调用另一个流作为子流:
......@@ -376,7 +376,7 @@ Web 流可以将变量存储在以下几个范围中的一个:
上面的示例调用`createGuest`流,然后等待它返回。当流返回`guestCreated`结果时,新的客人将被添加到预订的客人列表中。
#### [](#subflow-state-element-input)传递一个子流输入
#### 传递一个子流输入
使用`input`元素将输入传递给子流:
......@@ -388,7 +388,7 @@ Web 流可以将变量存储在以下几个范围中的一个:
```
#### [](#subflow-state-element-output)映射子流输出
#### 映射子流输出
当一个子流完成时,它的结束状态 ID 将返回给调用流,作为用于继续导航的事件。
......@@ -403,7 +403,7 @@ Web 流可以将变量存储在以下几个范围中的一个:
在上面的示例中,`guest`是由`guestCreated`结果返回的输出属性的名称。
### [](#checkpoint-subflow)3.1 0.2。检查点:调用子流
### 3.1 0.2.检查点:调用子流
现在查看调用子流的样例预订流程:
......
# 4. 表达式语言
## [](#el-introduction)4.1。导言
## 4.1.导言
Web Flow 使用 EL 访问其数据模型并调用操作。本章将让你熟悉 EL 语法、配置和你可以从流定义中引用的特殊 EL 变量。
......@@ -16,11 +16,11 @@ EL 用于流中的许多事情,包括:
EL 还用于将表单参数绑定到模型对象,并从模型对象的属性反向呈现格式化的表单字段。然而,当使用 Web 流与 JSF 一起使用时,这种方法并不适用,在这种情况下,标准的 JSF 组件 Lifecyle 就适用了。
### [](#el-types)4.1.1。表达式类型
### 4.1.1.表达式类型
要理解的一个重要概念是,在 Web 流中有两种类型的表达式:标准表达式和模板表达式。
#### [](#el-types-eval)标准表达式
#### 标准表达式
第一种也是最常见的一种表达式是*标准表达式*。这样的表达式由 EL 直接求值,不需要用`#{}`这样的分隔符括起来。例如:
......@@ -31,7 +31,7 @@ EL 还用于将表单参数绑定到模型对象,并从模型对象的属性
上面的表达式是一个标准表达式,在计算`searchCriteria`变量时调用`nextPage`方法。如果你试图将这个表达式包含在一个特殊的分隔符中,比如`#{}`,你将得到一个`IllegalArgumentException`。在这种情况下,分隔符被视为多余的。`expression`属性唯一可接受的值是一个表达式字符串。
#### [](#el-types-template)模板表达式
#### 模板表达式
第二种表达式是*模板表达式*。模板表达式允许将文本与一个或多个标准表达式混合在一起。每个标准表达式块都显式地被`#{}`分隔符包围。例如:
......@@ -46,13 +46,13 @@ EL 还用于将表单参数绑定到模型对象,并从模型对象的属性
|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|有关接受标准表达式和接受模板表达式的 XML 属性的完整列表,请参见 Web Flow XML 模式。<br/>你还可以在 Eclipse 中使用 F2(或在其他 IDE 中使用等效的快捷方式)在键入特定的流定义属性时访问可用的文档。| |
## [](#el-language-choices)4.2。EL 实现
## 4.2.EL 实现
### [](#el-spring-el)4.2.1。 Spring El
### 4.2.1. Spring El
Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html)( Spring el)。 Spring 创建 EL 是为了提供一种单一的、支持良好的表达式语言,用于在 Spring 产品组合中的所有产品中使用。在 Spring 框架中,它作为一个单独的 JAR`org.springframework.expression`分发。
### [](#el-unified-el)4.2.2。统一 El
### 4.2.2.统一 El
使用[Unified EL](https://en.wikipedia.org/wiki/Unified_Expression_Language)还意味着对`el-api`的依赖,尽管你的 Web 容器通常是*提供*。 Spring 虽然 EL 是默认的和推荐使用的表达式语言,但如果你希望这样做,可以用统一的 EL 替换它。你需要以下 Spring 配置来将`WebFlowELExpressionParser`插入`flow-builder-services`:
......@@ -83,7 +83,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
## [](#el-portability)4.3。EL 便携性
## 4.3.EL 便携性
通常,你会发现 Spring EL 和 Unified EL 具有非常相似的语法。
......@@ -99,7 +99,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
有关 Spring EL 语法的更多信息,请参阅 Spring 文档中的[语言参考](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#expressions-language-ref)部分。
## [](#el-variables)4.4。特殊 EL 变量
## 4.4.特殊 EL 变量
你可以从流中引用几个隐式变量。这些变量将在本节中讨论。
......@@ -143,7 +143,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
以下是可以在流定义中引用的隐式变量列表:
### [](#el-variable-flowScope)4.4.1.flowscope
### 4.4.1.flowscope
使用`flowScope`分配流变量。流作用域在流开始时被分配,在流结束时被销毁。对于默认的实现,存储在流作用域中的任何对象都需要是可序列化的。
......@@ -152,7 +152,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-viewScope)4.4.2.viewscope
### 4.4.2.viewscope
使用`viewScope`分配一个视图变量。当`view-state`进入时,视图作用域被分配,而当状态退出时,视图作用域被销毁。视图作用域是*只有*可从`view-state`中引用的。对于默认实现,存储在视图作用域中的任何对象都需要是可序列化的。
......@@ -164,7 +164,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-requestScope)4.4.3.RequestScope
### 4.4.3.RequestScope
使用`requestScope`分配一个请求变量。当一个流被调用时,请求作用域被分配,当流返回时,请求作用域被销毁。
......@@ -173,7 +173,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-flashScope)4.4.4.FlashScope
### 4.4.4.FlashScope
使用`flashScope`分配一个 flash 变量。当一个流开始时,flash 作用域被分配,在每个视图呈现后被清除,当该流结束时被销毁。对于默认的实现,存储在 Flash 作用域中的任何对象都需要是可序列化的。
......@@ -182,7 +182,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-conversationScope)4.4.5.ConversationScope
### 4.4.5.ConversationScope
使用`conversationScope`分配一个会话变量。对话范围在顶级流启动时被分配,在顶级流结束时被销毁。会话范围由顶级流及其所有子流共享。对于默认的实现,对话范围的对象存储在 HTTP会话中,并且通常应该是可序列化的,以考虑典型的会话复制。
......@@ -191,7 +191,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-requestParameters)4.4.6.requestParameters
### 4.4.6.requestParameters
使用`requestParameters`访问客户端请求参数:
......@@ -200,7 +200,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-currentEvent)4.4.7.currentEvent
### 4.4.7.currentEvent
使用`currentEvent`访问当前`Event`的属性:
......@@ -209,7 +209,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-currentUser)4.4.8.currentuser
### 4.4.8.currentuser
使用`currentUser`访问经过身份验证的`Principal`:
......@@ -219,7 +219,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-messageContext)4.4.9.messagecontext
### 4.4.9.messagecontext
使用`messageContext`访问上下文以检索和创建流执行消息,包括错误和成功消息。有关更多信息,请参见`MessageContext`Javadocs。
......@@ -228,7 +228,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-resourceBundle)4.4.10.ResourceBundle
### 4.4.10.ResourceBundle
使用`resourceBundle`访问消息资源。
......@@ -237,19 +237,19 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
### [](#el-variable-requestContext)4.4.11.FlowRequestContext
### 4.4.11.FlowRequestContext
使用`flowRequestContext`访问`RequestContext`API,这是当前流请求的表示。有关更多信息,请参见 API Javadocs。
### [](#el-variable-flowExecutionContext)4.4.12.FlowExecutionContext
### 4.4.12.FlowExecutionContext
使用`flowExecutionContext`访问`FlowExecutionContext`API,这是当前流状态的表示。有关更多信息,请参见 API Javadocs。
### [](#el-variable-flowExecutionUrl)4.4.13.flowexecutionurl
### 4.4.13.flowexecutionurl
使用`flowExecutionUrl`访问当前流执行视图状态的上下文相关 URI。
### [](#el-variable-externalContext)4.4.14.ExternalContext
### 4.4.14.ExternalContext
使用`externalContext`访问客户端环境,包括用户会话属性。有关更多信息,请参见`ExternalContext`API Javadocs。
......@@ -259,7 +259,7 @@ Web 流使用[Spring Expression Language](https://docs.spring.io/spring/docs/cur
```
## [](#el-scope-searching)4.5。范围搜索算法
## 4.5.范围搜索算法
正如本节前面提到的,在一个流作用域中分配变量时,需要引用该作用域。例如:
......
......@@ -2,9 +2,9 @@
自 1.0 版本发布以来,流定义语言已经发生了变化。这是 1.0 版本中的语言元素的列表,以及它们如何映射到 2.0 版本中的元素。虽然大多数变化是语义上的,但也有一些结构上的变化。有关 Web Flow1.0 和 2.0 之间的更改的更多详细信息,请参见升级指南。
[](#field-mappings-table)
**表 A.1。映射**
**表 A.1.映射**
| SWF 1.0 | SWF 2.0 |评论| | |
|--------------------|---------------------|--------------------------------------------------------------------------|------------------------|--------------------------------------------------------------------------|
......
# 9. 流继承
## [](#flow-inheritance-introduction)9.1。导言
## 9.1.导言
流继承允许一个流继承另一个流的配置。继承可以在流和状态两个级别上发生。一个常见的用例是父流定义全局转换和异常处理程序,然后每个子流都可以继承这些设置。
为了找到父流,必须像其他任何流一样将其添加到`flow-registry`中。
## [](#flow-inheritance-java-comparison)9.2。流继承和 Java 继承一样吗?
## 9.2.流继承和 Java 继承一样吗?
流继承类似于 Java 继承,因为在父级中定义的元素是通过子级公开的,但是,有一些关键的区别。
......@@ -14,9 +14,9 @@
子流可以从多个父流继承。Java 继承仅限于一个类。
## [](#flow-inheritance-levels)9.3。流继承的类型
## 9.3.流继承的类型
### [](#flow-inheritance-level-flow)9.3.1。流级继承
### 9.3.1.流级继承
流级继承由`flow`元素上的`parent`属性定义。属性包含一个用逗号分隔的流标识符的列表。子流将按列出的顺序从每个父流继承,将元素和内容添加到结果流中。来自第一次合并的结果流将被认为是第二次合并中的子流,依此类推。
......@@ -25,7 +25,7 @@
```
### [](#flow-inheritance-level-state)9.3.2。状态级继承
### 9.3.2.状态级继承
状态级继承类似于流级继承,只是从父级继承了一个状态,而不是整个流。
......@@ -42,7 +42,7 @@
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|流级继承的意图是将公共状态定义为<br/>添加到多个流定义中并在多个流定义之间共享,而状态级继承的意图<br/>是从单个<br/>父状态扩展并合并。流级继承非常适合组合<br/>和多重继承,但是在状态级,你仍然只能从单个父状态继承<br/>。| |
## [](#flow-inheritance-abstract)9.4。抽象流
## 9.4.抽象流
通常,父流的设计不是为了直接执行。为了保护这些流不被运行,它们可以标记为`abstract`。如果一个抽象流试图运行,将抛出一个`FlowBuilderException`
......@@ -51,7 +51,7 @@
```
## [](#flow-inheritance-algorithm)9.5。继承算法
## 9.5.继承算法
当一个子流继承自它的父流时,本质上发生的情况是父流和子流合并在一起以创建一个新的流。对于 Web 流定义语言中的每个元素都有规则,这些规则控制该特定元素如何合并。
......@@ -61,7 +61,7 @@
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|到父流中的外部资源的路径应该是绝对的。<br/>当两个流合并时,相对路径将中断,除非父流和子流位于同一目录中。<br/>一旦合并,父流中的所有相对路径将变得相对于子流。| |
### [](#flow-inheritance-algorithm-mergeable)9.5.1。可合并元素
### 9.5.1.可合并元素
如果元素的类型相同,且其键控属性相同,则父元素的内容将与子元素合并。合并算法将继续合并合并父元素和子元素的每个子元素。否则,父元素将作为一个新元素添加到子元素中。
......@@ -103,7 +103,7 @@
* 视图-状态:id
### [](#flow-inheritance-nonmergeable)9.5.2。不可合并元素
### 9.5.2.不可合并元素
不可合并的要素是:
......
# 7. 流管理的持久性
## [](#flow-managed-persistence-introduction)7.1。导言
## 7.1.导言
大多数应用程序以某种方式访问数据。许多修改由多个用户共享的数据,因此需要事务性数据访问属性。它们通常将关系数据集转换成域对象,以支持应用程序处理。Web 流提供了“流管理的持久性”,其中流可以为你创建、提交和关闭对象持久性上下文。Web 流集成了 Hibernate 和 JPA 对象持久性技术。
除了流管理的持久性之外,还有一种模式是在应用程序的服务层中完全封装持久性 CECONTEXT 管理。在这种情况下,Web 层不涉及持久性,而是完全与传递给服务层并由服务层返回的分离对象一起工作。本章将重点讨论流管理的持久性,探讨如何以及何时使用该特性。
## [](#flowScopedPersistenceContext)7.2。flowscoped 持续 concecontext
## 7.2.flowscoped 持续 concecontext
此模式在流启动时在`flowScope`中创建`PersistenceContext`,在流执行过程中使用该上下文进行数据访问,并在最后向持久性实体提交所做的更改。这种模式只在流执行结束时向数据库提交更改,从而提供了中间编辑的隔离。这种模式通常与乐观锁定策略结合使用,以保护由多个用户并行修改的数据的 Integrity。为了支持在一段较长的时间内保存和重新启动流的进程,必须使用流状态的持久存储。如果不需要保存和重新启动功能,则基于 HTTP会话的标准流状态存储就足够了。在这种情况下,会话在提交之前到期或终止可能会导致更改丢失。
......@@ -51,6 +51,6 @@
就是这样。当你的流开始时,侦听器将在`flowScope`中处理分配一个新的`EntityManager`。通过使用特殊的`persistenceContext`变量,在你的流中随时引用这个 EntityManager。此外,使用 Spring 托管数据访问对象进行的任何数据访问都将自动使用该 EntityManager。这样的数据访问操作应该总是在非事务或只读事务中执行,以保持中间编辑的隔离。
## [](#flow-managed-persistence-propagation)7.3。流管理的持久性和子流
## 7.3.流管理的持久性和子流
管理的流`PersistenceContext`被自动扩展(传播)到子流,假设该子流还具有`<perstistence-context/>`变量。当子流重新使用其父进程启动的`PersistenceContext`时,当达到结束状态时,它会忽略提交标志,从而将最终决定(提交或不提交)推迟到其父进程。
\ No newline at end of file
# 8. 保障资金流动
## [](#flow-security-introduction)8.1。导言
## 8.1.导言
安全性对于任何应用程序都是一个重要的概念。最终用户不应该仅仅通过猜测 URL 就能够访问网站的任何部分。网站的敏感区域必须确保只处理授权的请求。 Spring 安全性是一种经过验证的安全平台,可以在多个级别上与你的应用程序集成。本节将重点讨论保护流执行的问题。
## [](#flow-security-how-to)8.2。我如何确保一个流程?
## 8.2.我如何确保一个流程?
确保流执行的安全性是一个三步过程:
......@@ -16,7 +16,7 @@
这些步骤中的每一个都必须完成,否则将不应用流安全规则。
## [](#flow-security-secured-element)8.3。安全元件
## 8.3.安全元件
安全元素指定其包含的元素在完全进入之前应用授权检查。这可能不会在每个被保护的流执行阶段中发生一次。
......@@ -30,7 +30,7 @@
```
### [](#flow-security-secured-element-attributes)8.3.1。安全属性
### 8.3.1.安全属性
`attributes`属性是 Spring 安全授权属性的逗号分隔列表。通常,这些都是特定的安全角色。 Spring 安全访问决策管理器将这些属性与用户授予的属性进行比较。
......@@ -41,7 +41,7 @@
默认情况下,基于角色的访问决策管理器用于确定是否允许用户访问。如果你的应用程序不使用授权角色,则需要重写此内容。
### [](#flow-security-secured-element-match)8.3.2。匹配类型
### 8.3.2.匹配类型
有两种类型的匹配可用:`any``all`。如果至少向用户授予了一个所需的安全属性,则允许访问。All,只有当每个所需的安全属性都被授予给用户时,才允许访问。
......@@ -54,7 +54,7 @@
只有在使用默认的访问决策管理器时,才会尊重`match`属性。
## [](#flow-security-listener)8.4。SecurityFlowExecutionListener
## 8.4.SecurityFlowExecutionListener
在流中定义安全规则本身并不能保护流的执行。还必须在 WebFlow 配置中定义`SecurityFlowExecutionListener`,并将其应用于流执行器。
......@@ -72,7 +72,7 @@
如果拒绝访问应用程序的一部分,将抛出`AccessDeniedException`。此异常稍后将被 Spring Security 捕获,并用于提示用户进行身份验证。重要的是,允许此异常在执行堆栈中不受约束地向上移动,否则可能不会提示最终用户进行身份验证。
### [](#flow-security-listener-adm)8.4.1。自定义访问决策管理器
### 8.4.1.自定义访问决策管理器
如果你的应用程序使用的是不基于角色的权限,则需要配置一个自定义`AccessDecisionManager`。通过在安全侦听器上设置`accessDecisionManager`属性,可以覆盖默认的决策管理器。请咨询[Spring Security reference documentation](http://static.springframework.org/spring-security/site/reference.html)以了解更多有关决策经理的信息。
......@@ -84,13 +84,13 @@
```
## [](#flow-security-configuration)8.5。配置 Spring 安全性
## 8.5.配置 Spring 安全性
Spring 安全性具有可供选择的健壮配置。由于每个应用程序和环境都有自己的安全需求,因此[Spring Security reference documentation](http://static.springframework.org/spring-security/site/reference.html)是学习可用选项的最佳位置。
`booking-faces``booking-mvc`示例应用程序都被配置为使用 Spring 安全性。在 Spring 和 web.xml 级别都需要配置。
### [](#flow-security-configuration-spring)8.5.1。 Spring 配置
### 8.5.1. Spring 配置
Spring 配置定义了`http`细节(例如受保护的 URL 和登录/注销机制)和`authentication-provider`。对于样例应用程序,配置了本地身份验证提供程序。
......@@ -119,7 +119,7 @@ Spring 配置定义了`http`细节(例如受保护的 URL 和登录/注销机
```
### [](#flow-security-configuration-web)8.5.2.web.xml 配置
### 8.5.2.web.xml 配置
`web.xml`文件中,定义了一个`filter`来拦截所有请求。此筛选器将监听登录/注销请求,并对其进行相应的处理。它还将捕获`AccesDeniedException`s 并将用户重定向到登录页面。
......
# 1. 导言
## [](#manual-overview)1.1。这本指南涵盖的内容
## 1.1.这本指南涵盖的内容
本指南涵盖了 Spring Web 流程的所有方面。它涵盖了在最终用户应用程序中实现流以及使用功能集的工作。它还包括扩展框架和整体架构模型。
## [](#system-requirements)1.2。运行 Web 流需要什么
## 1.2.运行 Web 流需要什么
Java1.8 或更高。
Spring 5.0 或更高。
## [](#resources)1.3。资源
## 1.3.资源
你可以使用指定的标记在 StackOverflow 上提出问题并进行交互,请参见[Spring at StackOverflow](https://spring.io/questions)
......@@ -18,7 +18,7 @@ Spring 5.0 或更高。
提交拉请求并使用源代码,请参见[GitHub 上的 Web 流](https://github.com/spring-projects/spring-webflow)
## [](#jars-mvn-central)1.4。如何从 Maven Central 访问 Web 流工件
## 1.4.如何从 Maven Central 访问 Web 流工件
Web 流分布中的每个 JAR 在[Maven Central Repository](https://search.maven.org)中可用。如果你已经使用 Maven 作为你的 Web 开发项目的构建系统,这将使你能够轻松地将 Web 流集成到你的应用程序中。
......@@ -46,11 +46,11 @@ Web 流分布中的每个 JAR 在[Maven Central Repository](https://search.maven
```
## [](#d5e66)1.5。如何访问夜间版本和里程碑版本
## 1.5.如何访问夜间版本和里程碑版本
可以使用 Maven 获得 Web 流开发分支的夜间快照。这些快照构建对于在下一个版本发布之前测试你所依赖的修补程序非常有用,并且为你提供了一种方便的方式来提供有关修补程序是否满足你的需求的反馈。
### [](#d5e69)1.5.1。使用 Maven 访问快照和里程碑
### 1.5.1.使用 Maven 访问快照和里程碑
对于里程碑和快照,你需要使用 SpringSource 存储库。将以下存储库添加到你的 Maven POM.xml 中:
......
# 13. JSF 集成
## [](#spring-faces-introduction)13.1。导言
## 13.1.导言
Spring Web Flow 提供了一种 JSF 集成,允许你使用带有 Spring Web Flow 控制器的 JSF UI 组件模型。Web Flow 还提供了用于 JSF 环境的 Spring 安全标记库,有关更多详细信息,请参见[Section 13.9, “Using the Spring Security Facelets Tag Library”](spring-faces.html#spring-faces-security-taglib)
Spring Web Flow2.5 需要 JSF2.2 或更高版本。
## [](#spring-faces-config-web.xml)13.2。配置 web.xml
## 13.2.配置 web.xml
第一步是将请求路由到`web.xml`文件中的`DispatcherServlet`。在这个示例中,我们将所有以`/spring/`开头的 URL 映射到 Servlet。 Servlet 需要进行配置。在 Servlet 中使用`init-param`来传递`contextConfigLocation`。这是 Web 应用程序 Spring 配置的位置。
......@@ -57,7 +57,7 @@ Spring Web Flow2.5 需要 JSF2.2 或更高版本。
```
## [](#spring-faces-webflow-config)13.3。配置用于 JSF 的 Web 流
## 13.3.配置用于 JSF 的 Web 流
本节将解释如何使用 JSF 配置 Web 流。同时支持 Java 和 XML 风格的配置。以下是 XML 中的 Web 流和 JSF 的示例配置:
......@@ -154,13 +154,13 @@ public class WebFlowConfig extends AbstractFacesFlowConfiguration {
当使用 Java Config 时,`AbstractFacesFlowConfiguration`基类会自动注册`JsfResourceRequestHandler`,因此没有进一步的工作要做。
## [](#spring-faces-managed-beans)13.4。替换 JSF 管理的 Bean 设施
## 13.4.替换 JSF 管理的 Bean 设施
当将 JSF 与 Spring Web 流一起使用时,你可以将 JSF Managed Bean 工具完全替换为 Web 流管理变量和 Spring Managed bean 的组合。它为你提供了对托管对象的生命周期的更多控制,并为域模型的初始化和执行提供了定义良好的挂钩。此外,由于你可能已经在业务层中使用了 Spring,因此它减少了必须维护两个不同的托管 Bean 模型的概念开销。
在进行纯粹的 JSF 开发时,你很快就会发现请求作用域不够长,不足以存储驱动复杂事件驱动视图的会话模型对象。在 JSF 中,通常的选择是开始将事情放入会话范围,在进入应用程序的另一个视图或功能区域之前,需要清理对象,这是一个额外的负担。真正需要的是介于请求和会话范围之间的托管范围。JSF 提供了可以通过 UIViewRoot.getViewMap()以编程方式访问的闪存和视图范围。 Spring Web Flow 提供对 Flash、View、Flow 和 Conversation 范围的访问。这些作用域通过 JSF 变量解析器无缝地集成在一起,并且在所有 JSF 应用程序中都是相同的。
### [](#spring-faces-flow-variables)13.4.1。使用流量变量
### 13.4.1.使用流量变量
声明和管理模型的最简单和最自然的方法是使用[流量变量](defining-flows.html#flow-variables)。你可以在流程的开始声明这些变量:
......@@ -189,7 +189,7 @@ public class WebFlowConfig extends AbstractFacesFlowConfiguration {
```
### [](#spring-faces-spring-beans)13.4.2。使用范围 Spring bean
### 13.4.2.使用范围 Spring bean
虽然定义 AutoWired 流实例变量提供了很好的模块化和可读性,但可能会出现希望利用 Spring 容器的其他功能的情况,例如 AOP。在这些情况下,你可以在 Spring 应用程序上下文中定义 Bean,并为其提供一个特定的 Web 流范围:
......@@ -200,7 +200,7 @@ public class WebFlowConfig extends AbstractFacesFlowConfiguration {
这种方法的主要区别在于,在通过 EL 表达式首次访问 Bean 之前,不会对 Bean 进行完全初始化。这种通过 EL 的惰性实例化非常类似于 JSF 托管 bean 的典型分配方式。
### [](#faces-manipulating-model)13.4.3。操纵模型
### 13.4.3.操纵模型
在视图呈现之前需要初始化模型(例如通过从数据库加载持久实体)是很常见的,但是 JSF 本身并没有为这种初始化提供任何方便的挂钩。流定义语言通过其[Actions](defining-flows.html#flow-actions)为此提供了一种自然的工具。 Spring Web 流为将一个动作的结果转换为特定于 JSF 的数据结构提供了一些额外的便利。例如:
......@@ -233,7 +233,7 @@ public class WebFlowConfig extends AbstractFacesFlowConfiguration {
```
### [](#faces-data-model-implementations)13.4.4。数据模型实现
### 13.4.4.数据模型实现
在上面的示例中,result-type=“datamodel”将使用自定义的`DataModel`类型包装 list\<Booking\>。自定义`DataModel`提供了额外的便利,例如可以在请求范围之外的存储中进行序列化,以及访问 EL 表达式中当前选定的行。例如,在从一个视图回发操作事件时,你可以在选定行的模型实例上执行操作,该视图中的操作事件是由 DataTable 中的组件触发的:
......@@ -248,11 +248,11 @@ Spring Web 流提供了两种自定义的数据模型类型:`OneSelectionTrack
要理解这是如何配置的,请记住`FacesConversionService`在启动时针对别名“datamodel”注册了`DataModelConverter`。在流定义中使用 result-type=“datamodel”时,将使用`DataModelConverter`。转换器然后用`OneSelectionTrackingListDataModel`的实例包装给定的列表。要使用`ManySelectionTrackingListDataModel`,你需要注册自己的自定义转换器。
## [](#spring-faces-event-handling)13.5。使用 Spring Web 流处理 JSF 事件
## 13.5.使用 Spring Web 流处理 JSF 事件
Spring Web 流允许你以解耦的方式处理 JSF 动作事件,不需要你的 Java 代码中的 JSF API 的直接依赖。实际上,这些事件通常可以完全用 Flow Definiton 语言来处理,而不需要任何定制的 Java 操作代码。这允许更敏捷的开发过程,因为在连接事件(JSF 视图模板和 SWF 流定义)中操作的工件可以立即刷新,而不需要构建和重新部署整个应用程序。
### [](#spring-faces-in-page-events)13.5.1。处理 JSF 页面内操作事件
### 13.5.1.处理 JSF 页面内操作事件
在 JSF 中,一个简单但常见的情况是,需要向一个导致以某种方式操纵模型的事件发出信号,然后重新显示相同的视图,以反映模型已更改的状态。流定义语言在`transition`元素中对此有特殊的支持。
......@@ -292,7 +292,7 @@ Spring Web 流允许你以解耦的方式处理 JSF 动作事件,不需要你
在这里,你通过增加 SearchCriteria 实例上的页面数量来处理“Next”事件。然后使用更新的条件再次调用`on-render`操作,这将导致将结果的下一页加载到数据模型中。由于在`transition`元素上没有`to`属性,因此将重新呈现相同的视图,并且模型中的更改将反映在视图中。
### [](#spring-faces-action-events)13.5.2。处理 JSF 动作事件
### 13.5.2.处理 JSF 动作事件
除了页面内事件之外,下一个逻辑级别是需要导航到另一个视图的事件,并在此过程中对模型进行一些操作。使用纯 JSF 实现这一点需要向 faces-config.xml 添加导航规则,还可能需要在 JSF 托管的 Bean 中添加一些中间 Java 代码(这两个任务都需要重新部署)。使用流定义语言,你可以在一个地方以与页面内事件处理方式非常相似的方式简洁地处理这样的情况。
......@@ -323,7 +323,7 @@ Spring Web 流允许你以解耦的方式处理 JSF 动作事件,不需要你
这里,通过将当前选定的酒店实例从 DataTable 推入流作用域来处理“select”事件,以便它可以被“reviewhotel”`view-state`引用。
### [](#spring-faces-model-validation)13.5.3。执行模型验证
### 13.5.3.执行模型验证
在对模型应用更改之前,JSF 为在字段级验证输入提供了有用的工具,但是当你需要在应用了更新之后在模型级执行更复杂的验证时,通常,你不得不在托管的 Bean 中向你的 JSF 操作方法添加更多的自定义代码。这种类型的验证通常是域模型本身的责任,但是很难在不引入对域层中的 JSF API 的不希望的依赖的情况下,将任何错误消息传播回视图。
......@@ -342,7 +342,7 @@ Spring Web 流允许你以解耦的方式处理 JSF 动作事件,不需要你
在这里,“Proceed”事件是通过调用 Booking 实例上的模型级验证方法来处理的,传递一般的`MessageContext`实例,以便可以记录消息。然后,这些消息可以与带有`h:messages`组件的任何其他 JSF 消息一起显示,
### [](#spring-faces-ajax-events-jsf2)13.5.4。在 JSF 中处理 Ajax 事件
### 13.5.4.在 JSF 中处理 Ajax 事件
JSF 提供了用于发送 Ajax 请求以及在服务器端执行部分处理和呈现的内置支持。你可以的
通过 \<f:ajax\>指定用于部分呈现的 ID 列表
......@@ -364,7 +364,7 @@ Facelets 标签。
```
## [](#spring-faces-embedded-mode)13.6。在页面上嵌入流
## 13.6.在页面上嵌入流
默认情况下,当流进入视图状态时,它会在呈现视图之前执行客户端重定向。这种方法被称为 post-redirect-get。它的优点是将一个视图的表单处理与下一个视图的呈现分离开来。因此,浏览器的后退和刷新按钮可以无缝地工作,而不会引起任何浏览器警告。
......@@ -393,7 +393,7 @@ mvn package
你需要查看的特定示例位于“Advanced Ajax”选项卡下,它被称为“带有嵌入式子流的 Top Flow”。
## [](#spring-faces-redirect-in-same-state)13.7。在相同的状态下重定向
## 13.7.在相同的状态下重定向
默认情况下,只要当前请求不是 Ajax 请求,Web 流就会进行客户端重定向,即使它仍然处于相同的视图状态。例如,在表单验证失败之后,这是非常有用的。如果用户点击 Refresh 或 Back,他们将不会看到任何浏览器警告。如果网络流不做重定向,他们就会这么做。
......@@ -410,13 +410,13 @@ Web 流的默认行为是可取的,而且 JSF 应用程序不太可能遇到
```
## [](#spring-faces-file-upload)13.8。使用 JSF 处理文件上传
## 13.8.使用 JSF 处理文件上传
大多数 JSF 组件提供程序都包含某种形式的“文件上传”组件。通常,在使用这些组件时,JSF 必须完全控制对多部分请求的解析,并且 Spring MVC 的`MultipartResolver`不能使用。
Spring Web 流已经用来自 PrimeFaces 的文件上传组件进行了测试。检查你的 JSF 组件库的文档,以便其他提供者了解如何配置文件上传。
### [](#d5e1950)13.8.1。用 primeFaces 上传文件
### 13.8.1.用 primeFaces 上传文件
PrimeFaces 提供了用于上载文件的`<p:fileUpload>`组件。为了使用该组件,你需要配置`org.primefaces.webapp.filter.FileUploadFilter` Servlet 过滤器。过滤器需要根据 Spring MVC 的`DispatcherServlet`在你的`web.xml`中进行配置:
......@@ -439,7 +439,7 @@ PrimeFaces 提供了用于上载文件的`<p:fileUpload>`组件。为了使用
有关更多详细信息,请参见[PrimeFaces 文档](http://primefaces.org/documentation.html)
## [](#spring-faces-security-taglib)13.9。使用 Spring Security Facelets 标记库
## 13.9.使用 Spring Security Facelets 标记库
要使用库,你需要创建一个`.taglib.xml`文件,并将其注册在`web.xml`中。
......@@ -540,6 +540,6 @@ PrimeFaces 提供了用于上载文件的`<p:fileUpload>`组件。为了使用
```
## [](#spring-faces-component-libraries)13.10。第三方组件库集成
## 13.10.第三方组件库集成
Spring Web 流 JSF 集成力求与任何第三方 JSF 组件库兼容。通过在 SWF 驱动的 JSF 生命周期内尊重 JSF 规范的所有标准语义,第三方库通常应该“正常工作”。需要记住的主要一点是,由于 Web 流请求不是通过标准 FacesServlet 路由的,所以 web.xml 中的配置会略有变化。通常,传统上映射到 FacesServlet 的任何内容都应该映射到 Spring DispatcherServlet。(如果你正在逐页迁移遗留的 JSF 应用程序,也可以映射到这两个应用程序)。
\ No newline at end of file
# 12. Spring JavaScript 快速引用
## [](#spring-js-introduction)12.1。导言
## 12.1.导言
*spring-js-resources*模块是一个旧模块,不再推荐使用,但仍作为可选模块提供,以实现向后兼容。其最初的目标是提供一个客户端编程模型,用于通过行为和 Ajax 远程处理逐步增强 Web 页面。
Spring JS API 的使用在[样品库](https://github.com/spring-projects/spring-webflow-samples)中进行了演示。
## [](#spring-js-resource-servlet)12.2。服务 JavaScript 资源
## 12.2.服务 JavaScript 资源
Spring 框架提供了一种用于服务静态资源的机制。参见[Spring Framework documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-static-resources))。使用新的 \<mvc:resources\>元素,资源请求由`DispatcherSevlet`处理。下面是 XML 中的配置示例(也可以使用 Java 配置):
......@@ -68,7 +68,7 @@ Spring 框架提供了一种用于服务静态资源的机制。参见[Spring Fr
```
## [](#spring-js-includes)12.3。在页面中包括 Spring JavaScript
## 12.3.在页面中包括 Spring JavaScript
Spring JS 的设计使得可以为任何流行的 JavaScript 工具包构建其 API 的实现。 Spring.js 的初始实现建立在 Dojo 工具箱的基础上。
......@@ -88,7 +88,7 @@ Spring JS 的设计使得可以为任何流行的 JavaScript 工具包构建其
```
## [](#spring-js-decorations)12.4。 Spring JavaScript 装饰
## 12.4. Spring JavaScript 装饰
Spring JavaScript 中的一个核心概念是将装饰应用到现有 DOM 节点的概念。这种技术用于逐步增强网页,使网页在功能较差的浏览器中仍能正常工作。使用`addDecoration`方法应用装饰。
......@@ -166,7 +166,7 @@ Spring JavaScript 中的一个核心概念是将装饰应用到现有 DOM 节点
```
## [](#spring-js-ajax)12.5。处理 Ajax 请求
## 12.5.处理 Ajax 请求
Spring JavaScript 的客户端 Ajax 响应处理建立在从服务器接收“碎片”的概念上。这些片段只是标准的 HTML,旨在替换现有页面的部分内容。服务器上所需的关键部分是一种确定需要将完整响应中的哪些部分拉出以进行部分呈现的方法。
......@@ -174,11 +174,11 @@ Spring JavaScript 的客户端 Ajax 响应处理建立在从服务器接收“
Spring JavaScript 的 Ajax 远程处理功能是建立在这样一种理念之上的:Ajax 请求的核心处理代码不应与标准的浏览器请求不同,因此,在代码中不需要直接提供有关 Ajax 请求的特殊知识,并且可以对两种类型的请求使用相同的方法。
### [](#custom-ajax-handler)12.5.1。提供特定于库的 AjaxHandler
### 12.5.1.提供特定于库的 AjaxHandler
将各种 Ajax 库与 Web 流的 Ajax 感知行为集成在一起的关键接口是`org.springframework.js.AjaxHandler`。默认情况下配置了`SpringJavascriptAjaxHandler`,该配置能够检测通过 Spring JS 客户端 API 提交的 Ajax 请求,并且能够在需要重定向的情况下做出适当响应。为了集成不同的 Ajax 库(无论是纯 JavaScript 库,还是更高级别的抽象,例如支持 Ajax 的 JSF 组件库),可以将自定义的`AjaxHandler`注入到`FlowHandlerAdapter``FlowController`中。
### [](#spring-js-ajax-mvc)12.5.2。用 Spring 个 MVC 控制器处理 Ajax 请求
### 12.5.2.用 Spring 个 MVC 控制器处理 Ajax 请求
为了用 Spring MVC 控制器处理 Ajax 请求,所需要的只是在你的 Spring 应用程序上下文中配置所提供的 Spring MVC 扩展,以呈现部分响应(请注意,这些扩展需要使用用于模板化的磁贴):
......@@ -205,7 +205,7 @@ Spring JavaScript 的 Ajax 远程处理功能是建立在这样一种理念之
Ajax 请求可以指定要作为请求中的片段呈现的“Body”、“HotelSearchForm”或“BookingStable”。
### [](#spring-js-ajax-mvc-webflow)12.5.3。用 Spring MVC+ Spring Web 流处理 Ajax 请求
### 12.5.3.用 Spring MVC+ Spring Web 流处理 Ajax 请求
Spring Web 流通过使用`render`元素直接在流定义语言中处理片段的可选呈现。这种方法的好处是,片段的选择与客户端代码完全解耦,这样就不需要以纯 Spring MVC 控制器方法当前必须采用的方式与请求一起传递特殊参数。例如,如果你希望将前面的示例磁贴视图中的“HotelSearchForm”片段呈现为一个富 JavaScript 弹出窗口:
......
# 11. Spring MVC 集成
## [](#spring-mvc-introduction)11.1。导言
## 11.1.导言
本章展示了如何将 Web 流集成到 Spring MVC Web 应用程序中。对于具有 Web 流的 Spring MVC,`booking-mvc`示例应用程序是一个很好的参考。这个应用程序是一个简化的旅游网站,允许用户搜索和预订酒店房间。
## [](#spring-mvc-config-web.xml)11.2。配置 web.xml
## 11.2.配置 web.xml
使用 Spring MVC 的第一步是在`web.xml`中配置`DispatcherServlet`。你通常在每个 Web 应用程序中执行一次此操作。
......@@ -26,11 +26,11 @@
</servlet-mapping>
```
## [](#spring-mvc-config-spring-url-mapping)11.3。向流量调度
## 11.3.向流量调度
`DispatcherServlet`将对应用程序资源的请求映射到处理程序。流是处理程序的一种类型。
### [](#d5e1532)11.3.1。注册 FlowhandlerAdapter
### 11.3.1.注册 FlowhandlerAdapter
将请求发送到流的第一步是在 Spring MVC 中启用流处理。为此,请安装`FlowHandlerAdapter`:
......@@ -42,7 +42,7 @@
```
### [](#d5e1537)11.3.2。定义流映射
### 11.3.2.定义流映射
一旦启用了流处理,下一步就是将特定的应用程序资源映射到你的流。最简单的方法是定义`FlowHandlerMapping`:
......@@ -58,7 +58,7 @@
配置此映射允许 Dispatcher 将应用程序资源路径映射到流注册中心中的流。例如,访问资源路径`/hotels/booking`将导致使用 ID`hotels/booking`的流的注册表查询。如果找到带有该 ID 的流,则该流将处理该请求。如果没有找到流,那么将查询 Dispatcher 的有序链中的下一个处理程序映射,或者返回一个“nohandlerfound”响应。
### [](#d5e1545)11.3.3。流程处理工作流程
### 11.3.3.流程处理工作流程
当找到一个有效的流映射时,`FlowHandlerAdapter`会根据 HTTP 请求提供的信息,计算出是启动该流的新执行,还是恢复现有的执行。有许多与适配器使用的流执行的启动和恢复相关的默认值:
......@@ -70,7 +70,7 @@
有关更多信息,请参阅`FlowHandlerAdapter`的 API 文档。你可以通过子类化或实现你自己的 Flowhandler(将在下一节中讨论)来覆盖这些默认值。
## [](#spring-mvc-config-flow-handlers)11.4。实现自定义 Flowhandlers
## 11.4.实现自定义 Flowhandlers
`FlowHandler`是可用于自定义在 HTTP Servlet 环境中如何执行流的扩展点。a`FlowHandler``FlowHandlerAdapter`使用,并负责:
......@@ -110,7 +110,7 @@ public interface FlowHandler {
* 当需要对未处理的流异常进行细粒度控制时,覆盖`handleException`。当客户端试图访问已结束或过期的流执行时,默认行为会尝试重启流。默认情况下,任何其他异常都会被重新抛出到 Spring MVC ExceptionResolver 基础结构中。
### [](#spring-mvc-flow-handler-example)11.4.1。Flowhandler 示例
### 11.4.1.Flowhandler 示例
Spring MVC 和 Web 流之间的一种常见交互模式是,当流结束时,将其重定向到 @Controller。Flowhandler 允许在不将流定义本身与特定的控制器 URL 耦合的情况下完成此操作。下面显示了一个重定向到 Spring MVC 控制器的 Flowhandler 示例:
......@@ -130,7 +130,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
由于此处理程序只需要以自定义的方式处理流执行结果,因此不重写其他内容。`bookingConfirmed`结果将导致重定向,以显示新的预订。任何其他结果将重定向回酒店索引页面。
### [](#d5e1600)11.4.2。部署自定义 Flowhandler
### 11.4.2.部署自定义 Flowhandler
要安装自定义 Flowhandler,只需将其部署为 Bean。 Bean 名称必须与处理程序应用到的流的 ID 匹配。
......@@ -141,7 +141,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
通过这种配置,访问资源`/hotels/booking`将使用自定义 BookingFlowhandler 启动`hotels/booking`流。当预订流程结束时,Flowhandler 将处理流程执行结果并将其重定向到适当的控制器。
### [](#spring-mvc-flow-handler-redirects)11.4.3。Flowhandler 重定向
### 11.4.3.Flowhandler 重定向
处理 FlowExecutionResult 或 FlowException 的 Flowhandler 返回`String`,以指示处理后要重定向到的资源。在前面的示例中,对于`BookingFlowHandler`结果,`booking/show`资源 URI 重定向到`bookingConfirmed`,对于所有其他结果,`hotels/index`资源 URI 重定向到`booking/show`
......@@ -159,7 +159,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
当结合视图状态或结束状态使用`externalRedirect:`指令时,流定义中也支持这些相同的重定向前缀;例如,`view="externalRedirect:http://springframework.org"`
## [](#spring-mvc-config-spring-view-resolution)11.5。视图分辨率
## 11.5.视图分辨率
除非另有说明,否则 Web Flow2 将选定的视图标识符映射到位于流的工作目录中的文件。对于现有的 Spring MVC+Web 流应用程序,外部`ViewResolver`可能已经在为你处理此映射。因此,要继续使用该解析器,并避免更改打包现有流视图的方式,请按以下方式配置 Web 流:
......@@ -178,11 +178,11 @@ public class BookingFlowHandler extends AbstractFlowHandler {
MVCViewFactoryCreator 是一个工厂,它允许你配置如何在 Spring Web 流中使用 Spring MVC 视图系统。使用它来配置现有的 viewresolver,以及其他服务,例如定制的 MessageCodesresolver。你还可以通过将`useSpringBinding`标志设置为 true 来启用使用 Spring MVC 的本机 BeanWrapper 的数据绑定功能。这是使用统一 EL 进行视图到模型数据绑定的一种替代方法。有关更多信息,请参见该类的 Javadoc API。
## [](#spring-mvc-resuming-on-event)11.6。从视图发送事件信号
## 11.6.从视图发送事件信号
当流进入视图状态时,它会暂停,将用户重定向到其执行 URL,并等待用户事件恢复。事件通常通过激活按钮、链接或其他用户界面命令来发出信号。事件如何在服务器端进行解码取决于所使用的视图技术。本节展示了如何从基于 HTML 的视图中触发事件,这些视图是由 JSP、Velocity 或 Freemarker 等模板引擎生成的。
### [](#webflow-event-named-html-button)11.6.1。使用命名的 HTML 按钮发送事件信号
### 11.6.1.使用命名的 HTML 按钮发送事件信号
下面的示例显示了相同窗体上的两个按钮,当单击时分别表示`proceed``cancel`事件。
......@@ -194,7 +194,7 @@ MVCViewFactoryCreator 是一个工厂,它允许你配置如何在 Spring Web
当按下按钮时,WebFlow 查找一个以`_eventId_`开头的请求参数名,并将其余的子字符串作为事件 ID。所以在这个例子中,提交`_eventId_proceed`变成了`proceed`。当有几个不同的事件可以从相同的形式发出信号时,应该考虑这种样式。
### [](#webflow-event-hidden-parameter)11.6.2。使用隐藏的 HTML 表单参数来表示事件
### 11.6.2.使用隐藏的 HTML 表单参数来表示事件
下面的示例显示了一个表单,该表单在提交时表示`proceed`事件:
......@@ -206,7 +206,7 @@ MVCViewFactoryCreator 是一个工厂,它允许你配置如何在 Spring Web
在这里,WebFlow 只检测特殊的`_eventId`参数,并将其值用作事件 ID。只有当窗体上有一个事件可以用信号表示时,才应该考虑这种样式。
### [](#webflow-event-link)11.6.3。使用 HTML 链接发出事件信号
### 11.6.3.使用 HTML 链接发出事件信号
下面的示例显示了一个链接,该链接在激活时发出`cancel`事件的信号:
......@@ -217,7 +217,7 @@ MVCViewFactoryCreator 是一个工厂,它允许你配置如何在 Spring Web
触发一个事件会导致一个 HTTP 请求被发送回服务器。在服务器端,流处理从其当前视图状态中解码事件。这个解码过程的工作方式是特定于视图实现的。回想一下 Spring MVC 视图实现只是查找一个名为`_eventId`的请求参数。如果没有找到`_eventId`参数,则视图将查找一个以`_eventId_`开头的参数,并将剩余的子字符串用作事件 ID。如果两种情况都不存在,则不会触发流事件。
## [](#spring-mvc-embedded-flow)11.7。在页面上嵌入流
## 11.7.在页面上嵌入流
默认情况下,当流进入视图状态时,它会在呈现视图之前执行客户端重定向。这种方法被称为 post-redirect-get。它的优点是将一个视图的表单处理与下一个视图的呈现分离开来。因此,浏览器的后退和刷新按钮可以无缝地工作,而不会引起任何浏览器警告。
......@@ -231,11 +231,11 @@ MVCViewFactoryCreator 是一个工厂,它允许你配置如何在 Spring Web
当以“嵌入页面”模式启动时,流将不会在 Ajax 请求期间发出流执行重定向。Mode=Embedded 参数只需要在启动流时传递。你唯一关心的另一个问题是使用 Ajax 请求,并且只呈现更新显示该流的页面部分所需的内容。
### [](#spring-mvc-embedded-flow-alternatives)11.7.1。嵌入式模式与默认重定向行为
### 11.7.1.嵌入式模式与默认重定向行为
默认情况下,WebFlow 在进入每个视图状态时都会进行客户端重定向。但是,如果在 Ajax 请求期间保持相同的视图状态(例如,没有“to”属性的转换),那么就不会有客户端重定向。这种行为对于 Spring Web Flow2 用户应该非常熟悉。它适用于支持浏览器后退按钮的顶级流,同时还可以利用 Ajax 和部分呈现,用于在表单验证、分页槽搜索结果等视图中保持不变的用例。但是,在转换到新的视图状态之后,总是会进行客户端重定向。这使得不可能在页面或模态对话框中嵌入流并执行多个视图状态,而不会导致整页刷新。因此,如果你的用例需要嵌入一个流,你可以在“嵌入”模式中启动它。
### [](#spring-mvc-embedded-flow-examples)11.7.2。嵌入式流程示例
### 11.7.2.嵌入式流程示例
如果你想看到嵌入在页面和模态对话框中的流的示例,请参阅 WebFlow-Showcase 项目。你可以在本地签出源代码,将其构建为 Maven 项目,并将其导入到 Eclipse 中:
......@@ -247,7 +247,7 @@ mvn package
# import into Eclipse
```
## [](#spring-mvc-flash-output)11.8。将流输出保存到 MVC 闪存范围
## 11.8.将流输出保存到 MVC 闪存范围
`end-state`执行内部重定向时,流输出可以自动保存到 MVC 闪存范围。当在流的末尾显示摘要屏幕时,这一点特别有用。对于向后兼容性,默认情况下禁用此功能,以便将`saveOutputToFlashScopeOnRedirect`上的`FlowHandlerAdapter`设置为`true`
......
# 10. 系统设置
## [](#system-setup-introduction)10.1。导言
## 10.1.导言
本章将向你展示如何设置在任何 Web 环境中使用的 Web 流系统。
## [](#system-config-options)10.2。Java 配置和 XML 命名空间
## 10.2.Java 配置和 XML 命名空间
Web 流为基于 Java 和 XML 的配置提供了专门的配置支持。
......@@ -39,11 +39,11 @@ public class WebFlowConfig extends AbstractFlowConfiguration {
```
## [](#system-config-basic)10.3。基本系统配置
## 10.3.基本系统配置
下一节将展示在应用程序中设置 Web 流系统所需的最小配置。
### [](#basic-setup-flow-registry)10.3.1。FlowRegistry
### 10.3.1.FlowRegistry
`FlowRegistry`的 XML 中注册你的流:
......@@ -66,7 +66,7 @@ public FlowDefinitionRegistry flowRegistry() {
```
### [](#basic-setup-flow-executor)10.3.2。流动执行器
### 10.3.2.流动执行器
部署 FlowExecutor,这是用于执行 XML 流的中心服务:
......@@ -87,11 +87,11 @@ public FlowExecutor flowExecutor() {
请参阅本指南的 Spring MVC 和 Spring Faces 部分,分别介绍如何将 Web 流系统与 MVC 和 JSF 环境集成。
## [](#flow-registry)10.4.flow-registry 选项
## 10.4.flow-registry 选项
本节将探讨流注册中心配置选项。
### [](#flow-registry-location)10.4.1。指定流位置
### 10.4.1.指定流位置
使用`location`元素指定要注册的流定义的路径。默认情况下,流被分配的注册表标识符等于其文件名减去文件扩展名,除非定义了注册表池路径。
......@@ -111,7 +111,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-location-id)10.4.2。分配自定义流标识符
### 10.4.2.分配自定义流标识符
指定一个 ID,以便将自定义注册表标识符分配给 XML 中的流:
......@@ -129,7 +129,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-location-attributes)10.4.3。分配流元属性
### 10.4.3.分配流元属性
使用`flow-definition-attributes`元素将自定义的元属性分配给已注册的流。
......@@ -155,7 +155,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-patterns)10.4.4。使用位置模式注册流
### 10.4.4.使用位置模式注册流
使用`flow-location-patterns`元素来注册与特定资源位置模式匹配的流:
......@@ -175,7 +175,7 @@ return getFlowDefinitionRegistryBuilder()
```
### [](#flow-registry-base-path)10.4.5。流量定位基准路径
### 10.4.5.流量定位基准路径
使用`base-path`属性为应用程序中的所有流定义一个基本位置。然后,所有的流动位置都相对于基本路径。基本路径可以是资源路径,例如“/WEB-INF”,或者是 Classpath 上的位置,例如“ Classpath:org/springframework/webflow/samples”。
......@@ -227,7 +227,7 @@ return getFlowDefinitionRegistryBuilder()
在上面的示例中,假设在`/user/login``/user/registration``/hotels/booking``/flights/booking`目录中有位于`WEB-INF`中的流 ID,则最终得到的流 ID 分别为`user/login``hotels/booking``flights/booking`
### [](#flow-registry-parent)10.4.6。配置 FlowRegistry 层次结构
### 10.4.6.配置 FlowRegistry 层次结构
使用`parent`属性在层次结构中将两个流注册中心链接在一起。当查询子注册中心时,如果它找不到请求的流,它将委托给其父注册中心。
......@@ -277,7 +277,7 @@ public class SharedConfig extends AbstractFlowConfiguration {
```
### [](#flow-registry-builder-services)10.4.7。配置自定义 FlowBuilder 服务
### 10.4.7.配置自定义 FlowBuilder 服务
使用`flow-builder-services`属性定制用于在流注册中心中构建流的服务和设置。如果没有指定 flow-builder-services 标记,则使用默认的服务实现。定义标记时,只需引用要自定义的服务。
......@@ -354,29 +354,29 @@ public ViewFactoryCreator viewFactoryCreator() {
```
#### [](#builder-service-conversion)转换-服务
#### 转换-服务
使用`conversion-service`属性定制 Web 流系统使用的`ConversionService`。类型转换用于在流执行期间(例如在处理请求参数、调用操作等时)需要从一种类型转换为另一种类型。支持许多常见的对象类型,如数字、类和枚举。但是,你可能需要为自定义数据类型提供自己的类型转换和格式逻辑。有关如何提供自定义类型转换逻辑的重要信息,请阅读[第 5.7 节,“执行类型转换”](views.html#view-type-conversion)
#### [](#builder-service-expression-parser)表达式分析器
#### 表达式分析器
使用`expression-parser`属性定制 Web 流系统使用的`ExpressionParser`。默认表达式分析器使用统一的 EL(如果在 Classpath 上可用),否则使用 Spring EL。
#### [](#builder-service-view-factory-creator)视图-工厂-创建者
#### 视图-工厂-创建者
使用`view-factory-creator`属性定制 Web 流系统使用的`ViewFactoryCreator`。默认的 ViewFactoryCreator 生成 Spring MVC 视图工厂,它能够呈现 JSP、Velocity 和 Freemarker 视图。
可配置设置为`development`。这些设置是可以在流构建过程中应用的全局配置属性。
#### [](#builder-development)发展
#### 发展
将此设置为`true`以打开流*发展模式*。开发模式切换到热重载流定义的更改,包括对依赖流资源(如消息包)的更改。
## [](#flow-executor)10.5.flow-executor 选项
## 10.5.flow-executor 选项
本节将探讨流执行器配置选项。
### [](#flow-executor-execution-listeners)10.5.1。附加流执行侦听器
### 10.5.1.附加流执行侦听器
使用`flow-execution-listeners`元素来注册观察流执行生命周期的侦听器。例如,在 XML 中:
......@@ -420,7 +420,7 @@ public FlowExecutor flowExecutor() {
```
### [](#tuning-flow-execution-repository)10.5.2。调优流执行持久性
### 10.5.2.调优流执行持久性
使用`flow-execution-repository`元素调优流执行持久性设置。例如,在 XML 中:
......@@ -444,7 +444,7 @@ public FlowExecutor flowExecutor() {
```
#### [](#repository-max-executions)最大处决
#### 最大处决
调整`max-executions`属性,以限制每个用户可以创建的流执行数量会话。当超过最大执行次数时,删除最老的执行。
......@@ -452,9 +452,9 @@ public FlowExecutor flowExecutor() {
|:--------------------------------------------------------------------------------------------------------:|:---|
|`max-executions`属性是每个用户会话,即它在任何流定义的实例之间工作。| |
#### [](#repository-max-snapshots)max-execution-snapshots
#### max-execution-snapshots
调整`max-execution-snapshots`属性,以限制每个流执行可以获取的历史快照的数量。要禁用快照,请将该值设置为 0。要启用无限数量的快照,请将该值设置为-1。
调整`max-execution-snapshots`属性,以限制每个流执行可以获取的历史快照的数量。要禁用快照,请将该值设置为 0.要启用无限数量的快照,请将该值设置为-1.
|[[note](images/note.png)|Note|
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
......
# 14. 测试流程
## [](#testing-introduction)14.1。导言
## 14.1.导言
本章向你展示了如何测试流。
## [](#extending-abstractflowexecutiontest)14.2。扩展 AbstractXMLFlowExecutionTests
## 14.2.扩展 AbstractXMLFlowExecutionTests
要测试基于 XML 的流定义的执行情况,请扩展`AbstractXmlFlowExecutionTests`:
......@@ -15,7 +15,7 @@ public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests {
```
## [](#override-getResource)14.3。指定要测试的流的路径
## 14.3.指定要测试的流的路径
至少,你必须重写`getResource(FlowDefinitionResourceFactory)`才能返回你希望测试的流的路径:
......@@ -27,7 +27,7 @@ protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resou
```
## [](#override-configureFlowBuilderContext)14.4。注册流依赖项
## 14.4.注册流依赖项
如果你的流依赖于外部管理的服务,也可以覆盖`configureFlowBuilderContext(MockFlowBuilderContext)`以注册这些服务的存根或模拟:
......@@ -51,7 +51,7 @@ return new FlowDefinitionResource[] {
```
## [](#testing-flowstartup)14.5。测试流启动
## 14.5.测试流启动
让你的第一个测试练习启动你的流:
......@@ -74,7 +74,7 @@ public void testStartBookingFlow() {
断言通常会验证流处于你期望的正确状态。
## [](#testing-flowevents)14.6。测试流事件处理
## 14.6.测试流事件处理
定义额外的测试来执行流事件处理行为。你的目标应该是在流程中锻炼所有的路径。你可以使用方便的`setCurrentState(String)`方法跳转到你希望开始测试的流状态。
......@@ -94,7 +94,7 @@ public void testEnterBookingDetails_Proceed() {
```
## [](#testing-mockingsubflows)14.7。嘲弄子流
## 14.7.模拟一个子流
要测试调用一个子流,请注册一个子流的模拟实现,该实现断言输入被正确地传入,并为你的测试场景返回正确的结果。
......
# 5. 呈现视图
## [](#views-introduction)5.1。导言
## 5.1.导言
本章向你展示了如何使用`view-state`元素在流中呈现视图。
## [](#view-convention)5.2。定义视图状态
## 5.2.定义视图状态
使用`view-state`元素来定义流的一个步骤,该步骤呈现视图并等待用户事件恢复:
......@@ -23,11 +23,11 @@
流动包装
## [](#view-explicit)5.3。指定视图标识符
## 5.3.指定视图标识符
使用`view`属性指定要显式呈现的视图的 ID。
### [](#view-explicit-flowrelative)5.3.1。流相对视图 ID
### 5.3.1.流相对视图 ID
视图 ID 可以是在流的工作目录中查看资源的相对路径:
......@@ -36,7 +36,7 @@
```
### [](#view-explicit-absolute)5.3.2。绝对视图 ID
### 5.3.2.绝对视图 ID
视图 ID 可以是指向 WebApp 根目录中某个视图资源的绝对路径:
......@@ -45,7 +45,7 @@
```
### [](#view-explicit-logical)5.3.3。逻辑视图 ID
### 5.3.3.逻辑视图 ID
对于一些视图框架,例如 Spring MVC 的视图框架,视图 ID 也可以是由框架解析的逻辑标识符:
......@@ -56,11 +56,11 @@
有关如何与 MVC`ViewResolver`基础架构集成的更多信息,请参见 Spring MVC 集成部分。
## [](#view-scope)5.4。视图作用域
## 5.4.视图作用域
视图状态在进入时分配一个新的`viewScope`。这个作用域可以在视图状态中被引用,以分配应该在状态持续期间有效的变量。这个作用域对于在来自同一视图的一系列请求(通常是 Ajax 请求)上操作对象非常有用。当视图状态退出时,它会破坏它的视图范围。
### [](#view-scope-var)5.4.1。分配视图变量
### 5.4.1.分配视图变量
使用`var`标记声明一个视图变量。与流变量一样,当视图状态恢复时,任何`@Autowired`引用都会自动恢复。
......@@ -69,7 +69,7 @@
```
### [](#view-scope-actions)5.4.2。分配 ViewScope 变量
### 5.4.2.分配 ViewScope 变量
在视图呈现之前,使用`on-render`标记从操作结果中分配一个变量:
......@@ -80,7 +80,7 @@
```
### [](#view-scope-ajax)5.4.3。在视图范围内操作对象
### 5.4.3.在视图范围内操作对象
视图作用域中的对象通常在来自同一视图的一系列请求上进行操作。下面的示例页面通过一个搜索结果列表。在每次呈现之前,都会在视图范围内更新该列表。异步事件处理程序修改当前数据页,然后请求重新呈现搜索结果片段。
......@@ -102,7 +102,7 @@
```
## [](#view-on-render)5.5。执行呈现动作
## 5.5.执行呈现动作
在视图呈现之前,使用`on-render`元素执行一个或多个操作。呈现操作在初始呈现以及任何后续刷新上执行,包括视图的任何部分重新呈现。
......@@ -113,7 +113,7 @@
```
## [](#view-model)5.6。绑定到模型
## 5.6.绑定到模型
使用`model`属性声明视图绑定到的模型对象。此属性通常与呈现窗体等数据控件的视图结合使用。它使表单数据绑定和验证行为能够由模型对象上的元数据驱动。
......@@ -132,15 +132,15 @@
要生成能够驱动视图状态转换的流事件,必须成功地完成模型绑定。如果模型绑定失败,将重新呈现视图,以允许用户修改其编辑。
## [](#view-type-conversion)5.7。执行类型转换
## 5.7.执行类型转换
当使用请求参数填充模型(通常称为数据绑定)时,在设置目标模型属性之前,需要进行类型转换以解析基于字符串的请求参数值。默认类型转换可用于许多常见的 Java 类型,例如数字、原语、枚举和日期。用户还可以为用户定义的类型注册自己的类型转换逻辑,并覆盖默认的转换器。
### [](#converter-options)5.7.1。类型转换选项
### 5.7.1.类型转换选项
从版本 2.1 Spring 开始,Web 流使用 Spring 3 中引入的[类型转换](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#core-convert)[formatting](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#format)系统来满足几乎所有的类型转换需求。以前,Web 流应用程序使用的类型转换机制与 Spring MVC 中的机制不同,后者依赖于`java.beans.PropertyEditor`抽象。 Spring 3 提供了一种替代 PropertYeditor 的现代类型转换方法,而 PropertYeditor 实际上受到了 Web Flow 自己的类型转换系统的影响。因此,Web 流用户应该会发现使用新的 Spring 3 类型转换是很自然的。这种变化的另一个明显且非常重要的好处是,现在可以跨 Spring MVC 和 Spring Web 流使用单一类型转换机制。
### [](#converter-upgrade-to-spring-3)5.7.2。升级到 Spring 3 类型转换和格式化
### 5.7.2.升级到 Spring 3 类型转换和格式化
这对现有的应用程序实际上意味着什么?现有的应用程序很可能通过 Spring 绑定中可用的`DefaultConversionService`的子类来注册它们自己的类型`org.springframework.binding.convert.converters.Converter`的转换器。这些转换器可以像以前一样继续注册。它们将被改编为 Spring 3`GenericConverter`类型,并以 Spring 3`org.springframework.core.convert.ConversionService`实例注册。换句话说,现有的转换器将通过 Spring 的类型转换服务被调用。
......@@ -172,7 +172,7 @@ public class ApplicationConversionService extends DefaultConversionService {
总之, Spring 3 类型转换和格式现在几乎只在 Web 流中使用。尽管现有的应用程序将在没有任何更改的情况下工作,但我们鼓励朝着统一 Spring MVC 和 Spring 应用程序的 Web 流部分的类型转换需求的方向发展。
### [](#converter-configuration)5.7.3。配置类型转换和格式
### 5.7.3.配置类型转换和格式
在 Spring MVC 中,`FormattingConversionService`的实例是通过自定义 MVC 名称空间自动创建的:
......@@ -265,7 +265,7 @@ public class ApplicationConversionServiceFactoryBean extends FormattingConversio
当然,混搭也是可以的。通过“ApplicationConversionService”注册新的 Spring 3<gtr="98"/>类型。通过“DefaultConversionService”注册现有的 Spring binding<gtr="99"/>类型。
### [](#converter-working-with)5.7.4。使用 Spring 3 类型转换和格式化
### 5.7.4.使用 Spring 3 类型转换和格式化
要理解的一个重要概念是类型转换器和格式化程序之间的区别。
......@@ -279,17 +279,17 @@ Web 开发人员将发现`Formatter`接口最相关,因为它适合 Web 应用
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|重要的一点是,对象到对象的转换是更具体的对象到字符串转换的推广。<br/>实际上在最后`Formatters`被重新定义为`GenericConverter`类型, Spring 的`GenericConversionService`使它们等于任何其他转换器。| |
### [](#converter-formatting-annotations)5.7.5。格式化注释
### 5.7.5.格式化注释
新类型转换的最佳特性之一是能够使用注释以简洁的方式更好地控制格式。注释可以放在模型属性和映射到请求的 @Controller 方法的参数上。 Spring 开箱即用提供了两个注释`NumberFormat``DateTimeFormat`,但你可以创建自己的注释,并将它们与相关的格式设置逻辑一起注册。你可以在[Spring Travel](https://src.springframework.org/svn/spring-samples/travel)[Petcare](https://src.springframework.org/svn/spring-samples/petcare)中看到`DateTimeFormat`注释的示例,以及[Spring Samples](https://src.springframework.org/svn/spring-samples)存储库中的其他示例。
### [](#converter-dates)5.7.6。与日期合作
### 5.7.6.与日期合作
`DateTimeFormat`注释意味着使用[Joda Time](http://joda-time.sourceforge.net/)。如果在 Classpath 上存在该注释,则自动启用该注释的使用。默认情况下, Spring MVC 或 Web 流都不会注册任何其他的日期格式化程序或转换器。因此,对于应用程序来说,注册一个自定义格式化程序来指定打印和解析日期的默认方式是很重要的。另一方面,`DateTimeFormat`注释在需要偏离默认值的地方提供了更细粒度的控制。
有关使用 Spring 3 类型转换和格式的更多信息,请参阅[Spring documentation](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/index.html)的相关部分。
## [](#view-bind)5.8。抑制结合
## 5.8.抑制结合
使用`bind`属性来抑制特定视图事件的模型绑定和验证。当`cancel`事件发生时,以下示例将取消绑定:
......@@ -301,7 +301,7 @@ Web 开发人员将发现`Formatter`接口最相关,因为它适合 Web 应用
```
## [](#view-binder)5.9。显式指定绑定
## 5.9.显式指定绑定
使用`binder`元素来配置要对其应用数据绑定的模型属性的精确集合。这对于限制每个视图的“允许字段”集是有用的。不使用此功能可能会导致安全问题,这取决于应用程序域和实际用户,因为默认情况下,如果未指定 Binder 元素,则模型的所有公共属性都有资格通过视图进行数据绑定。相比之下,当指定`binder`元素时,只允许显式配置绑定。下面是一个例子:
......@@ -361,11 +361,11 @@ Web 开发人员将发现`Formatter`接口最相关,因为它适合 Web 应用
在上面的示例中,所有的绑定都是必需的。如果绑定了一个或多个空白输入值,将生成验证错误,视图将使用这些错误重新呈现。
## [](#view-validate)5.10。验证模型
## 5.10.验证模型
模型验证由针对模型对象指定的约束驱动。Web 流支持以编程的方式以及以声明的方式使用 JSR-303 Bean 验证注释来强制执行这些约束。
### [](#view-validation-jsr303)5.1 0.1。JSR-303 Bean 验证
### 5.1 0.1.JSR-303 Bean 验证
Web Flow 提供了对 JSR-303 Bean 验证 API 的内置支持,构建在 Spring MVC 中提供的等效支持之上。要启用 JSR-303 验证,请使用 Spring MVC 的`LocalValidatorFactoryBean`配置 flow-builder-services:
......@@ -382,7 +382,7 @@ Web Flow 提供了对 JSR-303 Bean 验证 API 的内置支持,构建在 Spring
请注意,JSR-303 Bean 验证和约定验证(在下一节中进行解释)并不相互排斥。换句话说,WebFlow 将应用所有可用的验证机制。
#### [](#view-validation-jsr303-partial)部分验证
#### 部分验证
JSR-303 Bean 验证支持通过验证组进行部分验证。例如:
......@@ -415,11 +415,11 @@ private String name;
```
### [](#view-validation-programmatic)5.1 0.2。程序验证
### 5.1 0.2.程序验证
有两种方法来执行模型验证程序。第一种是在模型对象中实现验证逻辑。二是实现外部`Validator`。这两种方式都为你提供了`ValidationContext`,以记录错误消息并访问有关当前用户的信息。
#### [](#view-validation-programmatic-validate-method)实现一种模型验证方法
#### 实现一种模型验证方法
在模型对象中定义验证逻辑是验证其状态的最简单方法。一旦这种逻辑根据 Web 流约定进行了结构化,那么 Web 流将在视图状态回发生命周期期间自动调用该逻辑。Web 流约定让你通过视图状态来构造模型验证逻辑,从而使你能够轻松地验证在该视图上可编辑的模型属性的子集。要做到这一点,只需创建一个名为`validate${state}`的公共方法,其中`${state}`是你希望在其中运行验证的视图状态的 ID。例如:
......@@ -455,7 +455,7 @@ public class Booking {
定义了任意数量的验证方法。通常,流通过一系列视图编辑模型。在这种情况下,将为需要运行验证的每个视图状态定义一个验证方法。
#### [](#view-validation-programmatic-validator)实现验证器
#### 实现验证器
第二种方法是定义一个单独的对象,称为*验证器*,它验证你的模型对象。要做到这一点,首先创建一个类,其名称具有模式 ${model}validator,其中`${model}`是模型表达式的头化形式,例如`booking`。然后定义一个名为`validate${state}`的公共方法,其中`${state}`是你的视图状态的 ID,例如`enterBookingDetails`。然后将类部署为 Spring Bean。可以定义任意数量的验证方法。例如:
......@@ -482,7 +482,7 @@ public class BookingValidator {
必须使用命名约定`${model}Validator`将验证器注册为 Spring bean,才能自动检测和调用。在上面的示例中, Spring 2.5 Classpath-扫描将检测到`@Component`并自动将其注册为名称为`bookingValidator`的 Bean。然后,每当需要验证`booking`模型时,将为你调用这个`bookingValidator`实例。
#### [](#default-validate-method)默认验证方法
#### 默认验证方法
一个*验证器*类还可以定义一个名为`validate`的方法,该方法与任何特定的视图状态都没有关联(根据约定)。
......@@ -513,11 +513,11 @@ public class BookingValidator {
在上面的代码示例中,将首先调用方法`validateEnterBookingDetails`。下一步将调用默认的`validate`方法。
### [](#view-validation-context)5.1 0.3。ValidationContext
### 5.1 0.3.ValidationContext
ValidationContext 允许你获得`MessageContext`以在验证期间记录消息。它还公开了关于当前用户的信息,例如已信号的`userEvent`和当前用户的`Principal`标识。该信息可用于根据 UI 中激活了什么按钮或链接,或者验证了谁,定制验证逻辑。有关更多信息,请参见`ValidationContext`的 API Javadocs。
## [](#view-validation-suppression)5.11。抑制验证
## 5.11.抑制验证
使用`validate`属性禁止对特定视图事件进行模型验证:
......@@ -531,13 +531,13 @@ ValidationContext 允许你获得`MessageContext`以在验证期间记录消息
在本例中,数据绑定仍将发生在`back`上,但验证将被抑制。
## [](#view-transitions)5.12。执行视图转换
## 5.12.执行视图转换
定义一个或多个`transition`元素来处理视图上可能发生的用户事件。转换可以将用户带到另一个视图,也可以只执行一个操作并重新呈现当前视图。在处理 Ajax 事件时,转换还可能请求呈现视图中称为“碎片”的部分。最后,还可以定义在所有视图中共享的“全局”转换。
实现视图转换将在下面的小节中进行说明。
### [](#transition-actions)5.1 2.1。过渡行动
### 5.1 2.1.过渡行动
视图-状态转换可以在执行之前执行一个或多个操作。这些操作可能会返回错误结果,以防止转换退出当前视图状态。如果出现错误结果,视图将重新呈现,并应向用户显示适当的消息。
......@@ -568,7 +568,7 @@ public class BookingAction {
当在转换过程中定义了多个动作时,如果一个动作返回一个错误结果,则集合中的其余动作将执行*不是*。如果你需要确保一个转换操作的结果不会影响另一个转换操作的执行,那么可以定义一个单独的转换操作,调用一个封装了所有操作逻辑的方法。
### [](#event-handlers-global)5.1 2.2。全球转型
### 5.1 2.2.全球转型
使用流的`global-transitions`元素创建适用于所有视图的转换。全局转换通常用于处理作为布局一部分的全局菜单链接。
......@@ -580,7 +580,7 @@ public class BookingAction {
```
### [](#simple-event-handlers)5.1 2.3。事件处理程序
### 5.1 2.3.事件处理程序
从视图状态,也可以定义没有目标的转换。这样的转换被称为“事件处理程序”:
......@@ -593,7 +593,7 @@ public class BookingAction {
这些事件处理程序不会改变流的状态。它们只需执行动作并重新呈现当前视图或当前视图的一个或多个片段。
### [](#event-handlers-render)5.1 2.4。呈现片段
### 5.1 2.4.呈现片段
在处理事件后,在转换中使用`render`元素请求部分重新呈现当前视图:
......@@ -609,11 +609,11 @@ Fragments 属性应该引用你希望重新呈现的视图元素的 ID。通过
这种部分呈现通常与 Ajax 发出信号的事件一起使用,以更新视图的特定区域。
## [](#view-messages)5.13。处理消息
## 5.13.处理消息
Spring Web 流的`MessageContext`是用于在流执行过程中记录消息的 API。可以将纯文本消息添加到上下文中,以及由 Spring `MessageSource`解析的国际化消息。消息可以通过视图进行呈现,并在流执行重定向后自动保留。提供了三个不同的消息严重性:`info``warning``error`。此外,还存在一个方便的`MessageBuilder`用于流畅地构造消息。
### [](#plain-text-message)5.1 3.1。添加纯文本消息
### 5.1 3.1.添加纯文本消息
```
MessageContext context = ...
......@@ -627,7 +627,7 @@ context.addMessage(builder.info()
```
### [](#plain-text-message-intl)5.1 3.2。添加国际化消息
### 5.1 3.2.添加国际化消息
```
MessageContext context = ...
......@@ -639,7 +639,7 @@ context.addMessage(builder.info().code("reservationConfirmation").build());
```
### [](#message-bundles)5.1 3.使用消息包
### 5.1 3.使用消息包
国际化消息是在由 Spring `MessageSource`访问的消息包中定义的。要创建特定于流的消息包,只需在流的目录中定义`messages.properties`文件。为每个需要支持的额外`Locale`创建一个默认的`messages.properties`文件和一个.properties 文件。
......@@ -658,7 +658,7 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy
```
### [](#message-generation)5.1 3.4。理解系统生成的消息
### 5.1 3.4.理解系统生成的消息
在几个地方,Web Flow 本身将生成要显示给用户的消息。发生这种情况的一个重要位置是在视图到模型的数据绑定过程中。当出现绑定错误(例如类型转换错误)时,WebFlow 将自动将该错误映射到从资源包中检索到的消息。要查找要显示的消息,WebFlow 将尝试包含绑定错误代码和目标属性名称的资源键。
......@@ -683,7 +683,7 @@ typeMismatch=The {0} field is of the wrong type.
```
## [](#view-popup)5.14。显示弹出窗口
## 5.14.显示弹出窗口
使用`popup`属性在模态弹出对话框中呈现视图:
......@@ -694,11 +694,11 @@ typeMismatch=The {0} field is of the wrong type.
当使用 Spring JavaScript 的 Web 流时,弹出窗口不需要客户端代码即可显示。WebFlow 将向客户机发送响应,请求从弹出窗口重定向到视图,客户机将执行该请求。
## [](#view-backtracking)5.15。视图回溯
## 5.15.视图回溯
默认情况下,当你退出一个视图状态并转换到一个新的视图状态时,你可以使用浏览器 Back 按钮返回到以前的状态。通过使用`history`属性,可以在每次转换的基础上配置这些视图状态历史策略。
### [](#history-discard)5.15.1。抛弃历史
### 5.15.1.抛弃历史
将 history 属性设置为`discard`,以防止回溯到视图:
......@@ -707,7 +707,7 @@ typeMismatch=The {0} field is of the wrong type.
```
### [](#history-invalidate)5.15.2。使历史失效
### 5.15.2.使历史失效
将历史属性设置为`invalidate`,以防止回溯到视图以及以前显示的所有视图:
......
# 2. 有什么新鲜事吗?
# 2. 最新更新
## [](#whatsnew-swf-250)2.1。 Spring Web 流 2.5
## 2.1. Spring Web 流 2.5
这个版本提供了一条到 Spring Framework5 的升级路径,而这条路径又需要 Java8+、 Servlet 3.1、 Hibernate 5、Tiles3。有关更多详细信息,请参见[Spring Framework wiki](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x)[样品库](https://github.com/spring-projects/spring-webflow-samples)已升级到 Spring Web 流 2.5。
这个版本提供了一条到 Spring Framework5 的升级路径,而这条路径又需要 Java8+、 Servlet 3.1、 Hibernate 5、Tiles3.有关更多详细信息,请参见[Spring Framework wiki](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x)[样品库](https://github.com/spring-projects/spring-webflow-samples)已升级到 Spring Web 流 2.5.
从 2.5 开始,不再有*spring-js*模块。该模块中的类已被保留,但已转移到*spring-webflow*模块中的新包中。*spring-js-resources*模块作为一个可选模块是可用的,必须显式地包含该模块。
此版本需要 JSF2.2 或更高版本。
## [](#whatsnew-swf-240)2.2。 Spring Web 流 2.4
## 2.2. Spring Web 流 2.4
这个版本需要 JDK1.6
这个版本需要 JDK1.6.
### [](#whatsnew-swf-java-config)2.2.1。基于 Java 的配置
### 2.2.1.基于 Java 的配置
Web Flow 现在支持基于 Java 的系统配置替代方案。参见更新的[第 10 章,* 系统设置 *](system-setup.html)
还请参见[Booking-MVC](https://github.com/spring-projects/spring-webflow-samples/tree/master/booking-mvc)[预订脸](https://github.com/spring-projects/spring-webflow-samples/tree/master/booking-faces)示例,这些示例已更新为使用所有 Java 配置。
### [](#whatsnew-swf-mvcflash)2.2.2。 Spring MVC 闪存范围集成
### 2.2.2. Spring MVC 闪存范围集成
当一个流结束时,在将属性保存在 Spring MVC 的闪存范围中供控制器访问后,它现在可以重定向到 Spring MVC 控制器。
[第 11.8 节,“将流输出保存到 MVC 闪存范围”](spring-mvc.html#spring-mvc-flash-output)
### [](#whatsnew-partial-validation)2.2.3。部分 JSR-303 Bean 验证
### 2.2.3.部分 JSR-303 Bean 验证
流定义可以通过 View State 和 Transition 元素支持的 Validation-Hints 属性在模型上应用部分验证。
[该部分被称为“部分验证”。](views.html#view-validation-jsr303-partial)
### [](#whatsnew-hibernate4)2.2.4。 Hibernate 支持
### 2.2.4. Hibernate 支持
除了 Hibernate 3 之外,`HibernateFlowExecutionListener`现在还支持 Hibernate 4
除了 Hibernate 3 之外,`HibernateFlowExecutionListener`现在还支持 Hibernate 4.
截至 2.4.4,`HibernateFlowExecutionListener`也与 Hibernate 5 起作用。
### [](#whatsnew-tiles3)2.2.5。磁贴 3 支持
### 2.2.5.磁贴 3 支持
现在`AjaxTilesView`除了支持 tile2.2 外,还支持 tile3
现在`AjaxTilesView`除了支持 tile2.2 外,还支持 tile3.
### [](#whatsnew-swf-jsf20)2.2.6。最低 JSF2.0 要求
### 2.2.6.最低 JSF2.0 要求
Spring Web Flow 不再支持 Java ServerFaces 版本 1.2 和更早版本,如果你还没有这样做,你将需要升级到 JSF2.0 或更高版本。此外,在这个版本中,已经删除了以前通过 JSF1.2 提供的用于渐进 Ajax 增强的 Spring 面组件。
[???]()。
### [](#whatsnew-swf-jsf20-portlet)2.2.7。Portlet API2.0 和 JSF2.0 支持
### 2.2.7.Portlet API2.0 和 JSF2.0 支持
Spring Web Flow2.2 中引入的内部 Portlet 集成已经进行了升级,以实现 JSF2.0 的兼容性。Portlet 环境不支持一些更高级的 JSF2.0 特性,例如部分状态保存,但是,现有的应用程序现在可以升级到所需的最低 JSF 版本。升级后的项目将需要确保`<faces:resources>`元素被包括在其 Spring 配置中。
### [](#whatsnew-deprecation)2.2.8。异议
### 2.2.8.异议
此版本删除*Spring.js*。该版本包括整个 * Spring-js-resources* 模块,包括*Spring.js** Spring-dojo.js* 以及捆绑的 Dojo 和 CSS 框架。同样不推荐的是来自*spring-js*模块的`SpringJavascriptAjaxHandler`*spring-js*的其余部分,例如`AjaxHandler``AjaxTilesView`,将在未来的版本中折叠成*spring-webflow*
OGNL 支持现在已被弃用。
## [](#whatsnew-swf-230)2.3。 Spring Web 流 2.3
## 2.3. Spring Web 流 2.3
### [](#whatsnew-swf-embedded-flow)2.3.1。在页面上嵌入流
### 2.3.1.在页面上嵌入流
默认情况下,WebFlow 在进入每个视图状态时都会进行客户端重定向。这使得不可能在页面或模态对话框中嵌入流并执行多个视图状态,而不会导致整页刷新。Web Flow 现在支持以“嵌入式”模式启动一个流。在这种模式下,在 Ajax 请求期间,流可以转换到其他视图状态,而无需客户端重定向。见[第 11.7 节,“在页面上嵌入流”](spring-mvc.html#spring-mvc-embedded-flow)[第 13.6 节,“在页面上嵌入流”](spring-faces.html#spring-faces-embedded-mode)
### [](#whatsnew-jsr303)2.3.2。支持 JSR-303 Bean 验证
### 2.3.2.支持 JSR-303 Bean 验证
对 JSR-303 Bean 验证 API 的支持现在可以在 Spring MVC 中提供的等效支持的基础上获得。有关更多详细信息,请参见[第 5.10 节,“验证模型”](views.html#view-validate)
### [](#whatsnew-pc-propagation)2.3.3。流管理的持久性上下文传播
### 2.3.3.流管理的持久性上下文传播
从 Web 流 2.3 开始,管理的流`PersistenceContext`将自动扩展(传播)到子流,假设子流也具有启用的特性。见[第 7.3 节,“流管理的持久性和子流”](flow-managed-persistence.html#flow-managed-persistence-propagation)
### [](#whatsnew-portlet-resource-requests)2.3.4。Portlet2.0 资源请求
### 2.3.4.Portlet2.0 资源请求
现在已经添加了对 Portlet2.0 资源请求的支持,从而支持部分呈现的 Ajax 请求。可以在 JSP 页面中使用`<portlet:resourceURL>`标记来准备此类请求的 URL。服务器端处理类似于一个动作和一个呈现请求的组合,但合并在一个请求中。与呈现请求不同,来自资源请求的响应仅包括来自目标 Portlet 的内容。
### [](#whatsnew-conversation-manager)2.3.5。自定义对话管理器
### 2.3.5.自定义对话管理器
现在,`<flow-execution-repository>`元素提供了一个 conversation-manager 属性,该属性接受对 Conversationmanager 实例的引用。
### [](#whatsnew-redirect-in-same-state)2.3.6。在相同的状态下重定向
### 2.3.6.在相同的状态下重定向
默认情况下,只要当前请求不是 Ajax 请求,在保持相同视图状态时,Web 流就会执行客户端重定向。这在表单验证失败后很有用。点击刷新或返回不会导致浏览器警告。因此,这种行为通常是可取的。然而,一个新的流执行属性使得禁用它成为可能,这在某些特定于 JSF 应用程序的情况下也是必要的。见[第 13.7 节,“在同一状态下重定向”](spring-faces.html#spring-faces-redirect-in-same-state)
### [](#whatsnew-samples)2.3.7。样本
### 2.3.7.样本
建立分布所包括的样本的过程已经简化。 Maven 可用于在一个步骤中构建所有样本。Eclipse 设置包含源代码引用以简化调试。
......@@ -108,17 +108,17 @@ mvn package
```
## [](#whatsnew-swf-220)2.4。 Spring Web 流 2.2
## 2.4. Spring Web 流 2.2
### [](#whatsnew-jsf2)2.4.1。JSF2 支持
### 2.4.1.JSF2 支持
#### [](#d5e180)全面的 JSF2 支持
#### 全面的 JSF2 支持
Spring Web Flow2.2 版本以 2.1 为基础,增加了对核心 JSF2 特性的支持,2.1 中不支持的以下特性现在可用:部分状态保存、JSF2 资源请求、处理和 JSF2Ajax 请求。在这一点上,对 JSF2 的支持被认为是全面的,尽管并不涵盖所有的 JSF2 特性--排除的主要是与 Web 流提供的核心价值重叠的特性,例如与导航和状态管理有关的特性。
有关重要的配置更改,请参见[第 13.3 节,“配置用于 JSF 的 Web 流”](spring-faces.html#spring-faces-webflow-config)。请注意,只支持 Sun Mojarra2.0.3 或更高版本的部分状态保存。它还没有得到 MyFaces 的支持。这是因为 MyFaces 在如何存储组件状态方面不那么容易定制。我们将与 MyFaces 合作提供这种支持。同时,你将需要在`web.xml`中使用`javax.faces.PARTIAL_STATE_SAVING`上下文参数来禁用 Apache MyFaces 的部分状态保存。
#### [](#d5e187)带原始表面组件的旅行样本
#### 带原始表面组件的旅行样本
演示 Spring Web 流和 JSF 支持的主要 Spring 旅行示例现在构建在 JSF2 和来自 PrimeFaces 组件库的组件上。请核对一下分配中的订货面样品。
......@@ -131,34 +131,34 @@ svn co https://src.springframework.org/svn/spring-samples/webflow-primefaces-sho
```
### [](#whatsnew-sec)2.4.2。 Spring 安全 Facelets 标记库
### 2.4.2. Spring 安全 Facelets 标记库
Spring 新的安全标记库可用于 JSF2.0 或 JSF1.2Facelets 视图。它提供了一个 \<authorize\>标记以及几个 EL 函数。有关更多详细信息,请参见[Section 13.9, “Using the Spring Security Facelets Tag Library”](spring-faces.html#spring-faces-security-taglib)
### [](#whatsnew-versions)2.4.3。 Spring JavaScript 更新
### 2.4.3. Spring JavaScript 更新
#### [](#d5e200)弃用资源 servlet
#### 弃用资源 servlet
从 Spring 3.0.4 开始, Spring 框架包括对 ResourcesServlet 的替换。请参阅 Spring 框架文档了解定制 MVC 名称空间的详细信息,特别是新的[“资源”](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources)元素。
#### [](#d5e204)Dojo1.5 和 Dojox
#### Dojo1.5 和 Dojox
捆绑的定制 Dojo 版本升级到了 1.5 版本。它现在包括 Dojox。
请注意,通常鼓励应用程序准备自己的定制 Dojo 构建以优化性能,这取决于 Dojo 的哪些部分通常一起使用。有关示例,请参见 Spring Web 流用于准备自己的定制 Dojo 构建的[scripts](https://src.springframework.org/svn/spring-webflow/branches/spring-webflow-2.2-maintenance/spring-js-resources/scripts/dojo)
#### [](#d5e209)两个 Spring JS 工件
#### 两个 Spring JS 工件
`spring-js`工件被一分为二--新工件(`spring-js-resources`)包含客户端资源(.js、.css 等),而现有工件(`spring-js`)仅包含服务器端 Java 代码。
准备自己的定制 Dojo 构建的应用程序现在有一个选项,可以避免将`spring-js-resources``Spring.js`直接放在其 Web 应用程序的根下面。
#### [](#d5e219)客户端资源移至 meta-inf/web-resources
#### 客户端资源移至 meta-inf/web-resources
捆绑的客户机资源(.js、.css 等)已从其先前位于`META-INF`下的位置移到`META-INF/web-resources`。这种变化对于应用程序是透明的,但是当使用 Spring 3.0.4 中提供的新的资源处理机制时,将导致更简单和更安全的配置。
### [](#whatsnew-jsf-portlet)2.4.4。JSF Portlet 支持
### 2.4.4.JSF Portlet 支持
#### [](#d5e226)Portlet API2.0 和 JSF1.2 支持
#### Portlet API2.0 和 JSF1.2 支持
在 Spring 以前的版本中,对 JSF Portlet 的 Web 流支持依赖于用于 JSF 实现的 Portlet 桥,并且被认为是实验性的。 Spring Web Flow2.2 基于其自身的内部 Portlet 集成,增加了对 JSF Portlet 的支持,该集成以 Portlet API2.0 和 JSF1.2 环境为目标。有关更多详细信息,请参见[???]()。 Spring Web Flow Travel JSF Portlet 示例已经在 Apache Pluto Portal 容器上成功地进行了测试。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册