1,“grails create-app WebFlowDemo”,输出如下:
D:_DEVgrails_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:DMY_DEVgrails0.6 Base Directory: D:_DEVgrails_apps Environment set to development Note: No plugin scripts found Running script D:DMY_DEVgrails0.6scriptsCreateApp.groovy Overriding previous definition of reference to groovyJarSet [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemosrc [mkdir] Created dir: D:_DEVgrails_appsWebFl owDemosrcjava [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemosrcgroovy [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-app [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appcontrollers [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appservices [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appdomain [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-app aglib [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-apputils [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appviews [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appviewslayouts [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appi18n [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appconf [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemo est [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemo estunit [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemo estintegration [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoscripts [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-app [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appjs [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appcss [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appimages [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFclasses [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appMETA-INF [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemolib [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appconfspring [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemograils-appconfhibernate [propertyfile] Creating new property file: D:_DEVgrails_appsWebFlowDemoapplication.properties [copy] Copying 2 files to D:_DEVgrails_appsWebFlowDemo [copy] Copying 2 files to D:_DEVgrails_appsWebFlowDemoweb-appWEB-INF [copy] Copying 5 files to D:_DEVgrails_appsWebFlowDemoweb-appWEB-INF ld [copy] Copying 131 files to D:_DEVgrails_appsWebFlowDemoweb-app [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemograils-appconf [copy] Copying 13 files to D:_DEVgrails_appsWebFlowDemograils-app [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemograils-appconfspring [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemo [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemo [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemo [propertyfile] Updating property file: D:_DEVgrails_appsWebFlowDemoapplication.properties Created Grails Application at D:_DEVgrails_apps/WebFlowDemo D:_DEVgrails_apps>
2,“cd WebFlowDemo”,进入工程目录
3,“grails create-domain-class User”,创建一个域类User,输出如下
D:_DEVgrails_appsWebFlowDemo>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:DMY_DEVgrails0.6 Base Directory: D:_DEVgrails_appsWebFlowDemo Environment set to development Note: No plugin scripts found Running script D:DMY_DEVgrails0.6scriptsCreateDomainClass.groovy [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemograils-appdomain Created for User [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemo estintegration Created Tests for User D:_DEVgrails_appsWebFlowDemo>
4,将grails-appdomainUser.groovy修改为如下内容:
class User implements Serializable { String username String password }
5,“grails generate-all User”,生成所有与域类User相关的目录和文件,输出如下
D:_DEVgrails_appsWebFlowDemo>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:DMY_DEVgrails0.6 Base Directory: D:_DEVgrails_appsWebFlowDemo Environment set to development Note: No plugin scripts found Running script D:DMY_DEVgrails0.6scriptsGenerateAll.groovy [mkdir] Created dir: C:Documents and SettingsDaniel.grails.6projectsWebFlowDemoclasses Compiling 5 source files to C:Documents and SettingsDaniel.grails.6projectsWebFlowDemoclasses [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFgrails-appi18n [copy] Copying 8 files to D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFgrails-appi18n [copy] Copying 1 file to D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFspring [copy] Copying 1 file to C:Documents and SettingsDaniel.grails.6projectsWebFlowDemoclasses [copy] Copying 1 file to C:Documents and SettingsDaniel.grails.6projectsWebFlowDemoclasses Generating views for domain class User Generating controller for domain class User Finished generation for domain class User D:_DEVgrails_appsWebFlowDemo>
6,将grails-appcontrollersUserController.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-appviewsuser目录下新建一个名为“loginSystem”的子目录,该名称为UserController.groovy中的loginSystemFlow的“loginSystem”相对应。
8,在grails-appviewsuserloginSystem目录下新建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 < body > < div class ="nav" > < span class ="menuButton" >< a class ="home" href ="${createLinkTo(dir:'')}" > Home < div class ="body" > < h1 > Login Page < g:if test ="${message }" > < div class ="message" > ${message } < g:form action ="loginSystem" method ="post" > < div class ="dialog" > < table > < tbody > < tr class ='prop' > < td valign ='top' class ='name' > < label for ='username' > Username: < td valign ='top' class ='value ${hasErrors(bean:user,field:'username','errors')}' > < input type ="text" id ='username' name ='username' value ="${user? .username?.encodeAsHTML()}" /> < tr class ='prop' > < td valign ='top' class ='name' > < label for ='password' > Password: < td valign ='top' class = 'value ${hasErrors(bean:user,field:'password','errors')}' > < input type ="text" id ='password' name ='password' value ="${user? .password?.encodeAsHTML()}" /> < div class ="buttons" > < span class ="button" >< g:submitButton class ="save" name ="login" value ="Login" > < g:link action ="loginSystem" event ="register" > Register ok.gsp ${message } < br /> < g:link action ="loginSystem" > back to login page showRegisterView.gsp This is a register page < br /> < g:link action ="loginSystem" > back to login page
9,“grails run-app”,启动Grails应用,输出如下
D:_DEVgrails_appsWebFlowDemo>grails run-app Welcome to Grails 0.6 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: D:DMY_DEVgrails0.6 Base Directory: D:_DEVgrails_appsWebFlowDemo Environment set to development Note: No plugin scripts found Running script D:DMY_DEVgrails0.6scriptsRunApp.groovy [mkdir] Created dir: D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFlib Compiling 1 source files to C:Documents and SettingsDaniel.grails.6projectsWebFlowDemoclasses 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:_DEVgrails_appsWebFlowDemoweb-app] 2007-09-08 00:12:26.425:/WebFlowDemo: INFO: Initializing Log4J from [D:_DEVgrails_appsWebFlowDemoweb-appWEB-INFclasseslog4j.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按钮 :)
12,输入daniel和123,并按一下Login按钮
Welcome, daniel
back to login page
13,点击"back to login page"链接,在点击login页面上的Register链接
This is a register page
back to login page
一个最简单的Spring Web Flow应用完成。