Spring Web Flow 2.0 简介

Spring实战4之Spring Web Flow篇 一、披萨流程 首先从构建一个高层次的流程开始,它定义了订购披萨的整体流程,然后将其拆分为多个子流程。 1.定义基本流程 当顾客访问Spizza网站时,他们需要进行用户识别、选择一个或多个披萨添加到订单、提供支付信息,然后提交订单,等待披萨上来,如下图: 网上购买披萨的流程 下面展示Spring Web Flow的XML流程定义来实现披萨订单的整体流程:<?xml version="1.0" 阅读详情

Spring Web Flow 2.0 新特性

  Spring Web Flow 是 Spring 的一个子项目,其最主要的目的是解决跨越多个请求的、用户与服务器之间的、有状态交互问题。最新版本为 2.0 ,相比于 1.x 版的 Spring Web Flow ,有以下几个值得注意的新特性。

  与 Spring MVC 深度整合

  Spring Web Flow 1.x 是个自成体系的框架,可与 Spring Web MVC 、 Struts 、 JSF 等 Web 框架整合。最新的 Spring Web Flow 2.0 则明确声明是基于 Spring Web MVC 的一个扩展。

  提供了处理 Ajax 事件的能力

  Ajax 事件的处理与 Web Flow 事件的处理相一致,在处理完成后, flow 即可刷新客户端相关界面代码。

  与 JSF 整合

  通过将 JSF 层层包装,最终可在 Spring Framework 和 Spring Web Flow 中使用 JSF 的各种组件。

  与 Spring Security (原 Acegi Security )整合

  只需将某个 flow 声明为“ secured ”,即 可利用 Spring Security 来确定当前用户是否有权限运行 flow 、激发事件等等。

  更简洁的配置

  官方的数据说同一个 flow , 2.0 版的配置比 1.x 版的配置少 50% 的 XML 代码。

  重用更方便

Spring Web Flow 2.0 提供了 flow 的继承,重用即有的 flow 代码更加容易。

 

 

Spring Web Flow 2.0 就是 Spring Web MVC 的一个扩展,如果粗略一些来讲,所谓 flow 就相当于 Spring Web MVC 中一种特殊的 controller ,这种 controller 可通过 XML 文件加以配置,因此在使用 Spring Web Flow 2.0 前须先对 Spring Web MVC进行配置,步骤如下:

创建 Web 应用的目录结构

  在 /WEB-INF/lib 下导入相关类库

  在 Web 应用部署描述符文件 web.xml 中声明 DispatcherServlet 并指定配置文件

  添加 DispatcherServlet 映射

  创建 web-application-config.xml 文件

  创建 webmvc-config.xml 文件

  创建 index.jsp

  创建 Web 应用的目录结构

  本示例应用将采用 eclipse Dynamic Web Project 向导默认生成的目录结构,在 WEB-INF 目录下添加 config 和 flows 子目录,其中 config 子目录用来存放各种配置文件, flows 子目录下存放 Spring Web Flow 的定义文件。最后目录如图3所示:

  图 2 目录结构

 Spring Web Flow 2.0入门 : 配置 Spring Web MVC

  在 /WEB-INF/lib 下导入相关类库

  只需将以下几个 jar 包导入 /WEB-INF/lib 目录下就可以了:

  commons-logging.jar

  jstl.jar

  standard.jar

  spring-webmvc.jar

  spring.jar

  声明 DispatcherServlet 并指定配置文件

  为使用 Spring Web MVC ,须在 web.xml 中声明 DispatcherServlet ,见清单3:

  清单 3 声明 DispatcherServlet 和指定配置文件

<servlet>
 <servlet-name>CartServlet</servlet-name>
 <servlet-class>
 org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
  /WEB-INF/config/web-application-config.xml
  </param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>

 

添加 DispatcherServlet 映射

  要让 DispatcherServlet 处理所有以 /spring/ 开头的请求,见清单 4:

  清单 4 web.xml 中的 DispatcherServlet映射

<servlet-mapping>
<servlet-name>CartServlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>

创建 web-application-config.xml

  开发基于 Spring Web Flow 的应用往往会有大量的配置,这些配置全放在一个文件中是不合适的。本示例参考 Spring Web Flow 2.0 自带示例,将不同功能的配置文件分开。其中 web-application-config.xml 用于配置与 Web 应用全局相关的内容, Spring Web MVC 的相关配置放在 webmvc-config.xml 中,教程后面要添加的 Spring Web Flow 的配置则放在 webflow-config.xml 中。在 web-application-config.xml 中用 import 元素导入其他的配置文件。 web-application-config.xml的内容见清单5:

  清单 5 web-application-config.xml

<?xml version="1.0" encoding="utf-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  <!-- 搜索 samples.webflow 包里的 @Component 注解,并将其部署到容器中 -->
  <context:component-scan base-package="samples.webflow" />
  <!-- 启用基于注解的配置 -->
  <context:annotation-config />
  <import resource="webmvc-config.xml"/>
</beans>

 

加入注解功能是出于最后运行 Web Flow 示例的需要,在这里只要知道注解功能已被启用就可以了。

创建 webmvc-config.xml

  webmvc-config.xml 主要用于配置 Spring Web MVC 。所要做的就是添加一个 view resolver (视图解析器),用于将视图名解析成真实的视图资源。另外,再配置好 URL 请求的 handler (处理器),用于将 URL 请求定向到某个控制器,在本例中,用到的是 UrlFilenameViewController。

  清单 6 webmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="viewResolver"
   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="viewClass"
   value="org.springframework.web.servlet.view.JstlView"/>
   <property name="prefix" value="/WEB-INF/jsp/"/>
   <property name="suffix" value=".jsp"/>
  </bean>
  <bean id="viewMappings"
   class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
   <property name="defaultHandler">
   <!-- UrlFilenameViewController 会将 "/index" 这样的请求映射成名为 "index" 的视图 -->
   <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
  </property>
 </bean>
</beans>

创建 index.jsp

  现在的 index.jsp 只是显示一行文字。

  清单 7 index.jsp

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Cart Application</title>
 </head>
 <body>
  <h1>Hello!</h1>
 </body>
