Spring Web Flow是Spring家族中的一位成员,他能简化Web应用的开发。在Grails0.6中就集成了Spring Web Flow这一Web应用开发利器。下面通过一个实例向大家展示一下在Grails中如何方便的使用Spring Web Flow。
		
		
		1,“grails create-app WebFlowDemo”,输出如下:
		
		
				
				D:\_DEV\grails_apps>grails create-app WebFlowDemo
Welcome to Grails 0.6 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails0.6
Base Directory: D:\_DEV\grails_apps
Environment set to development
Note: No plugin scripts found
Running script D:\D\MY_DEV\grails0.6\scripts\CreateApp.groovy
Overriding previous definition of reference to groovyJarSet
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src\java
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src\groovy
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\controllers
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\services
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\domain
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\taglib
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\utils
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\views
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\views\layouts
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\i18n
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test\unit
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test\integration
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\scripts
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\js
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\css
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\images
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\classes
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\META-INF
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\lib
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\spring
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\hibernate
[propertyfile] Creating new property file: D:\_DEV\grails_apps\WebFlowDemo\application.properties
     [copy] Copying 2 files to D:\_DEV\grails_apps\WebFlowDemo
     [copy] Copying 2 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF
     [copy] Copying 5 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\tld
     [copy] Copying 131 files to D:\_DEV\grails_apps\WebFlowDemo\web-app
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf
     [copy] Copying 13 files to D:\_DEV\grails_apps\WebFlowDemo\grails-app
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\spring
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo
[propertyfile] Updating property file: D:\_DEV\grails_apps\WebFlowDemo\application.properties
Created Grails Application at D:\_DEV\grails_apps/WebFlowDemo
D:\_DEV\grails_apps>
		
		
		2,“cd WebFlowDemo”,进入工程目录
		
		
		3,“grails create-domain-class User”,创建一个域类User,输出如下
		
		
				
				D:\_DEV\grails_apps\WebFlowDemo>grails create-domain-class User
Welcome to Grails 0.6 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails0.6
Base Directory: D:\_DEV\grails_apps\WebFlowDemo
Environment set to development
Note: No plugin scripts found
Running script D:\D\MY_DEV\grails0.6\scripts\CreateDomainClass.groovy
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\domain
Created  for User
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\test\integration
Created Tests for User
D:\_DEV\grails_apps\WebFlowDemo>
		
		
		4,将grails-app\domain\User.groovy修改为如下内容:
		
		
				
				class
				 User 
				implements
				 Serializable { 
    String username
    String password
}
		
		
		5,“grails generate-all User”,生成所有与域类User相关的目录和文件,输出如下
		
		
				
				D:\_DEV\grails_apps\WebFlowDemo>grails generate-all User
Welcome to Grails 0.6 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails0.6
Base Directory: D:\_DEV\grails_apps\WebFlowDemo
Environment set to development
Note: No plugin scripts found
Running script D:\D\MY_DEV\grails0.6\scripts\GenerateAll.groovy
    [mkdir] Created dir: C:\Documents and Settings\Daniel\.grails\0.6\projects\WebFlowDemo\classes
