First they ignore you
          then they ridicule you
          then they fight you
          then you win
              -- Mahatma Gandhi
          Chinese => English     英文 => 中文             
          隨筆-221  評論-1047  文章-0  trackbacks-0

          在學(xué)習(xí)任何東西之前,最重要的是培養(yǎng)興趣,Groovy世界最耀眼的技術(shù)之一--Grails相信大家早已耳聞,我將通過Grails實(shí)戰(zhàn)系列文章向您展現(xiàn)Grails的迷人風(fēng)采,使您感受到Grails的魅力,以至瘋狂地愛上Grails,并墜入Groovy的愛河。學(xué)Groovy,Grails與學(xué)Java一樣,在實(shí)戰(zhàn)之前需要搭建開發(fā)環(huán)境,您可以在 Groovy輕松入門--搭建Groovy開發(fā)環(huán)境 學(xué)習(xí)到如何搭建Groovy環(huán)境,之后我會講一下如何搭建Grails環(huán)境,然后手把手地寫個(gè)Demo程序告終,我還會抽空寫篇“Groovy輕松入門--Grails實(shí)戰(zhàn)之進(jìn)階篇”

          一,搭建Grails環(huán)境
          0,下載Grails(?http://dist.codehaus.org/grails/grails-bin-1.0.zip,請留意朝花夕拾——Groovy & Grails中的“最新版本”提示)并解壓到自己指定位置(我的位置是D:\D\MY_DEV\grails)
          1,設(shè)置環(huán)境變量GRAILS_HOME(注意大寫),過程與“設(shè)置環(huán)境變量GROOVY_HOME”相似
          2,將%GRAILS_HOME%\bin添加到環(huán)境變量path中,過程與“將GROOVY_HOME目錄下的bin追加到環(huán)境變量path中”相似
          (如果只想進(jìn)行Grails開發(fā),可以不設(shè)GROOVY_HOME)

          二,創(chuàng)建Grails Demo程序
          3,打開“命令行”,選擇當(dāng)前目錄(我的為D:\Temp\grails_apps),在黑底白字的窗口中輸入“grails create-app demo”,不包括雙引號“”,在您的屏幕中可以看到類似下面的輸出結(jié)果:

          D:\_DEV\grails_apps>grails create-app demo

          Welcome to Grails 1.0 - http://grails.org/
          Licensed under Apache Standard License 2.0
          Grails home is set to: D:\D\MY_DEV\grails-1.0

          Base Directory: D:\_DEV\grails_apps
          Environment set to development
          Note: No plugin scripts found
          Running script D:\D\MY_DEV\grails-1.0\scripts\CreateApp.groovy
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\src
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\src\java
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\src\groovy
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\controllers
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\services
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\domain
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\taglib
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\utils
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\views
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\views\layouts
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\i18n
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\conf
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\test
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\test\unit
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\test\integration
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\scripts
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\js
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\css
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\images
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\WEB-INF\classes
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\META-INF
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\lib
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\conf\spring
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\grails-app\conf\hibernate
          [propertyfile] Creating new property file: D:\_DEV\grails_apps\demo\application.properties
          ???? [copy] Copying 2 files to D:\_DEV\grails_apps\demo
          ???? [copy] Copying 2 files to D:\_DEV\grails_apps\demo\web-app\WEB-INF
          ???? [copy] Copying 5 files to D:\_DEV\grails_apps\demo\web-app\WEB-INF\tld
          ???? [copy] Copying 87 files to D:\_DEV\grails_apps\demo\web-app
          ???? [copy] Copying 17 files to D:\_DEV\grails_apps\demo\grails-app
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo
          [propertyfile] Updating property file: D:\_DEV\grails_apps\demo\application.properties
          Created Grails Application at D:\_DEV\grails_apps/demo
          D:\_DEV\grails_apps>

          通過“grails create-app”這個(gè)命令,Grails自動幫我們創(chuàng)建了開發(fā)所需的工程環(huán)境。其實(shí)您現(xiàn)在就已經(jīng)擁有了一個(gè)可運(yùn)行的Web應(yīng)用程序,
          然后進(jìn)入demo目錄(“cd demo”),輸入“grails run-app”,回車,啟動這個(gè)‘五臟俱全’的程序雛形,打開瀏覽器,輸入 http://localhost:8080/demo ,回車,看到了吧 :) 讓我們繼續(xù)吧,請停止這個(gè)程序(Ctrl + C)

          4,在“命令行”中輸入“cd demo”,回車,以進(jìn)入demo目錄,然后再輸入“grails create-domain-class User”創(chuàng)建domain class即類似于pojo的pogo,它對應(yīng)MVC中的Model,不過由Grails自動創(chuàng)建的pogo是空的,需要自己添加屬性,約束(constraints)等。輸出結(jié)果如下所示:

          D:\_DEV\grails_apps\demo>grails create-domain-class User

          Welcome to Grails 1.0 - http://grails.org/
          Licensed under Apache Standard License 2.0
          Grails home is set to: D:\D\MY_DEV\grails-1.0

          Base Directory: D:\_DEV\grails_apps\demo
          Environment set to development
          Note: No plugin scripts found
          Running script D:\D\MY_DEV\grails-1.0\scripts\CreateDomainClass.groovy
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo\grails-app\domain
          Created? for User
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo\test\integration
          Created Tests for User
          D:\_DEV\grails_apps\demo>

          5,進(jìn)入D:\Temp\grails_apps\demo\grails-app\domain(這個(gè)目錄中存放著所有的domain class),打開User.groovy,修改為如下內(nèi)容:
          class ?User?{?
          ????String?name
          ????String?password
          ????
          ????String?toString()?{
          ????????
          " $name?:?$password " ????
          ????}
          ????
          ????
          static ?constraints? = ?{
          ????????name(blank:?
          false )????
          ????????password(blank:?
          false ,?size:? 6 .. 16 )
          ????}
          }????
          contraints這個(gè)類變量是定義一些約束的,比如name不能為空白,password不能為空白而且長度在6到16之間(包括6和16)

          6,在“命令行”中輸入“grails generate-all User”,為User產(chǎn)生所有CRUD操作需要的代碼(如控制器UserController.groovy)和頁面(如list.gsp),輸出結(jié)果如下所示:
          D:\_DEV\grails_apps\demo>grails generate-all User

          Welcome to Grails 1.0 - http://grails.org/
          Licensed under Apache Standard License 2.0
          Grails home is set to: D:\D\MY_DEV\grails-1.0

          Base Directory: D:\_DEV\grails_apps\demo
          Environment set to development
          Note: No plugin scripts found
          Running script D:\D\MY_DEV\grails-1.0\scripts\GenerateAll.groovy
          ??? [mkdir] Created dir: D:\_DEV\grails_apps\demo\web-app\WEB-INF\lib
          ??? [mkdir] Created dir: C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\classes
          ? [groovyc] Compiling 7 source files to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\classes
          ??? [mkdir] Created dir: C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\resources\grails-app\i18n
          [native2ascii] Converting 10 files from D:\_DEV\grails_apps\demo\grails-app\i18n to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\re
          sources\grails-app\i18n
          ???? [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\classes
          ???? [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\resources
          ???? [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo
          [0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057: display name [org
          .codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057]; startup date [Tue Feb 05 23:26:45 CST 2008]; root of context hierarch
          y
          [16] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationConte
          xt@2b2057]: org.springframework.beans.factory.support.DefaultListableBeanFactory@eebf17
          Generating views for domain class User ...
          Generating controller for domain class User ...
          Finished generation for domain class User
          D:\_DEV\grails_apps\demo>


          7,修改demo\grails-app\controllers\UserController.groovy的內(nèi)容為:
          ????????????
          class?UserController?{

          ????def?loginService?
          //?新增的代碼
          ????
          ????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?
          =?{
          ????????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?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.hasErrors()?&&?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(params)
          ????????
          if(!user.hasErrors()?&&?user.save())?{
          ????????????flash.message?
          =?"User?${user.id}?created"
          ????????????redirect(action:show,id:user.id)
          ????????}
          ????????
          else?{
          ????????????render(view:
          'create',model:[user:user])
          ????????}
          ????}

          ????
          //?新增的代碼
          ????def?login?=?{
          ????????
          if?(request.method?==?'POST')?{
          ????????????User?u?
          =?new?User()
          ????????????u.properties?
          =?params
          ????
          ????????????
          if?(!u.validate())?{
          ????????????????render(view:
          'login',?model:[user:u])
          ????????????}
          ????
          ????????????
          if?(params.name?&&?params.password)?{
          ????
          ????????????????def?user?
          =?loginService.check(u)
          ????????????????
          ????????????????
          if?(user)?{
          ??????????????????? flash.message?
          =?"Welcome?${user.name}"?
          ??????????????????? render(view:?
          "ok",?model:?[user:?user])
          ????????????????}?
          else?{
          ??????????????????? flash.error?
          =?"Invalid?${u.name}?with?${u.password}"
          ??????????????????? render(view:?
          "login",?model:?[user:?u])
          ????????????????}????
          ????????????}?
          else?{
          ????????????????render(view:?
          "login",?model:?[user:?u])
          ????????????}
          ????????}
          ????}
          }

          大家或許也看到了LoginService這個(gè)類,我將在后面演示創(chuàng)建它,這個(gè)LoginService類封裝了所有登陸相關(guān)的業(yè)務(wù)邏輯,Grails會自動將其注入到UserController中

          8,在“命令行”中,輸入“grails create-service Login”,創(chuàng)建LoginService.groovy,輸出:
          D:\_DEV\grails_apps\demo>grails create-service Login

          Welcome to Grails 1.0 - http://grails.org/
          Licensed under Apache Standard License 2.0
          Grails home is set to: D:\D\MY_DEV\grails-1.0

          Base Directory: D:\_DEV\grails_apps\demo
          Environment set to development
          Note: No plugin scripts found
          Running script D:\D\MY_DEV\grails-1.0\scripts\CreateService.groovy
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo\grails-app\services
          Created Service for Login
          ???? [copy] Copying 1 file to D:\_DEV\grails_apps\demo\test\integration
          Created ServiceTests for Login
          D:\_DEV\grails_apps\demo>

          9,修改demo\grails-app\services\LoginService.groovy的內(nèi)容為:
          class?LoginService?{

          ????
          boolean?transactional?=?true

          ????def?check(User?u)?{
          ????????def?user?
          =?User.findWhere(name:?u.name,?password:?u.password)
          ????????
          return?user
          ????}

          }

          10,在demo\grails-app\views\user目錄下創(chuàng)建login.gsp和ok.gsp,它們對應(yīng)MVC中的View,內(nèi)容分別為:
          login.gsp (復(fù)制demo\grails-app\views\user\create.gsp的內(nèi)容到login.gsp中,并修改):



          <html>
          ????
          <head>
          ????????
          <meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8"/>
          ????????
          <meta?name="layout"?content="main"?/>
          ????????
          <!--?將Create?User修改為Login?-->
          ????????
          <title>Login</title>?????????
          ????
          </head>
          ????
          <body>
          ????????
          <div?class="nav">
          ????????????
          <span?class="menuButton"><a?class="home"?href="${createLinkTo(dir:'')}">Home</a></span>
          ????????????
          <span?class="menuButton"><g:link?class="list"?action="list">User?List</g:link></span>
          ????????
          </div>
          ????????
          <div?class="body">
          ????????????
          <!--?將Create?User修改為Login?-->
          ????????????
          <h1>Login</h1>
          ????????????
          <!--?將flash.message修改為flash.error?-->
          ????????????
          <g:if?test="${flash.error}">
          ????????????
          <!--?將class="message"修改為class="errors",?將flash.message修改為flash.error?-->
          ????????????
          <div?class="errors">${flash.error}</div>
          ????????????
          </g:if>
          ????????????
          <g:hasErrors?bean="${user}">
          ????????????
          <div?class="errors">
          ????????????????
          <g:renderErrors?bean="${user}"?as="list"?/>
          ????????????
          </div>
          ????????????
          </g:hasErrors>
          ????????????
          ????????????
          <!--?將action="save"修改為action="login"?-->
          ????????????
          <g:form?action="login"?method="post"?>
          ????????????????
          <div?class="dialog">
          ????????????????????
          <table>
          ????????????????????????
          <tbody>
          ????????????????????????
          ????????????????????????????
          <tr?class="prop">
          ????????????????????????????????
          <td?valign="top"?class="name">
          ????????????????????????????????????
          <label?for="name">Name:</label>
          ????????????????????????????????
          </td>
          ????????????????????????????????
          <td?valign="top"?class="value?${hasErrors(bean:user,field:'name','errors')}">
          ????????????????????????????????????
          <input?type="text"?id="name"?name="name"?value="${fieldValue(bean:user,field:'name')}"/>
          ????????????????????????????????
          </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"?maxlength="16"?id="password"?name="password"?value="${fieldValue(bean:user,field:'password')}"/>
          ????????????????????????????????
          </td>
          ????????????????????????????
          </tr>?
          ????????????????????????
          ????????????????????????
          </tbody>
          ????????????????????
          </table>
          ????????????????
          </div>
          ????????????????
          <div?class="buttons">
          ????????????????????
          <!--?將value="Create"修改為value="Login"?-->
          ????????????????????
          <span?class="button"><input?class="save"?type="submit"?value="Login"?/></span>
          ????????????????
          </div>
          ????????????
          </g:form>
          ????????
          </div>
          ????
          </body>
          </html>

          ok.gsp:

          <g:if?test="${flash.message}">
          ????
          <div?class="message">${flash.message}</div>
          </g:if>

          Name:?${user?.name}???
          <br>
          Password:?${user?.password}

          11,修改demo\grails-app\conf\BootStrap.groovy,初始化數(shù)據(jù)庫:將一個(gè)User實(shí)例保存到數(shù)據(jù)庫(grails自帶hsqldb和jetty)中,內(nèi)容如下:
          class?BootStrap?{

          ?????def?init?
          =?{?servletContext?->
          ????????
          new?User(name:?"demo",?password:?"123456").save()
          ?????}

          ?????def?destroy?
          =?{
          ?????}
          }?

          12,在“命令行”中,輸入“grails run-app”,運(yùn)行我們的Web應(yīng)用,輸出如下:
          D:\_DEV\grails_apps\demo>grails run-app

          Welcome to Grails 1.0 - http://grails.org/
          Licensed under Apache Standard License 2.0
          Grails home is set to: D:\D\MY_DEV\grails-1.0

          Base Directory: D:\_DEV\grails_apps\demo
          Environment set to development
          Note: No plugin scripts found
          Running script D:\D\MY_DEV\grails-1.0\scripts\RunApp.groovy
          ? [groovyc] Compiling 4 source files to C:\Documents and Settings\Daniel\.grails\1.0\projects\demo\classes
          Running Grails application..
          2008-02-05 23:46:08.912::INFO:? Logging to STDERR via org.mortbay.log.StdErrLog
          2008-02-05 23:46:08.066::INFO:? jetty-6.1.4
          2008-02-05 23:46:08.347::INFO:? No Transaction manager found - if your webapp requires one, please configure one.
          2008-02-05 23:46:09.081:/demo:INFO:? Set web app root system property: 'demo' = [D:\_DEV\grails_apps\demo\web-app\]
          2008-02-05 23:46:09.081:/demo:INFO:? Initializing Log4J from [file:C:\Documents and Settings\Daniel/.grails/1.0/projects/demo/resources/log4j.pro
          perties]
          2008-02-05 23:46:09.113:/demo:INFO:? Initializing Spring root WebApplicationContext
          [0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5facbd: display name [org
          .codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5facbd]; startup date [Tue Feb 05 23:46:14 CST 2008]; parent: org.springframew
          ork.web.context.support.XmlWebApplicationContext@1fef80a
          [0] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContex
          t@5facbd]: org.springframework.beans.factory.support.DefaultListableBeanFactory@aa4c7c
          2008-02-05 23:46:21.590:/demo:INFO:? Initializing Spring FrameworkServlet 'grails'
          2008-02-05 23:46:21.871::INFO:? Started SelectChannelConnector@0.0.0.0:8080
          Server running. Browse to http://localhost:8080/demo

          ?
          13,打開瀏覽器,輸入:http://localhost:8080/demo/user/login?,在Name處輸入demo,Password處輸入123456,點(diǎn)擊‘Login’,跳轉(zhuǎn)到成功頁面:
          Welcome demo
          Name: demo
          Password: 123456

          如果您對Grails的工程目錄不太熟悉,我這里為大家提供了一張表,詳細(xì)地描述了各目錄的用途:

          《Grails權(quán)威指南》3-1.Grails工程目錄

          目錄名稱

          相關(guān)描述

          grails-app

          此目錄包含了Grails應(yīng)用程序的核心工件(core artifact)

          + conf

          此目錄包含了諸如DevelopmentDataSource.groovy的配置文件

          + controllers

          此目錄包含了處理請求(request)的控制器(controller)Grails控制器將在第7章中進(jìn)行講解

          + domain

          此目錄包含了領(lǐng)域模型(domain model),領(lǐng)域模型將在第4章進(jìn)行講解

          + i18n

          此目錄包含了用于國際化的消息束(message bundle)(譯者注:指的是properties文件,如messages.properties

          + services

          此目錄包含了封裝業(yè)務(wù)邏輯的service文件,service將在第10章中進(jìn)行講解

          + taglib

          此目錄包含了輔助頁面生成的動態(tài)標(biāo)簽庫,動態(tài)標(biāo)簽將在第8章中進(jìn)行講解

          + views

          此目錄包含了Groovy服務(wù)器頁面(GSP)以及JSP頁面

          + layouts

          此目錄包含了GSPJSP的布局(layout),這些布局由SiteMesh提供支持,這將在第8章中進(jìn)行講解

          grails-test

          此目錄包含了應(yīng)用程序的單元測試

          hibernate

          此目錄包含了可選的Hibernate配置文件,這將在第11章中進(jìn)行講解

          lib

          此目錄包含了jar文件

          spring

          此目錄包含了可選的Spring配置文件,這將在第11章中進(jìn)行講解

          src

          此目錄包含了其他GroovyJava資源

          + java

          此目錄包含了待編譯的Java源文件

          + groovy

          此目錄包含了待編譯的Groovy源文件

          web-app

          此目錄包含了Web應(yīng)用程序的資源(CSSJavaScript等)


          注:Grails1.0已將hibernate和spring兩個(gè)目錄移到grails-app\conf目錄下了,
          而grails-test目錄也更名為test,test目錄下有integration目錄和unit目錄,分別存放集成測試代碼和單元測試代碼


          想象一下用您平時(shí)做項(xiàng)目時(shí)所用的框架組合(比如SSH)來創(chuàng)建同樣的Web應(yīng)用程序,您立刻會感受,Grails讓我們專注于業(yè)務(wù)邏輯,而不用浪費(fèi)時(shí)間在那些scaffolding code(如配置文件)上。從今天開始,您不用再羨慕那些Ruby程序員所用的RoR了,您大可以使用Grails來高效開發(fā)Web應(yīng)用。

          您也可以訪問Grails官方網(wǎng)站(http://www.grails.org)進(jìn)一步學(xué)習(xí)。

          附:朝花夕拾——Groovy & Grails
          posted on 2007-03-21 00:49 山風(fēng)小子 閱讀(19541) 評論(31)  編輯  收藏 所屬分類: Groovy & Grails
          主站蜘蛛池模板: 舟山市| 昭觉县| 敖汉旗| 渭源县| 双江| 尚义县| 屯门区| 石泉县| 淅川县| 凌源市| 泾川县| 鄄城县| 延川县| 夏津县| 都匀市| 台北县| 南安市| 乡城县| 墨江| 天祝| 屏东市| 鄂托克旗| 溧水县| 治县。| 云梦县| 邵武市| 三台县| 潍坊市| 土默特右旗| 井研县| 文昌市| 西乌珠穆沁旗| 上饶市| 拜城县| 东山县| 彭水| 江安县| 乌鲁木齐县| 民权县| 镇雄县| 凤山市|