</html>

  运行应用程序

  将应用程序发布到 Tomcat 容器,再通过 http://localhost:8080/CartApp/spring/index.jsp 访问 index.jsp 页面(应用程序所在文件夹名是 CartApp ),测试 Spring Web MVC 配置是否正确。如果一切正常,可得到如下页面:

  图 3 显示结果

 Spring Web Flow 2.0入门 : 配置 Spring Web MVC

 

配置好 Spring Web MVC 的环境后,接下来就可以往里面加入 Spring Web Flow 2.0 的配置。不过,要搞明白 Spring Web Flow 2.0 的配置,必须先要了解相关的理论知识。

  FlowRegistry

  FlowRegistry 是存放 flow 的仓库,每个定义 flow 的 XML 文档被解析后,都会被分配一个唯一的 id ,并以 FlowDefinition 对象的形式存放在 FlowResigtry 中。 FlowRegistry 配置方式可参看清单 8。

  说明

  以下的示例清单中的 XML 配置元素默认使用了 webflow 名字空间,这也是 Spring Web Flow 习惯上的名字空间,参看教程后面 webflow-config.xml 文件,可以更多了解 webflow 名字空间。

  清单 8 FlowRegistry 的配置

  <webflow:flow-registry id="flowRegistry">

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

  </webflow:flow-registry>

  每个 flow 都必须要有 id 来标识,如果在配置中省略,那么该 flow 默认的 id 将是该定义文件的文件名去掉后缀所得的字符串。

  FlowExecutor

  FlowExecutor 是 Spring Web Flow 的一个核心接口,启动某个 flow ,都要通过这个接口来进行。从配置角度来说,只要保证有个 FlowExecutor 就可以了, Spring Web Flow 的默认行为已经足够。默认配置参看清单9。

  清单 9 FlowExecutor 的配置

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

  哪个 flow 被执行了?

  FlowRegistry 中注册的 flow 可能会有多个,但前面介绍过,每个 flow 都会有 id ,没有配置的,也会有个默认值, FlowExecutor 就是通过 id 来找出要执行的 flow 。至于这个 id ,则是要由用户来指定的。在默认配置情况下,如果客户端发送了如下URL请求:

http://localhost:8080/CartApp/spring/shopping

则从 Spring Web Flow 的角度来看,这个 URL 就表示客户想要执行一个 id 为“ shopping ”的 flow ,于是就会在 FlowRegistry 中查找名为“ shopping ”的 flow,由FlowExecutor负责执行。

 

  Spring Web Flow 如何与 Spring Web MVC 整合在一起?

  客户端发送的请求,先会由 servlet 容器(本教程示例中即为 Tomcat )接收, servlet 容器会找到相应的应用程序(本教程中即为 CartApp ),再根据 web.xml 的配置找到出符合映射条件的 servlet 来处理。 Spring Web MVC 中处理请求的 servlet 是 DispatcherServlet ,如果请求的路径满足 DispatcherServlet 的映射条件,则 DispatcherServlet 会找出 Spring IoC 容器中所有的 HandlerMapping ,根据这些 HandlerMapping 中匹配最好的 handler (一般情况下都是 controller ,即控制器)来处理请求。当 Controller 处理完毕,一般都会返回一个 view (视图)的名字,DispatcherServlet再根据这个view的名字找到相应的视图资源返回给客户端。

  搞清楚 Spring Web MVC 处理请求的流程后,基本上就可以明白要整合 Spring Web MVC 与 Spring Web Flow 所需要的配置了。为了让客户端的请求变成执行某个 flow 的请求,要解决以下几个问题:

  需要在某个 HandlerMapping 中配置负责处理 flow 请求的 handler (或 controller )

  该handler (或 controller )要负责启动指定的 flow

  flow 执行过程中以及执行完成后所涉及的视图应呈现给客户端

  FlowHandler 和 FlowController

  现在,需要一种接收执行 flow 的请求,然后根据请求来启动相应 flow的handler (处理器), Spring Web Flow 2.0 提供了两种方案可供选择。第一种方案是自己编写实现了 FlowHandler 接口的类,让这个类来实现这个功能。第二种方案是使用一个现成的叫做 FlowController 的控制器。第一种方案灵活性比较大,在许多场合可能也是唯一的选择,但对每个 flow 都需要编写相应的 FlowHandler 。本教程的示例采用第二种方案,对 FlowHandler 的介绍可参看 Spring Web Flow 2.0 自带的文档。 FlowController 其实是个适配器,一般来讲,我们只要明白 FlowController 可根据客户端请求的结尾部分,找出相应的 flow 来执行。配置 FlowController只需指定FlowExecutor即可,具体配置见清单10:

清单 10 FlowController 的配置

<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
 <property name="flowExecutor" ref="flowExecutor"/>
</bean>

  另外还需在 HandlerMapping 中指明 /shopping.do 请求由 flowController 来处理,配置见清单11:

  清单 11 在 viewMappings 中添加配置

<bean
 id="viewMappings"
 class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 <property name="mappings">
  <value>
  /shopping.do=flowController
  </value>
 </property>
…...
</bean>

  需要指出的是,不管设成 /shopping.do 还是设成 /shopping ,或者 /shopping.htm ,效果都是一样的, flowController 都会去找 id 为 shopping的flow来执行。

  FlowBuilder Services

  清单 8 所示 FlowRegistry 的配置,其中省略了 flow-registry 元素中一项比较重要的属性, flow-builder-services 。 flow-builder-services 属性的配置指明了在这个 flow-registry “仓库”里的 flow 的一些基本特性,例如,是用 Unified EL 还是 OGNL 、 model (模型)对象中的数据在显示之前是否需要先作转换,等等。在本示例中,我们需要在 flow-builder-services 属性中指明 Spring Web Flow 中所用到的 view ,由 Spring Web MVC 的“ View Resolver ”来查找,由 Spring Web MVC 的“ View Class”来解析,最后呈现给客户。具体配置参看清单12:

  清单 12 flow-builder-services 配置

<webflow:flow-builder-services id="flowBuilderServices"
 view-factory-creator="mvcViewFactoryCreator"/>
<bean
 id="mvcViewFactoryCreator"
 class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
 <property name="viewResolvers" ref="viewResolver"/>
