`

Spring Web Flow 2简化页面流的开发,结合Spring MVC更俊,Spirng Security 3添加安全机制

阅读更多

  闲来无事,看看Spring这个生态系统中的各个模块挺不错,简化了很多事情,本文参考Spring Web Flow项目中的booking-mvc这个sample进行了仔细学习,很有收获,该sample主要讲解了Spirng Web Flow的一些核心概念,以及与spring mvc,spring security的组合使用,功力大大增强。

    还是典型的3层模型,dao,service,controller,涉及到Java EE 6的规范主要是JPA2.0,JSR303和JSR250。废话不多说先上例子吧。

    由于dao和service都比较简单,重点讲web层,稍后你会看到dao层我们只声明了接口,并没有写实现代码,这是由于我们借助了spring-data-jpa这个子项目的功能,由spring动态代理实现。大大简化了dao层。spring-data旨在提供一个统一的数据访问层接口。不管你是关系型数据库,还是no database,还是key-value,访问数据接口统一,是门面模式的体现。关于spring-data项目的详细信息,请查看官方信息:http://www.springsource.org/spring-data

    首先,我们来谈谈spring web flow 的一些核心概念:什么是flow呢,引用官方文档的一句话:A flow encapsulates a reusable sequence of steps that can execute in different contexts.大致意思就是说,流就是封装了一个可复用的序列步骤,这些序列步骤可以在不同的上下文环境中执行。哎呀,翻译的好别扭啊。那什么是”state“呢,在spring web flow中,把组成流的一系列的步骤称之为state(姑且叫状态吧),通常,进入一个状态就意味着一个页面视图将要呈现给用户,在这个页面视图中用户可以输入一些数据,而且还可以触发一些事件,比如点击了某个button之类的,而这些事件通常又会把当前的state转移到另外一个state,这就是state的transition(姑且叫转移,过渡也行)。在这些state中还可以执行一些动作,比如将收集到的用户数据,持久化到db中等等。

   介绍完一些基本概念后,我们来具体说一下操作。首先先讲spring web flow 和 spring mvc 的集成,在web.xml中配置spring mvc的前端控制器。配置很简单,如下:

 <!-- Loads the Spring web application context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
       <servlet-name>mvc</servlet-name>
       <url-pattern>/</url-pattern>
</servlet-mapping>

 由于我们是基于约定的编程,当mvc这个servlet加载时,会在/WEB-INF/目录下查找文件名为mvc-servlet.xml这个配置文件。下面我们就具体看看spring mvc的配置,首先,我们让spring 扫描web层的controller,代码如下:

 <context:component-scan base-package="org.leochen.samples.web" />

 第2步,充分利用mvc这个命名空间的作用,

<mvc:annotation-driven />

 这个打包了一些列功能配置,比如支持JSR 303的验证,以及sprng 3的类型转换和字段的格式化等。

第3步,添加spring mvc对静态资源的处理,结合在web.xml中配置的url-pattern为”/“,

<mvc:resources mapping="/resources/**" 
                          location="/resources/,classpath:/META-INF/web-resources/" />
<mvc:default-servlet-handler />

 静态资源都放在web根目录下的resources文件下,对所有以/resources开头的请求,都会被映射到web根目录下的resources目录下和类路径下面的META-INF/web-resources(这个是spring-webflow 中一些jar包中的资源文件)目录下查找。

第4步,添加对国际化资源文件的处理,代码如下:

 <mvc:interceptors>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
  </mvc:interceptors>

 <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>


 <bean id="messageSource" 
            class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <array>
                <value>/WEB-INF/messages/globalMessage</value>
                <value>/WEB-INF/messages/validationMessage</value>
            </array>
        </property>
        <property name="defaultEncoding" value="UTF-8" />
        <property name="cacheSeconds" value="0" />
  </bean>

  第5步,配置tiles

<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/**/views.xml</value>
            </list>
        </property>
    </bean>

<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
 <property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView" />
</bean>

 这里tilesViewResolver 使用的spring web flow中提供的实现类。

   下面来讲讲spring web flow 需要配置的一些东西,我们把这些配置单独放到一个文件中,叫做mvc-webflows.xml,方便管理,最后会在mvc-servlet.xml中include这个spring web flow 的配置文件。

第1步,配置flow-registry,顾名思义,这是spring-webflow流的注册入口,代码如下:

<?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-3.0.xsd
           http://www.springframework.org/schema/webflow-config
           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">

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

 在这里要着重讲几点:首先这个base-path,表示所有的flow都是在/WEB-INF/views目录下,flow-location-pattern 这个主要是用来查找各个流定义文件,关于流(flow)的id的确定,有以下两种分配算法,如果base-path存在,那么流的id就是从base-path到流的定义文件之间的目录路径,比如说流的定义文件为/WEB-INF/views/hotels/booking/booking-flow.xml,而base-path是/WEB-INF/views,所以flow的id就为hotels/booking.如果base-path不存在或者流的定义文件就在base-path目录下,那么这时flow的id就为流的定义文件名减去后缀(这里我们定义的后缀为-flow.xml),比如说我们的流定义文件叫booking-flow.xml,那么这时flow的id就为booking。

第2步,配置flow executor,流执行器

 <webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
        <webflow:flow-execution-listeners>
            <webflow:listener ref="securityFlowExecutionListener" />
        </webflow:flow-execution-listeners>
    </webflow:flow-executor>

 这里flow-execution-listeners子元素是用来跟spring security 进行集成的,稍后会谈到。

第3步,补齐flow-registry的flow-builder-services属性的相关依赖配置。代码如下:

<webflow:flow-builder-services id="flowBuilderServices"
                                   view-factory-creator="mvcViewFactoryCreator"
                                   development="true"
                                   validator="validator" />

    <!-- Installs a listener to apply Spring Security authorities -->
    <bean id="securityFlowExecutionListener" 
                class="org.springframework.webflow.security.SecurityFlowExecutionListener" />

    <!-- Configures Web Flow to use Tiles to create views for rendering -->
    <bean id="mvcViewFactoryCreator" 
               class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
        <property name="viewResolvers">
            <list>
                <ref bean="tilesViewResolver" />
            </list>
        </property>
        <property name="useSpringBeanBinding" value="true" />
    </bean>
<bean id="validator" 
           class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

 简单说一下webflow:flow-builder-services 几个属性的含义,view-factory-creator表示使用的是哪个视图工厂,validator是用来在处理页面流的过程使用的是JSR303的验证,bean id为validator就是spring对jsr303的支持类。development可以扫描flow定义文件的变化,开发时这么用比较好。

    好了,spring web flow 的定义文件就这么多了,下面来将spring mvc与spring web flow 集成。代码如下:

<!-- Spring MVC Integration With Spring Web Flow -->
    <!-- 1.Registering the FlowHandlerAdapter, Enables FlowHandler URL mapping -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
        <property name="flowExecutor" ref="flowExecutor" />
    </bean>

    <!-- 2.Defining flow mappings, Maps request paths to flows in the flowRegistry -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
        <property name="flowRegistry" ref="flowRegistry" />
        <property name="order" value="-1" />
    </bean>

  ok,spring mvc 和spring web flow 集成完毕,下面加入spring security 3.

第1步,当然是配置web.xml文件了,代码如下:

 <!-- Enables Spring Security -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>



   <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 注意这里的filter-name可不是随便起的,这个name为成为spring security filter chain中的一个filter相匹配上,从而完成spring security的功能。注意到filter-class只是spring-web中的一个类而已,并不是spring-security中的类。

第2步,配置spring-security,applicationContext-security.xml,全部配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="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-3.0.xsd
                http://www.springframework.org/schema/security
                http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    

 <http security="none" pattern="/resources/**" />

 <http auto-config="true" use-expressions="true">

        <intercept-url pattern="/sec/**" access="hasRole('ROLE_USER')" />

        <form-login login-page="/login"
                    login-processing-url="/loginProcess"
                    authentication-failure-url="/login?error=1"
                    default-target-url="/" />

 <remember-me key="SpringWebFlowTutorial-rmkey-BUUttZnBJCa#U=4Dwg@%5_ptCC8wHtlY"
                          services-ref="ipTokenBasedRememberMeService" />

        <logout logout-url="/logout" logout-success-url="/" invalidate-session="true" />
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="customJdbcDao">
            <password-encoder ref="passwordEncoder">
                <salt-source ref="saltSource" />
            </password-encoder>
        </authentication-provider>
    </authentication-manager>


    <beans:bean id="customJdbcDao" class="org.leochen.samples.dao.impl.CustomJdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="enableGroups" value="true" />
        <beans:property name="enableAuthorities" value="false" />
    </beans:bean>

    <!-- the property of 'key' must be have -->
 <beans:bean id="ipTokenBasedRememberMeService" 
                          class="org.leochen.samples.web.security.IPTokenBasedRememberMeService">
    <beans:property name="userDetailsService" ref="customJdbcDao" />
    <beans:property name="key" 
                       value="SpringWebFlowTutorial-rmkey-BUUttZnBJCa#U=4Dwg@%5_ptCC8wHtlY" />
    <beans:property name="tokenValiditySeconds" value="1209600" />
        <beans:property name="parameter" value="_remember_me" />
        <beans:property name="cookieName" value="LOGIN_REMEMBER_ME" />
    </beans:bean>
</beans:beans>

 spring security 可以参考spring security的文档和 Spring Security 3这本书来参考学习,很有帮助。

这样基本配置就这么着了,对于那些datasource,jpa 以及spring-jpa的配置会在附件中的代码中给出,附件中的代码可以完整运行。当然了,要熟悉maven。

    下面说一下一个流的基本定义图,如下图:

 

     还是看图一目了然吧,下面是flow定义文件,/WEB-INF/views/hotels/booking/booking-flow.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">

    <!--notice: 'attributes' property cann't use the form like hasRole('ROLE_USER'),
                         it's just the role name -->
 <secured attributes="ROLE_USER"/>

 <var name="searchCriteria" class="org.leochen.samples.web.controllers.hotels.SearchCriteria"/>

    <input name="hotelId" required="true"/>
    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId,currentUser.name)" 
                         result="flowScope.booking"/>
    </on-start>

    <view-state id="enterBookingDetails" model="booking">
        <binder>
            <binding property="checkinDate" />
            <binding property="checkoutDate" />
			<binding property="beds" />
			<binding property="smoking" />
			<binding property="creditCard" />
			<binding property="creditCardName" />
			<binding property="creditCardExpiryMonth" />
			<binding property="creditCardExpiryYear" />
			<binding property="amenities" />
        </binder>
        
        <on-render>
            <render fragments="main"/>
        </on-render>

        <transition on="submit" to="reviewBooking"/>
        <transition on="cancel" to="bookingCancelled" bind="false" />
    </view-state>

    <view-state id="reviewBooking">
        <on-render>
            <render fragments="main"/>
        </on-render>

        <transition on="confirm" to="bookingConfirmed">
            <evaluate expression="bookingService.save(booking)" />
        </transition>
        <transition on="revise" to="enterBookingDetails"/>
        <transition on="cancel" to="bookingCancelled"/>
    </view-state>


    <end-state id="bookingConfirmed" />
    <end-state id="bookingCancelled" />
</flow>
 

    下面贴上E-R图,看得直观,如下:

 



   最后,想说几点关于jsr303验证的几个注意点,使用hibernate validator(jsr 303的实现)为spring mvc提供验证

的时候,需要把org.hibernate.validator包下面的ValidationMessages.properties文件拷贝到类路径下,这样就可以

 自定义验证消息了,对于spring web flow 的验证,只需在flow定义文件的相同目录下定义messages.properties文件

就可以添加验证消息了,spring web flow 对于验证消息key的生成遵循这么一个约定,key值有3部分组成,第一部分是model的名称,比如booking,第二部分是model的property,比如booking的checkinDate属性,第三部分是error

code,举个全的例子,booking.checkinDate.NotNull=,booking.creditCardExpiryMonth.typeMismatch=

 

Spring3.1新特性,配置JPA无需persistence.xml描述文件,SpringWebFlowTutorial-without-persistence.xml.7z这个是修改后的打包文件,里面还将SpringWebFlowTutorial.sql文件中的booking_amenities表的amenity 字段长度增大些,一个小bug修正了一下。原先的版本在应用服务器glassfish中还不能部署成功,是因为spring提供

  LocalContainerEntityManagerFactoryBean与Java EE应用服务器有些冲突,在没有Spring3.1新特性之前,

可以有其他的解决方案,具体请参考Spring官方文档。现在spring不用persistence.xml文件了,就可以避免掉冲突了。

 

  • 大小: 5.6 KB
  • 大小: 30.9 KB
  • pic.7z (2.6 MB)
  • 下载次数: 642
7
3
分享到:
评论
9 楼 sodagreen.simplicity 2015-09-23  
说的很赞,也挺清楚,就是文章一开始的配置文件讲述稍嫌太多了。
8 楼 澹若水 2015-09-06  
感谢分享,学习了
7 楼 clongjava 2012-07-27  
610622106 写道
楼主,你的 E-R图用什么软件画的呢?

是MySQL Workbench
6 楼 610622106 2012-07-27  
楼主,你的 E-R图用什么软件画的呢?
5 楼 fxl545826 2012-06-27  
osacar 写道
web flow和work flow有啥区别?

workflw是工作流,webflow是页面流转,workflow的话可能针对于一个新闻经过录入以后要经过主编等的审核,能够审批通过了,返工等类似处理,而webflw可能针对于一些例如购物车了,注册了需要多个页面分几个步骤来完成最后的完成。这样能理解吗?
4 楼 liumayulingyan 2011-12-19  
牛B
3 楼 osacar 2011-12-18  
web flow和work flow有啥区别?
2 楼 clongjava 2011-12-18  
KimHo 写道
挺好的,感谢分享!

谢谢支持
1 楼 KimHo 2011-12-17  
挺好的,感谢分享!

相关推荐

    spring web flow reference 2.4.0

    - **Spring MVC Flash Scope集成**:增强了与Spring MVC框架的集成,允许在Web Flow和Spring MVC之间共享临时数据。 - **部分JSR-303 Bean验证**:实现了对JSR-303 Bean验证规范的部分支持,提高了数据验证的能力。 ...

    spring webflow 官方中文版权威指南PDF

    11. **安全控制**:WebFlow如何与Spring Security或其他安全框架集成,实现权限控制和认证。 12. **测试**:如何编写单元测试和集成测试,确保WebFlow流程的正确性。 13. **实战案例**:提供实际项目中的示例,...

    Spring Web Flow 介绍.rar

    Spring Web Flow 可以结合Spring Security,提供角色基础的访问控制和安全性管理,确保只有授权的用户可以执行特定的流程。 ### 9. 错误处理与回退机制 内置的错误处理机制允许开发者定义在流程中遇到错误时的行为...

    spring web flow权威指南

    7. **集成性**:Spring Web Flow与Spring MVC无缝集成,可以利用Spring的依赖注入和AOP特性,同时也可以与其他Spring生态系统的组件(如Spring Security、Spring Session)协同工作。 通过《Spring Web Flow权威...

    spring web flow 官方文档

    安全性是任何应用程序都必须考虑的关键因素,Spring Web Flow提供了多种机制来保护工作流免受未经授权的访问。 #### 8.2 How do I secure a flow? 工作流的安全性可以通过多种方式实现,包括权限检查、角色分配、...

    Spring-WebFlow入门中文文档

    3. **技术无关性**:无论你使用 Struts、Spring MVC、Tapestry、JSP 还是 Portlets,都可以轻松集成 Spring Web Flow 来管理页面流程。 4. **流程管理**:Spring Web Flow 自动管理流程的生命周期,包括事件触发、...

    spring-webflow-reference

    - Spring Web Flow 2.2则增加了对JSF 2的支持、Spring Security Facelets标签库更新、Spring JavaScript更新和JFS Portlet支持等。 2. 流程定义(Defining Flows): - 流程是一种可以由不同状态组成的交互序列,...

    Spring Web Flow 2 Web Development

    《Spring Web Flow 2 Web Development》是一本深入探讨Spring Web Flow 2技术的专著,主要针对使用Spring框架进行Web应用程序开发的开发者。Spring Web Flow是Spring框架的一个扩展,它专注于管理用户会话中的复杂...

    Spring Web Flow 2小教程

    - **支持机制**:Spring Web Flow 2.0 提供了对Ajax事件的支持,使得开发人员能够在不刷新整个页面的情况下更新视图。 - **实际效果**:用户交互更加流畅,用户体验得到显著提升。 ##### 2.3 与JSF整合 - **整合...

    Pro Spring MVC With Web Flow

    plus the first published coverage of Spring Web Flow 2.x, this book includes numerous tips and tricks to help you get the most out of Spring MVC, Spring Web Flow, and web development in general. ...

    spring web flow demo

    要了解 Spring Web Flow 是什么东西,最好的办法莫过于查看示例,图 2 展示了一个简化的购物车的流 程。 图 1 购物车示例 图 2 所示流程用 Spring Web Flow 2.0 的配置文件表示如下: 清单 1 用 Spring Web Flow ...

    Spring Web Flow2入门(二)

    通过这两个实例,你可以深入了解Spring Web Flow2如何创建和管理用户交互流程,以及如何将其与Spring MVC和Spring Security整合,以构建功能丰富的Web应用。实践是掌握技术的最好方式,所以动手尝试一下吧!

    spring flow Demo例子

    - Spring Web Flow与Spring MVC紧密集成,可以利用Spring MVC的视图解析机制来决定展示哪个JSP页面。 - 使用`&lt;view&gt;`元素指定视图ID,Spring Web Flow将自动寻找对应的视图解析路径。 5. **控制器(Controller)...

    spring webflow

    9. **安全控制**:Spring Webflow可以与Spring Security等安全框架集成,实现对流程访问的权限控制,确保只有授权的用户才能执行特定流程。 10. **测试与调试**:Spring Webflow提供了一套测试API,使得开发者能够...

Global site tag (gtag.js) - Google Analytics