Compiling 5 source files to C:\Documents and Settings\Daniel\.grails\0.6\projects\WebFlowDemo\classes
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\grails-app\i18n
     [copy] Copying 8 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\grails-app\i18n
     [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\spring
     [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\0.6\projects\WebFlowDemo\classes
     [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\0.6\projects\WebFlowDemo\classes
Generating views for domain class User 
Generating controller for domain class User 
Finished generation for domain class User
D:\_DEV\grails_apps\WebFlowDemo>
		 
		
		6,将grails-app\controllers\UserController.groovy修改为如下内容
		
		
				
				            
				class
				 UserController {
    def index 
				=
				 { redirect(action:list,params:params) }
    
				//
				 the delete, save and update actions only accept POST requests
				
						
				
				    def allowedMethods 
				=
				 [delete:
				'
				POST
				'
				, save:
				'
				POST
				'
				, update:
				'
				POST
				'
				]
    def list 
				=
				 {
        
				if
				(
				!
				params.max)params.max 
				=
				 
				10
				
						
        [ userList: User.list( params ) ]
    }
    def show 
				=
				 {
        [ user : User.get( params.id ) ]
    }
    def delete 
				=
				 {
        def user 
				=
				 User.get( params.id )
        
				if
				(user) {
            user.delete()
            flash.message 
				=
				 
				"
				User ${params.id} deleted.
				"
				
						
            redirect(action:list)
        }
        
				else
				 {
            flash.message 
				=
				 
				"
				User not found with id ${params.id}
				"
				
						
            redirect(action:list)
        }
    }
    def edit 
				=
				 {
        def user 
				=
				 User.get( params.id )
        
				if
				(
				!
				user) {
                flash.message 
				=
				 
				"
				User not found with id ${params.id}
				"
				
						
                redirect(action:list)
        }
        
				else
				 {
            
				return
				 [ user : user ]
        }
    }
    def update 
				=
				 {
        def user 
				=
				 User.get( params.id )
        
				if
				(user) {
             user.properties 
				=
				 params
            
				if
				(user.save()) {
                flash.message 
				=
				 
				"
				User ${params.id} updated.
				"
				
						
                redirect(action:show,id:user.id)
            }
            
				else
				 {
                render(view:
				'
				edit
				'
				,model:[user:user])
            }
        }
        
				else
				 {
            flash.message 
				=
				 
				"
				User not found with id ${params.id}
				"
				
						
            redirect(action:edit,id:params.id)
        }
    }
    def create 
				=
				 {
        def user 
				=
				 
				new
				 User()
        user.properties 
				=
				 params
        
				return
				 [
				'
				user
				'
				:user]
    }
    def save 
				=
				 {
        def user 
				=
				 
				new
				 User()
        user.properties 
				=
				 params
        
				if
				(user.save()) {
            flash.message 
				=
				 
				"
				User ${user.id} created.
				"
				
						
            redirect(action:show,id:user.id)
        }
        
				else
				 {
            render(view:
				'
				create
				'
				,model:[user:user])
        }
    }
    def loginSystemFlow 
				=
				 {
        login {
            on(
				"
				login
				"
				) {
                
				if
				 (
				"
				daniel
				"
				 
				!=
				 params.username 
				||
				 
				"
				123
				"
				 
				!=
				 params.password) {
                    flash.message 
				=
				 
				"
				username or password is invalid
				"
				
				
                    def user = new User()
                    user.properties = params
                    flash.user = user
						                    return error ()
                } else {
                    // 仅仅用来演示如何使用flow scope
                    flow.message = "Welcome, ${params.username}"
                }
            }.to "ok"
            on("register").to "showRegisterView"
        }
        
        ok()
        
        showRegisterView()
    }
}
		on("login"){...}.to "ok"表示点击login按钮后所要去的页面为ok,如果验证失败("daniel" != params.username || "123" != params.password),则利用内置的error(),使用户返回login页面;而on("register").to "showRegisterView"是类似的,不再累述。
		
		
		
		7,在grails-app\views\user\目录下新建一个名为“loginSystem”的子目录,该名称为UserController.groovy中的loginSystemFlow的“loginSystem”相对应。
		
		
		8,在grails-app\views\user\loginSystem\目录下新建login.gsp,ok.gsp,showRegisterView.gsp三个GSP文件(这三个文件的文件名与
    def loginSystemFlow = {
        login {
            ...
        }
        
        ok()
        
        showRegisterView()
    }
中粗体突显的state名相对应,其中login为start state,而ok和showRegisterView为end state)
		,并将其内容修改为:
		
		login.gsp
		
		
				
				
						
				
				<
				html
				>
				
						
    
				<
				head
				>
				
						
        
				<
				meta 
				http-equiv
				="Content-Type"
				 content
				="text/html; charset=UTF-8"
				 
				/>
				
						
        
				<
				meta 
				name
				="layout"
				 content
				="main"
				 
				/>
				
						
        
				<
				title
				>
				Login Page
				</
				title
				>
				
						
    
				</
				head
				>
				
						
    
				<
				body
				>
				
						
        
				<
				div 
				class
				="nav"
				>
				
						
            
				<
				span 
				class
				="menuButton"
				><
				a 
				class
				="home"
				
						
                href
				="${createLinkTo(dir:'')}"
				>
				Home
				</
				a
				>
				
						
            
				</
				span
				>
				
						
        
				</
				div
				>
				
						
        
				<
				div 
				class
				="body"
				>
				
						
            
				<
				h1
				>
				
						
                Login Page
            
				</
				h1
				>
				
						
            
				<
				g:if 
				test
				="${message }"
				>
				
						
                
				<
				div 
				class
				="message"
				>
				
						
                    ${message }
                
				</
				div
				>
				
						
            
				</
				g:if
				>
				
						
            
				<
				g:form 
				action
				="loginSystem"
				 method
				="post"
				>
				
						
                
				<
				div 
				class
				="dialog"
				>
				
						
                    
				<
				table
				>
				
						
                        
				<
				tbody
				>
				
						
                            
				<
				tr 
				class
				='prop'
				>
				
						
                                
				<
				td 
				valign
				='top' 
				class
				='name'
				>
				
						
                                    
				<
				label 
				for
				='username'
				>
				
						
                                        Username:
                                    
				</
				label
				>
				
						
                                
				</
				td
				>
				
						
                                
				<
				td 
				valign
				='top' 
				class
				='value 
				${hasErrors(bean:user,field:'username','errors')}'
				>
				
						
                                    
				<
				input 
				type
				="text"
				 id
				='username' 
				name
				='username'
                                        
				value
				="${user?.username?.encodeAsHTML()}"
				 
				/>
				
						
                                
				</
				td
				>
				
						
                            
				</
				tr
				>
				
						
                            
				<
				tr 
				class
				='prop'
				>
				
						
                                
				<
				td 
				valign
				='top' 
				class
				='name'
				>
				
						
                                    
				<
				label 
				for
				='password'
				>
				
						
                                        Password:
                                    
				</
				label
				>
				
						
                                
				</
				td
				>
				
						
                                
				<
				td 
				valign
				='top' 
				class
				='value 
				${hasErrors(bean:user,field:'password','errors')}'
				>
				
						
                                    
				<
				input 
				type
				="text"
				 id
				='password' 
				name
				='password'
                                        
				value
				="${user?.password?.encodeAsHTML()}"
				 
				/>
				
						
                                
				</
				td
				>
				
						
                            
				</
				tr
				>
				
						
                        
				</
				tbody
				>
				
						
                    
				</
				table
				>
				
						
                
				</
				div
				>
				
						
                
				<
				div 
				class
				="buttons"
				>
				
						
                    
				<
				span 
				class
				="button"
				><
				g:submitButton 
				class
				="save"
				
						
                            name
				="login"
				 value
				="Login"
				></
				g:submitButton
				>
				
						
                    
				</
				span
				>
				
						
                
				</
				div
				>
				
						
                
				<
				g:link 
				action
				="loginSystem"
				 event
				="register"
				>
				Register
				</
				g:link
				>
				
						
            
				</
				g:form
				>
				
						
        
				</
				div
				>
				
						
    
				</
				body
				>
				
						
				
				</
				html
				>
				
						
				
		
		
		ok.gsp
		
		
				
				${message }
				<
				br 
				/>
				
						
						
				
				<
				g:link 
				action
				="loginSystem"
				>
				back to login page
				</
				g:link
				>
		
		
		showRegisterView.gsp
		
		
				
				This is a register page 
				<
				br 
				/>
				
						
				
				<
				g:link 
				action
				="loginSystem"
				>
				back to login page
				</
				g:link
				>
		
		
		
		9,“grails run-app”,启动Grails应用,输出如下
		
		
				
				D:\_DEV\grails_apps\WebFlowDemo>grails run-app
Welcome to Grails 0.6 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails0.6
Base Directory: D:\_DEV\grails_apps\WebFlowDemo
Environment set to development
Note: No plugin scripts found
Running script D:\D\MY_DEV\grails0.6\scripts\RunApp.groovy
    [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\lib
Compiling 1 source files to C:\Documents and Settings\Daniel\.grails\0.6\projects\WebFlowDemo\classes
Running Grails application..
2007-09-08 00:12:24.443::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2007-09-08 00:12:24.521::INFO:  jetty-6.1.4
2007-09-08 00:12:26.425:/WebFlowDemo:INFO:  Set web app root system property: '@grails.project.key@' = [D:\_DEV\grails_apps\WebFlowDemo\web-app\]
2007-09-08 00:12:26.425:/WebFlowDemo:INFO:  Initializing Log4J from [D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\classes\log4j.properties]
2007-09-08 00:12:26.472:/WebFlowDemo:INFO:  Loading Spring root WebApplicationContext
[9282] hibernate.ConfigurableLocalSessionFactoryBean Building new Hibernate SessionFactory
[9922] mvc.GrailsUrlHandlerMapping Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping
[12750] commons.GrailsConfigUtils [GrailsContextLoader] Grails application loaded.
[12797] mvc.GrailsWebRequestFilter Initializing filter 'grailsWebRequest'
[12797] mvc.GrailsWebRequestFilter Filter 'grailsWebRequest' configured successfully
[12797] filter.UrlMappingsFilter Initializing filter 'urlMapping'
[12797] filter.UrlMappingsFilter Initializing filter 'urlMapping'
[12797] filter.UrlMappingsFilter Filter 'urlMapping' configured successfully
[12797] filter.UrlMappingsFilter Filter 'urlMapping' configured successfully
[12797] filter.GrailsReloadServletFilter Initializing filter 'reloadFilter'
[12797] filter.GrailsReloadServletFilter Filter 'reloadFilter' configured successfully
[12891] servlet.GrailsDispatcherServlet Initializing servlet 'grails'
[12954] servlet.GrailsDispatcherServlet FrameworkServlet 'grails': initialization started
2007-09-08 00:12:36.562:/WebFlowDemo:INFO:  Loading WebApplicationContext for Spring FrameworkServlet 'grails'
[13485] servlet.GrailsDispatcherServlet Using context class [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext] for servlet '
grails'
[13485] servlet.GrailsDispatcherServlet Using MultipartResolver [org.springframework.web.multipart.commons.CommonsMultipartResolver@dd7404]
[13485] servlet.GrailsDispatcherServlet Using LocaleResolver [org.springframework.web.servlet.i18n.SessionLocaleResolver@ebbf5c]
[13500] servlet.GrailsDispatcherServlet Unable to locate ThemeResolver with name 'themeResolver': using default [org.springframework.web.servlet.
theme.FixedThemeResolver@192c766]
[13516] servlet.GrailsDispatcherServlet No HandlerAdapters found in servlet 'grails': using default
[13532] servlet.GrailsDispatcherServlet Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': using default [org.springfra
mework.web.servlet.view.DefaultRequestToViewNameTranslator@a40575]
[13532] servlet.GrailsDispatcherServlet Using MultipartResolver [org.springframework.web.multipart.commons.CommonsMultipartResolver@dd7404]
[13532] servlet.GrailsDispatcherServlet FrameworkServlet 'grails': initialization completed in 578 ms
[13532] servlet.GrailsDispatcherServlet Servlet 'grails' configured successfully
2007-09-08 00:12:37.374::INFO:  Started SelectChannelConnector@0.0.0.0:8080
Server running. Browse to http://localhost:8080/WebFlowDemo
		
		
		10,访问http://localhost:8080/WebFlowDemo/user/loginSystem
		
		 11,输入任意登录信息,并按一下Login按钮,我直接按Login按钮 :)
		
		
		11,输入任意登录信息,并按一下Login按钮,我直接按Login按钮 :)
		
		 12,输入daniel和123,并按一下Login按钮
		
		
		12,输入daniel和123,并按一下Login按钮
		Welcome, daniel
back to login 
page13,点击"back to login page"链接,在点击login页面上的Register链接This is a register page 
back to 
login page一个最简单的Spring Web Flow应用完成。
最后告诉大家一个好消息,《Grails权威指南》最晚将在下个月出版,喜欢Grails的朋友到时可以买一本系统地学习一下Grails这个强大的框架,为自己今后的开发注入新的活力。关于此书的一些说明可以看一下《Grails权威指南》译者序(草稿)
附:
朝花夕拾——Groovy & Grails
	posted on 2007-09-08 00:39 
山风小子 阅读(5986) 
评论(3)  编辑  收藏  所属分类: 
Groovy & Grails