</bean>

  Spring Web Flow 2.0 配置小结

  所有这些配置的目的无非是两个:一是要让客户端的请求转变成 flow 的执行,二是要让 flow 执行过程中、或执行结束后得到的视图能返还给客户端。如果对这里的讲解还不是很清楚,可先看下一节实际的配置,再回过头来看本章内容,以加深理解。

 

 

 

要了解 Spring Web Flow 是什么东西,最好的办法莫过于查看示例,图 2 展示了一个简化的购物车的流程。

  图 1 购物车示例

 Spring Web Flow 2.0 入门 : 购物车用例   

  图 2 所示流程用 Spring Web Flow 2.0 的配置文件表示如下:

  清单 1 用 Spring Web Flow 语义表达购物车流程

……
<flow>
<view-state id="viewCart">
<transition on="submit" to="viewOrder"/>
</view-state>
<view-state id="viewOrder">
<transition on="confirm" to="viewConfirmed"/>
</view-state>
<view-state id="viewConfirmed">
<transition on="returnToIndex" to="returnToIndex"/>
</view-state>
<end-state id="returnToIndex"/>
</flow>

  清单 1 省略了许多技术细节,展示的只是一个业务的流程,主要是为了让大家对 Spring Web Flow 的语义有个初始的印象。从清单 1 中,应注意到一个很重要的特征—— Spring Web Flow 语义与 Servlet API 无关。更确切地讲, Spring Web Flow 语义关注的是业务的流程,并未与 Sun 公司的 Web 规范紧密结合,这种描述是更高层次的抽象,差不多是在建模的角度来描述业务流程。

  不过, Spring Web Flow 也并非只有抽象,现在还没有哪一种工具或语言可以将一个模型直接转换成相应的应用程序。 Spring Web Flow 更像是抽象建模和技术细节的混血儿,相比于湮没在繁多的控制器和视图中的 Web MVC 应用来讲, Spring Web Flow 提供了如清单 1 所描述的更高层次的抽象,但同时它也整合了像 Unified EL 这样的工具来控制技术上的细节。

  Spring Web Flow 的基本元素

  Flow 可看作是客户端与服务器的一次对话( conversation )。 Flow 的完成要由分多个步骤来实现,在 Spring Web Flow 的语义中,步骤指的就是 state 。 Spring Web Flow 提供了五种 state ,分别是 Action State 、 View State 、 Subflow State 、 Decision State 、 End State ,这些 state 可用于定义 flow 执行过程中的各个步骤。除了 End State 外,其他 state 都可以转换到别的 state ,一般通过在 state 中定义 transition 来实现到其他 state 的转换,转换的发生一般由事件( event )来触发。

 

实现示例应用的购物车流程,可按以下步骤操作:

  在 /WEB-INF/lib 目录下导入相关类库

  在 webmvc-config.xml 中添加与 Spring Web Flow 集成的配置

  添加 Spring Web Flow 的配置文件 webflow-config.xml

  添加 flow 定义文件 shopping.xml

  添加三个 jsp 页面

修改 index.jsp

 

  在 /WEB-INF/lib 目录下导入相关类库

  将以下几个 jar 包导入 /WEB-INF/lib 目录:

  org.springframework.webflow-2.0.2.RELEASE.jar

  org.springframework.js-2.0.2.RELEASE.jar

  org.springframework.binding-2.0.2.RELEASE.jar

jboss-el.jar

 

  在 webmvc-config.xml 中添加配置

  Spring Web MVC 相关的配置前面已经分析过了,完整的配置见清单 13 :

  清单 13 webmvc-config.xml<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean
  id="viewResolver"
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView">
  </property>
  <property name="prefix" value="/WEB-INF/jsp/">
  </property>
  <property name="suffix" value=".jsp">
  </property>
 </bean>
 <bean
  id="viewMappings"
  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  <!-- /shopping.do 请求由 flowController 来处理 -->
  <property name="mappings">
   <value> /shopping.do=flowController </value>
  </property>
  <property name="defaultHandler">
  <!-- UrlFilenameViewController 会将 "/index" 这样的请求映射成名为 "index" 的视图 -->
   <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
  </property>
 </bean>
 <bean
  id="flowController"
  class="org.springframework.webflow.mvc.servlet.FlowController">
  <property name="flowExecutor" ref="flowExecutor"/>
 </bean>
</beans>

 

添加配置文件 webflow-config.xml

  在 /WEB-INF/config 目录下添加 webflow-config.xml 文件, schema 名字空间可直接复制清单 14 中的内容。

  清单 14 webflow-config.xml<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:webflow="http://www.springframework.org/schema/webflow-config"
 xsi:schemaLocation=" http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/webflow-config
  http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
 <webflow:flow-executor id="flowExecutor"/>
 <!— 所有 flow 定义文件位置在此配置, flow-builder-services 用于配置 flow 的特性 -->
 <webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
  <webflow:flow-location path="/WEB-INF/flows/shopping.xml" id="shopping"/>
 </webflow:flow-registry>
 <!—Web Flow 中的视图通过 MVC 框架的视图技术来呈现 -->
 <webflow:flow-builder-services id="flowBuilderServices"
  view-factory-creator="mvcViewFactoryCreator"/>
 <!— 指明 MVC 框架的 view resolver ,用于通过 view 名查找资源 -->
 <bean id="mvcViewFactoryCreator"
  class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
  <property name="viewResolvers" ref="viewResolver"/>
 </bean>
</beans>

 

webflow-config.xml 创建完成以后,不要忘记在 web-application-config.xml 中添加 import 元素,将 webflow-config.xml 文件导入。

  清单 15 在 web-application-config.xml 中导入 webflow-config.xml。<import resource="webflow-config.xml"/>

  添加 flow 定义文件 shopping.xml

  在 /WEB-INF/flows 目录下创建 shopping.xml 文件,描述了图 2 所示的流程。

  清单 16 shopping.xml<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<view-state id="viewCart" view="viewCart">
<transition on="submit" to="viewOrder">
</transition>
</view-state>
<view-state id="viewOrder" view="viewOrder">
<transition on="confirm" to="orderConfirmed">
</transition>
</view-state>
<view-state id="orderConfirmed" view="orderConfirmed">
<transition on="returnToIndex" to="returnToIndex">
</transition>
</view-state>
<end-state id="returnToIndex" view="externalRedirect:servletRelative:/index.jsp">
</end-state>
</flow>

 

与清单 1 相比,在 view-state 元素中指定了 view 属性的名字,这个名字也是 Spring Web MVC 中 viewResolver 所查找的 view 的名字。从清单 16 的配置中可以知道,这三个 view-state 元素所对应的视图资源分别应该是: viewCart.jsp 、 viewOrder.jsp 和 orderConfirmed.jsp 。清单 16 中最后的 end-state 指明了当 flow 执行结束后跳转到初始的 index.jsp 页面,在此处的 view 属性的名字需要解释一下。 externalRedirect 用在 view 名字中,表示所指向的资源是在 flow 的外部, servletRelative 则表明所指向资源的路径起始部分与 flow 所在 servlet 相同。 Spring Web Flow 2.0还提供了其他几个关键词用于重定向,这里就不多介绍了。

 

  添加三个 jsp 页面

  在 /WEB-INF/jsp 目录下创建三个 flow 所需的视图资源。以下清单只给出 jsp 页面中 body 元素以内的代码,其余省略。

  清单 17 viewCart.jsp<h1>View Cart</h1>
<a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
清单 18 viewOrder.jsp<h1>Order</h1>
<a href="${flowExecutionUrl}&_eventId=confirm">Confirm</a>
清单 19 orderConfirmed.jsp<h1>Order Confirmed</h1>
<a href="${flowExecutionUrl}&_eventId=returnToIndex">Return to index</a>

  这几个页面都使用了变量 flowExecutionUrl ,表示 flow 执行到当前状态时的 URL 。 flowExecutionUrl 的值已经由 Spring Web Flow 2.0 框架的代码进行赋值,并放入相应的 model 中供 view 访问。 flowExecutionUrl 的值包含 flow 在执行过程中会为每一状态生成的唯一的 key ,因此不可用其他手段来获取。请求参数中 _eventId 的值与清单 16 中 transition 元素的 on 属性的值是对应的,在接收到_eventId参数后,相应transition会被执行。

  修改 index.jsp 页面

  在 index.jsp 页面中添加启动 flow 的链接,从 webmvc-config.xml 配置文件中可以看出,要启动 flow ,只需提供 /shopping.do 链接即可。

  清单 20 index.jsp<h1>Hello!</h1><br/>
<a href="shopping.do">View Cart</a>

  运行应用程序

  将应用程序发布到 Tomcat 服务器,访问 index.jsp ,并启动 flow ,测试页面的跳转。效果如图 5所示:

  图 4 flow 运行效果

 Spring Web Flow 2.0入门 : 在购物车示例应用中配置 Spring Web Flow 

 

 

到现在为止,这个购物车应用只是实现了页面之间的跳转,接下来我们要实现与业务逻辑相关的功能。由于本教程的重点在于介绍如何应用 Spring Web Flow ,所实现的业务比较简单,与实际应用有较大的距离,请读者谅解。

  业务的逻辑涉及到数据的获取、传递、保存,相关的业务功能函数的调用等内容,这些功能的实现都可用 Java 代码来完成,但定义 Spring Web Flow 的语法与 Java 是无关的,这就要求 Spring Web Flow 提供与 Java 代码的整合机制。要了解这种机制,关键在于搞清楚两个问题:

  业务逻辑代码在什么时候被调用?

业务逻辑代码在调用后得到的数据如何保存、传递?

 

业务逻辑代码在什么时候被调用?

  在 Spring Web Flow 中,业务逻辑代码的执行可由以下三种情形来触发:

  客户端请求中包含了 _eventId 参数

  执行到框架自定义的切入点

执行到 <action-state> 元素

 

  客户端请求中包含了 _eventId 参数

  这种方式一般用在 state 之间的 transition ,通过指定 _eventId 参数的值,表明了客户的行为,从而导致相应事件的发生,在 Spring Web Flow 的定义文件中可以通过 evaluate 元素来指定要处理的业务逻辑。参看清单21:

  清单 21 transition 示例

<transition on="submit">
<evaluate expression="validator.validate()" />
</transition>

  清单 21 的代码表示,当客户端的请求中包含“ _eventId=submit ”,则 evaluate 元素中 expression 属性所指明的表达式会被执行,即 validator 对象的validate 方法会得到调用。

  执行到框架自定义的切入点

  Spring Web Flow 定义了 5 个切入点,通过 flow 定义文件的配置,可在这 5 个切入点插入相关业务逻辑代码。

  表 2 Spring Web Flow 自定义的切入点

  

切入点名称

XML 元素名称

触发时刻

flow start

on-start

flow 执行之前

state entry

on-entry

进入某个 state 之后,做其他事情之前

view render

on-render

在进入 view 的 render 流程之后,在 view 真正 render出来之前

state exit

on-exit

在退出 state 之前

flow end

on-end

flow 执行结束之后

  清单 22 给出了在 view render 切入点插入业务逻辑代码的例子:

  清单 22 on-render 元素

<view-state id="viewCart" view="viewCart" >
 <on-render>
  <evaluate expression="productService.getProducts()"
   result="viewScope.products"/>
 </on-render>
</view-state>

  执行到 <action-state> 元素

  Spring Web Flow 中的这个 <action-state> 是专为执行业务逻辑而设的 state 。如果某个应用的业务逻辑代码即不适合放在 transition 中由客户端来触发,也不适合放在 Spring Web Flow 自定义的切入点,那么就可以考虑添加 <action-state> 元素专用于该业务逻辑的执行。示例代码参看清单23:

  清单 23 action-state 示例

<action-state id="addToCart">
 <evaluate expression="cart.addItem(productService.getProduct(productId))"/>
 <transition to="productAdded"/>
</action-state>

 

业务逻辑代码在调用后得到的数据如何保存、传递?

  Spring Web Flow 的定义中可直接使用表达式语言( Expression Language ),前面的代码都是用的 Unified EL ,对于习惯用 OGNL 的开发人员,可通过 flow-builder-services 的配置改成使用 OGNL 。不管是哪一种表达式语言, Spring Web Flow 都提供了一些固定名称的变量,用于数据的保存、传递。在 Spring Web Flow 的解决方案 一节中,已经提到 Spring Web Flow 所着力解决的问题即是数据存取范围的问题,为此, Spring Web Flow 提供了两种比较重要的范围,一是 flow 范围,另一个是 conversation 范围。通过 flowScope 和 conversationScope 这两个变量, Spring Web Flow 提供了在这两种范围里存取数据的方法。清单 24演示了如何将业务逻辑代码执行的结果存放到flow范围中。

  清单 24 flowScope 示例

<evaluate expression="productService.getProducts()" result="flowScope.products" />

  Spring Web Flow 还提供了大量其他的变量,以方便数据的存取。如 viewScope 范围即是从进入 view-state 至退出 view-state 结束, requestScope 即和一般的 request 范围没什么区别,等等。另外还有一些用于获取 flow 以外数据的变量,如 requestParameters 、 messageContext 等等。具体变量的列表可参看 Spring Web Flow自带的文档。

  

为示例应用添加商品

  接下来,我们要在示例应用的 viewCart.jsp 页面中添加商品,可按以下步骤操作:

  添加 Product 类

  添加 ProductService 类

  修改 shopping.xml 文件

  修改 viewCart.jsp 页面

  

添加 Product 类

  Product 类是个普通的 JavaBean ,用于定义商品( Product )的一般属性,同时也提供了构造方法。由于会把 Product 存放于 conversationScope 中, Product 实现了 Serializable 接口。具体见清单25:

  清单 25 Product 类

package samples.webflow;
import java.io.Serializable;
public class Product implements Serializable {
  private static final long serialVersionUID = 1951520003958305899L;
  private int id;
  private String description;
  private int price;
  
  
public Product(int id, String description, int price) {
    this.id = id;
    this.description = description;
    this.price = price;
  }
  /*省略getter和setter*/
}

  添加 ProductService 类

  ProductService 主要提供商品列表,并能根据商品的 id 查找出该商品,由于示例较简单,这里只添加了三条纪录。见清单 26:

  清单 26 ProductService 类

package samples.webflow;
/*
省略import语句*/
@Service("productService")
public class ProductService {
  /*products 用于存放多个商品 */
  private Map<Integer, Product> products = new HashMap<Integer, Product>();
  
  public ProductService() {
    products.put(1, new Product(1, "Bulldog", 1000));
    products.put(2, new Product(2, "Chihuahua", 1500));
    products.put(3, new Product(3, "Labrador", 2000));
  }
  
  
public List<Product> getProducts() {
    return new ArrayList<Product>(products.values());
  }
  
  
public Product getProduct(int productId) {
    return products.get(productId);
  }
}

  Service 注解表示 Spring IoC 容器会初始化一个名为 productService 的 Bean ,这个 Bean 可在 Spring Web Flow 的定义中直接访问。

  修改 shopping.xml 文件

  要在 viewCart 页面中显示商品,只需在 view-state 元素的 on-render 切入点调用 productService 的 getProducts 方法,并将所得结果保存到 viewScope 中即可。见清单27:

  清单 27 shopping.xml 需修改的部分

<view-state id="viewCart" view="viewCart" >
 <on-render>
  <evaluate expression="productService.getProducts()" result="viewScope.products"/>
 </on-render>
 <transition on="submit" to="viewOrder"> </transition>
</view-state>

  修改 viewCart.jsp 页面

  清单 27 表明 productService 的 getProducts 方法所得的结果会存放在 viewScope 中名为 products 的变量中, jsp 页面的代码可直接访问该变量。见清单 28:

  清单 28 修改后的 viewCart.jsp 页面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>View Cart</title>
</head>
<body>
<h1>View Cart</h1>
<h2>Items in Your Cart</h2>
<a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
<h2>Products for Your Choice</h2>
<table>
<c:forEach var="product" items="${products}">
<tr>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
</body>
</html>

  运行应用程序

  图 5 viewCart.jsp 页面效果

 Spring Web Flow 2.0 入门 :  用 Unified EL 实现业务逻辑 

 

商品已经有列表了,接下来就要增加把商品放入购物车的功能,在本示例中用 subflow 来实现这一功能,操作步骤如下:

  实现 Cart 和 CartItem 两个业务类

  在 shopping.xml 中添加配置

  在 /WEB-INF/flows 目录下添加 addToCart.xml

  在 webflow-config.xml 中添加 addToCart.xml 的位置

修改 viewCart.jsp 页面

 

实现 Cart 和 CartItem 两个业务类

  CartItem 表示存放于购物车中的条目,主要记录相应商品及商品数量,同时不要忘记实现 java.io.Serializable 接口,见清单 29:

  清单 29 CartItem 类

package samples.webflow;
import java.io.Serializable;
public class CartItem implements Serializable {
  private static final long serialVersionUID = 8388627124326126637L;
  private Product product;
  private int quantity;
  public CartItem(Product product, int quantity) {
    this.product = product;
    this.quantity = quantity;
  }
  public int getTotalPrice() {
    return this.quantity * this.product.getPrice();
  }
  public void increaseQuantity() {
    this.quantity++;
  }
  /*省略getter和setter*/
}

  除去相应的属性外, CartItem 可根据商品的数量算出该商品的总价格( getTotalPrice ),也可通过 increaseQuantity 增加商品数量。

  Cart 是购物车的实现类,其同样要实现 java.io.Serializable 接口,但它没有像 ProductService 一样成为由 Spring IoC 容器管理的 Bean ,每个客户的购物车是不同的,因此不能使用 Spring IoC 容器默认的 Singleton 模式。见清单 30:

 

清单 30 Cart 类

package samples.webflow;
/*
省略 import 语句 */
public class Cart implements Serializable {
  private static final long serialVersionUID = 7901330827203016310L;
  private Map<Integer, CartItem> map = new HashMap<Integer, CartItem>();
  public List<CartItem> getItems() {
    return new ArrayList<CartItem>(map.values());
  }
  public void addItem(Product product) {
    int id = product.getId();
    CartItem item = map.get(id);
    if (item != null)
      item.increaseQuantity();
    else
      map.put(id, new CartItem(product, 1));
   }
  public int getTotalPrice() {
    int total = 0;
    for (CartItem item : map.values())
      total += item.getProduct().getPrice() * item.getQuantity();
    return total;
  }
}

  Cart 主要实现三个业务函数, getItems 用于获取当前购物车里的物品, addItem 用于向购物车添加商品, getTotalPrice 用于获取购物车里所有商品的总价格。

  在 shopping.xml 中添加配置

  在 shopping flow 开始时必须分配一个 Cart 对象,由于要调用 subflow ,这个 Cart 对象应存放于 conversationScope 中。同时要添加一个 subflow-state 用于执行添加商品到购物车的任务。

  清单 31 shopping.xml 中添加的配置

<var name="mycart" class="samples.webflow.Cart"/>
<on-start>
 <set name="conversationScope.cart" value="mycart"></set>
</on-start>
<view-state id="viewCart" view="viewCart" >
 <on-render>
  <evaluate expression="productService.getProducts()" result="viewScope.products"/>
 </on-render>
 <transition on="submit" to="viewOrder"/>
 <transition on="addToCart" to="addProductToCart"/>
</view-state>
<subflow-state id="addProductToCart" subflow="addToCart">
 <transition on="productAdded" to="viewCart" />
</subflow-state>

 

在 /WEB-INF/flows 目录下添加 addToCart.xml

  清单 31 中 subflow-state 元素的 subflow 属性即指明了这个被调用的 flow 的 id 为“ addToCart ”,现在就要添加addToCart flow的定义。

  清单 32 addToCart.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/webflow
  http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
 <on-start>
  <set name="requestScope.productId" value="requestParameters.productId"/>
 </on-start>
 <action-state id="addToCart">
  <evaluate expression="cart.addItem(productService.getProduct(productId))"/>
  <transition to="productAdded"/>
 </action-state>
 <end-state id="productAdded"/>
</flow>

  addToCart flow 主要由一个 action-state 构成,完成添加商品到购物车的功能, addToCart flow 的实现需要有输入参数,即 productId 。在本示例中是通过请求参数来传递,通过 requestParameters 来获取该数值。这里还要注意到清单 32 中的 end-state 的 id 为“ productAdded ”,与清单 31 中 subflow-state 中的 transition元素的on属性的名称是对应的。

 

在 webflow-config.xml 中添加 addToCart.xml 的位置

  新增加的 flow 不要忘记在 flow-registry 中注册。

  清单 33 flow-registry 中注册 addToCart

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

  修改 viewCart.jsp 页面

  最后就可以来看在视图中如何显示相关的信息,并触发相应的 webflow 事件,见清单 34:

  清单 34 完整的 viewCart.jsp 的代码

<h1>View Cart</h1>
<h2>Items in Your Cart</h2>
<c:choose>
<c:when test="${empty cart.items}">
<p>Your cart is empty.</p>
</c:when>
<c:otherwise>
<table border="1" cellspacing="0">
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
<c:forEach var="item" items="${cart.items}">
<tr>
<td>${item.product.description}</td>
<td>${item.quantity}</td>
<td>${item.product.price}</td>
<td>${item.totalPrice}</td>
</tr>
</c:forEach>
<tr>
<td>TOTAL:</td>
<td></td>
<td></td>
<td>${cart.totalPrice}</td>
</tr>
</table>
</c:otherwise>
</c:choose>
<a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
<h2>Products for Your Choice</h2>
<table>
<c:forEach var="product" items="${products}">
<tr>
<td>${product.description}</td>
<td>${product.price}</td>
<td>
<a href="${flowExecutionUrl}&_eventId=addToCart&productId=${product.id}">[add to cart]</a>
</td>
</tr>
</c:forEach>
</table>

  运行效果

  图 6 添加购物车后的效果

 Spring Web Flow 2.0 入门 : 用 subflow 实现添加商品到购物车功能

global transition

 顾名思义, global transition 是一种全局的 transition ,可在 flow 执行的各个 state 中被触发。

  清单 35 global-transitons

<global-transitions>
 <transition on="cancelShopping" to="returnToIndex"/>
</global-transitions>

  客户端请求中如果包含 _eventId=cancelShopping ,则会重新回到 index.jsp 页面。

 

 

 

 前面讲了, Spring Web Flow 提供了描述业务流程的抽象能力,但对一种 Web 开发技术而言,仅有这些是不够的。同时, Spring Web Flow 是不是能够取代其他 Web MVC 技术?或者在任何情况下都应优先使用 Spring Web Flow ?要回答这些问题,先来看一下 Spring Web Flow 所着力解决的技术问题。

  Web 应用程序的三种范围

  Java Servlet 规范为 Web 应用程序中用到的各种对象规定了三种范围( scope ),分别是 request 范围、 session 范围和 application 范围。

  request 范围中的对象是跟客户的请求绑定在一起的,每次请求结束都会销毁对象,而新的请求过来时又会重新创建对象。 request 范围适合存放数据量较大的临时数据。

  session 范围中的对象是跟会话( session )绑定在一起的,每次会话结束会销毁这些对象,而新的会话中又会重新创建。 HTTP 协议本身是无状态的,服务器和客户端要实现会话的管理,只能借助于一些辅助的手段,如在协议的数据包中加一些隐藏的记号,等等。 session 范围适合存放本次会话需要保留的数据。

  application 范围的对象是跟应用程序本身绑定在一起,从 Servlet API 的角度来讲,就是存放在 ServletContext 中的对象,它们随着 Servlet 的启动而创建, Servlet 关闭时才会销毁。 application 范围适合存放那些与应用程序全局相关的数据。

  现实开发中最令人头痛的莫过于 session 范围, Java Servlet 规范指明可在 web.xml 中按如下方式配置 session 的有效时间为100分钟:

  清单 2 web.xml 中 session 的配置

<session-config>
<session-timeout>100</session-timeout>
</session-config>

  然而,现实中的 session 范围更像是“鸡肋”,把大量数据放入 session 会导致严重的效率问题,在分布式的环境中处理 session 范围更是一不小心就会出错,但抛弃 session 又会给开发带来许多不便。 request 范围虽说能存放量大的数据,但有效范围有限。摆在开发者面前的很多用例都要求一种比 request 范围要长,但又比 session 范围要短的这么一种有效范围。

  Spring Web Flow 的解决方案

  针对 Java Servlet 规范中的这个缺陷, Spring Web Flow 2.0 中提供了以下两种范围:

  flow 范围。此范围内的对象在 flow 开始时创建, flow 结束时销毁,在 flow 定义文件中可通过“ flowScope ”变量名来访问。

  conversation 范围。此范围内的对象与 flow 范围对象基本相似,唯一不同在于 conversation 范围内的对象所在的 flow 如果调用了其他 subflow ,那么在 subflow 中也可访问该对象。

  备注:subflow 定义:被其他 flow 所调用的 flow 即可称为 subflow。

  由于 flow 是由开发人员自己定义的,可根据业务的需求自由改变, flow 范围和 conversation 范围的使用也就突破了 Java Servlet 规范中 session 范围和 request 范围的局限,真正做到了自由定制。

  并非所有情形都适用 Spring Web Flow

  可以看出, Spring Web Flow 所着力解决的问题即是客户端与服务器的对话( conversation )问题,这个范围比 request 要长,而比 session 要短。为实现 conversation 范围(即 flow 范围),需要付出效率上的代价,因此,并非所有 Web 应用都适合使用 Spring Web Flow 。 Seth Ladd 等人所著 Expert Spring MVC and Web Flow 一书,对何时使用Spring Web Flow,列出了如下表格。

  表 1 何时使用 Spring Web Flow

  

解决方案

何时使用

Spring MVC Controller

某个单独的、只需较少业务逻辑就可创建的页面,同时该页面不是 flow 的一部分

Spring MVC SimpleFormController

某个只涉及表单提交的页面,如一个搜索框

Spring MVC AbstractWizardFormController

由一系列导航页面组成的业务过程

Spring Web Flow

任何比较复杂的、有状态的、需要在多个页面之间跳转的业务过程

  Spring Web Flow 的其他特点

  Web Flow 作为一个单独的概念被提出来,也可算是 Spring Web Flow 的一大亮点。目前大多数 Web MVC 框架都把重点把在各种 controller 和形形色色的 view 技术上面,对 Web 应用流程本身的关注是不够的, Web Flow 的提出就提供了一层抽象,设计者就可以从 Web Flow 抽象层面来进行设计、开发。当然, Web Flow 不能理解为只是 Web 页面间的跳转流程,定义 Spring Web Flow 的语义并非只限于页面之间的跳转,而可以是 Web 应用中的各种行为。由此,用例的模型建构好以后,就可直接从该模型转换到相应的 Web Flow,开发人员的设计变得更加直观、有效。

  另外,在 Spring Web Flow 中重用 Web Flow 是比较容易的。在定义 flow 、 state 时可通过继承某个已有的 flow 或 state ,来避免重复定义。同时,一个 flow 可以调用其它 flow ,就跟一般程序语言中在某个函数内部调用其它函数一样方便。

 

Spring Web Flow 是一种用于构建复杂、对话驱动型 Web 应用程序的框架 Spring Web Flow 2.3.1 是一个维护版本,主要用于修复已知问题和改进稳定性。此版本并未引入大量新功能,而是专注于提高现有特性的健壮性和兼容性。综上所述,Spring Web Flow 2.3.1 虽然属于一个小规模迭代版本,但在解决先前存在的诸多痛点以及提升用户体验等方面做出了积极贡献。无论是从功能性还是易用性角度来看,都值得广大使用者关注并及时迁移到最新版以享受更好的技术支持和服务保障。 阅读详情

相关推荐

黄色手机app应用介绍网站模板

黄色手机app应用介绍网站模板

Java后台框架篇--Spring之WebFlow

1.构建webflow2.3.3环境(2.0以上应该都可以) 导入webflow的jar包+springmvc的一些必须包,目录结构如下 2.配置webflow(spring-wf.xml) [html] view plain copy xml version="1.0" encoding="UTF-8"?>   beans x

非淡泊无以明志,非宁静无以致远 5266

光纤布拉格光栅(FBG)笔记【1】:波导结构和布拉格波长推导

引言 本文是光纤布拉格光栅(FBG)的笔记【1】,主要介绍了光纤布拉格光栅的波导结构,并且利用动量和能量守恒推导了光纤布拉格波长的表达式 普通光纤中让折射率发生周期性变化就是结构最简单的均匀光纤布拉格光栅(FBG),其波导结构如下图所示。 其传感原理描述可以分为以下的三点: ①光纤纤芯传播的光会在每个光栅面进行反射和透射; ②如果不满足布拉格条件,依次排列的光栅平面反射的光会逐渐变得不同直到最后相互抵消;同时由于系数不匹配,与布拉格波长不相符的光在每个光栅平面的反射也很微弱,这些光大部分在光纤中发生透.

subtitle_的博客 2万+

Spring Web Flow入门(带详细注释)

确认支付Item1:加入购物车Item2:加入购物车Item2:加入购物车

m0_62089210的博客 1936

华为Atlas200DK实战指南:从零搭建AI开发环境到人像语义分割模型部署

本文提供了一份详尽的华为Atlas 200DK AI开发环境搭建与模型部署实战指南。文章采用合设环境方案,从SD卡准备、系统镜像烧录、网络配置到必备工具安装,逐步引导开发者完成环境搭建。核心部分详细讲解了如何利用华为ATC工具将TensorFlow模型转换为昇腾专用格式,并最终成功编译和运行人像语义分割模型,实现实时人像识别效果。

weixin_29309213的博客 356

Android车载多屏开发实战:从零搭建同显/异显Demo(附源码)

本文详细介绍了Android车载多屏开发的实战经验,从零搭建同显/异显Demo,涵盖多屏模拟、核心API调用、同显/异显架构实现及性能优化等关键环节。通过C++构建完整开发链路,帮助开发者快速掌握多屏同显和多屏异显技术,提升智能座舱系统的交互体验。附源码供参考。

weixin_29233857的博客 404

「Java开发指南」如何用MyEclipse完成Spring Web Flow 2.0搭建?

本教程将引导开发者如何使用Spring Annotator实现Spring控制器,欢迎下载最新版IDE体验!

需要界面开发、IDE工具研发中文教程资料的小伙伴,记得私信我~ 705

【AI实践】Dify调用本地和在线模型服务

Ollama可以本地部署模型,如何集成私有数据、如何外部应用程序对接,因此需要有一个应用开发框架。ip地址需要换成自己电脑的IP地址;模型名称需要和Ollama模型名称保持一致;docker是虚拟环境的主机,Ollama部署在本地主机,无法通过本机访问。找到Ollama,配置本地Ollama已经验证的模型,如phi3。在docker页面里面,也可以看到running。docker已经安装完成的情况下。,打开dify,注册登录后。在工作区选择调用即可。

AI_Gump的博客 4855

Spring Web Flow 2.0.0.RC1已经发布,这是一个重要的里程碑版本,它带来了许多改进和新特性

Spring Web Flow是一个用于构建基于Web的应用程序的框架,它提供了一种声明式的方式来定义和管理Web应用程序的流程控制。我们还建议Web Flow 1用户此时开始评估其对Web Flow 2的升级,因为RC1引入了全面的版本2文档以及用于自动将版本1流转换为版本2语法的工具。总的来说,Spring Web Flow 2.0.0.RC1是一个值得期待的版本,它为开发者提供了更多的灵活性和便利性,使得他们可以更容易地构建复杂的Web应用程序。你可以通过访问特定的URL来触发一个流程实例,例如。

[Blog][Domain] programb.blog.youkuaiyun.com 532

基于 STM32 设计的 HC05 蓝牙音箱

本项目介绍如何使用 STM32 微控制器和 HC05 蓝牙模块设计一个简单的蓝牙音箱。该音箱可以接收来自手机或其他蓝牙设备的音频数据,并通过扬声器播放。该项目展示了如何使用 STM32 微控制器和 HC05 蓝牙模块设计一个简单的蓝牙音箱。易于实现功能实用可扩展性强如果您需要开发一个蓝牙音箱,该项目可以作为参考。

走向CTO的路上... 2471

AI在保险产品定价优化中的创新应用

在当今保险市场中,准确合理的产品定价是保险公司实现可持续发展的关键因素之一。传统的保险产品定价主要基于经验数据和精算模型,但这种方式往往存在数据处理效率低、对复杂风险因素考虑不足等问题。本文的目的在于深入探讨AI技术如何在保险产品定价中进行创新应用,以提高定价的准确性、效率和灵活性,更好地满足市场需求和客户个性化需求。本文的范围涵盖了AI技术在保险产品定价各个环节的应用,包括风险评估、费率计算、产品设计等方面。同时,还会涉及到相关的核心算法、数学模型以及实际应用案例等内容。

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 983

Spring Web Flow 2.0 入门

开始之前 关于本教程 本教程通过一个简化的购物车应用,介绍了如何使用 Spring Web Flow 2.0 来构建 Web 应用程序。本教程以讲解实例为主,为了读者更好地理解 Spring Web Flow ,也有部分理论的解释。 先决条件 本教程要求读者具备 Java Web 应用的基本知识、熟悉 Spring Framework 的应用。 系统要求 运行本教程中的示例,需要下列工

ichsonx的专栏 1450

Dify智能体开发:Dify文件上传

相较于聊天文本,文档文件能够承载大量的信息,例如学术报告、法律合同。受限于 LLM 自身仅能够支持文件或图片,难以获取文件内更加丰富的上下文信息,应用的使用者不得不手动复制粘贴大量信息与 LLM 对话,增加了许多不必要的使用成本。

王国平的博客 2591

Spring Web Flow 2.2.0 Released

News and Events Rossen Stoyanchev October 12, 2010 I’m pleased to announce the availability of Spring Web Flow 2.2: JSF 2 support Spring Travel sample application built on JSF 2 and PrimeFaces components Facelets tag library for Spring Security dojo 1.5 an

[Blog][Domain] programb.blog.youkuaiyun.com 194

【CUDA编程部署教程】第一章:GPU架构与CUDA编程核心 1

我们将剖析现代GPU的计算心脏——流式多处理器(SM),理解其独特的Warp执行模型,探索Tensor Core带来的革命性矩阵运算加速,并深入探讨决定性能命脉的内存体系。当必须访问全局内存时,则必须遵循**合并访问(Coalesced Access)**的原则,即让一个Warp内的32个线程访问连续的内存地址,从而让硬件将多次访问合并为一次高效的内存事务,以充分利用带宽。SM的调度器以Warp为单位分派指令,在一个Warp内,所有32个线程在同一时刻执行完全相同的指令,但处理的数据不同,这种模型被称为。

VectorShift的博客 221

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

转 Spring Web Flow 2.0入门 - 配备Spring Web Flow 2.0的基础

详细请点击:http://www.verydemo.com/demo_c143_i15669.html 转 Spring Web Flow 2.0入门 - 配置Spring Web Flow 2.0的基础

jiangjun072685153的专栏 392

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring Web Flow 2.0.9 Released

Releases Keith Donald April 15, 2010 Dear Spring Community, We are pleased to announce that Spring Web Flow 2.0.9 is now available. Download | Reference Documentation | Change Log This release includes a number of minor bug fixes, as well as an update to t

[Blog][Domain] programb.blog.youkuaiyun.com 402

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Spring Web Flow 2.0 入门 配置 Spring Web Flow 2.0 的基础

第 6 页,共 15 页文档选项<!--document.write(打印本页);//-->打印本页样例代码

518

转 Spring Web Flow 2.0入门 - 配置Spring Web Flow 2.0的基础

[size=medium]配置好 Spring Web MVC 的环境后,接下来就可以往里面加入 Spring Web Flow 2.0 的配置。不过,要搞明白 Spring Web Flow 2.0 的配置,必须先要了解相关的理论知识。 FlowRegistry FlowRegistry 是存放 flow 的仓库,每个定义 flow 的 XML 文档被解析后,都会被分配一个唯一的 i...

游云的专栏 277

Spring Web Flow 2.0 入门详解

转自:http://www.cnblogs.com/xwdreamer/archive/2011/11/10/2296939.html Spring Web Flow 2.0 入门详解 目录: 参考文献购物车用例什么情况下可以使用 Spring Web Flow?配置 Spring Web MVC配置 Spring Web Flow 2.0 的基础在购物车示例应用

sunshingheavy的专栏 680
上一篇: 使用 Spring 2.5 TestContext 测试框架
下一篇: jQuery 简介
halemyan
博客等级 码龄20年 5粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值