Groovy和Grails介绍(2)

在Java EE Server上部署和运行Grails

  Grails具有一个内置Resin服务器,您可使用grails run-app 命令运行应用程序。此命令会将应用程序部署到Resin服务器并启动服务器。因此您现在可以在http://localhost:8080 /ClothesMgt 访问此应用程序。您还可以同样轻松地将应用程序部署到任意JavaEE服务器。我尝试将它部署到Tomcat。要实现此操作,我所需要做的是运行 grails war 命令,将生成的war文件复制到Tomcat中的webapps目录!

  在此案例中生成的war文件的名称为 ClothesMgt.war。一旦部署到Tomcat,您就应该能够在http://localhost:8080/ClothesMgt/ 上访问它,并看到如图2所示的屏幕。

Groovy和Grails简介图-2


  图2:Grails 应用程序

  通过此应用程序,能够获得Shirt、Trouser和Cabinet的全部 CRUD功能。可以显示衣橱的全部数据、向衣橱添加新衬衫和裤子、编辑它们的值和删除记录——实现这些操作都无需编写任何业务逻辑、视图或数据访问代码。 仅在几分钟内您就在JavaEE服务器上部署好了一个合适的Web应用程序。很酷吧?!

  让我们更进一步来定制Grails。
创建自定义控制器

  我现在将把新功能和页面添加到Web应用程序,同时重用已经存在的域类。shirt/list 和 trouser/list 会分别显示衬衫和裤子的清单,现在让我们添加一个新的显示,来同时显示衬衫和裤子的清单。要创建一个新的显示,您需要一个新的控制器和视图。

  使用 generate-controller 和 generate-views 命令,可以轻松实现使用域类自动生成视图和控制器。然而,在此案例中我希望创建一个与域类不直接关联的控制器。因此我将使用grails create-controller命令。当被提示输入控制器名称时,声明Display。Grails将在grails- app/controllers/ 目录创建一个名为DisplayController.groovy 的控制器,在grails-tests 目录创建一个测试套件。如清单5所示编辑控制器。

  清单5:DisplayController.groovy

class DisplayController {
    
   def index = {redirect(action:list,params:params)}
    
   def list = {
         params['max'] = 10
         return [ shirtList: Shirt.list( params ),
                  trouserList: Trouser.list( params )]
   }    
}

  index 闭包将请求重定向到清单。在list 闭包中我将最大参数设为10,然后使用动态方法Shirt.list 和 Trouser.list。然后返回Groovy Map,它有两个清单——衬衫清单和裤子清单。

  作为Java开发人员,当看到Shirt.list()时会自然认为是在Shirt 域类中的list 方法。然而,如果打开Shirt.groovy,会发现并没有此方法。对于Java开发人员来说,不了解Groovy的特性就使用Grails不仅是令人 困惑的,而且是死胡同。动态方法是Grails的特殊特性,它是构建于Groovy语言的一个非常特殊的特性元对象协议 (MOP)之上的。如此证明可以使用动态方法查询域类。因此,在控制器中,您将注意到在域类上调用的方法似乎在域类中不存在。您可以在这里阅读关于使用动 态方法查询的更多信息。可以在这里找到对Grails控制器和域类中可用的动态方法的参考资料。

  既然控制器能够处理请求、获取清单并转发到视图,我需要创建相应视图。
创建自定义视图

  当创建控制器时,Grails还在grails-app/views 目录创建了一个新的显示目录,并将以下映射添加到web.xml 文件中。

<servlet-mapping>
<servlet-name>grails</servlet-name>
<url-pattern>/display/*</url-pattern>
</servlet-mapping>

  目前Grails有一个generate-views 命令,此命令能够生成基于域类的视图,然而没有能够自动生成视图的create-view 命令。请看图3中的例子。

Groovy和Grails简介图-3

  图3:一个显示Trousers的默认视图

  因为我希望创建一个独立于域类的视图,所以让我们手动创建视图文件。在目录grails-app/views/display/中,创建一个名为 list.gsp的文件,如清单6所示。

  清单6:list.gsp

<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <title>Display Shirt And Trouser List</title>
   <link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}"></link>
</head>
<body>
    <div class="nav">
       <span class="menuButton"><a href="${createLinkTo(dir:'')}">Home</a></span>
   </div>
   <div class="body">
      <h1>Shirt List</h1>
       <table>
         <tr>
          <th>Id</th><th>Cabinet</th> <th>Color</th><th>Name</th>
         </tr>
         <g:each in="${shirtList}">
          <tr>
           <td>${it.id}</td> <td>${it.cabinet.name}</td>
           <td>${it.color}</td> <td>${it.name}</td>
          </tr>
         </g:each>
         </table>
         <h1>Trouser List</h1>
         <table>
          <tr>
            <th>Id</th> <th>Cabinet</th>
            <th>Color</th> <th>Name</th>
          </tr>
          <g:each in="${trouserList}">
            <tr>
              <td>${it.id}</td> <td>${it.cabinet.name}</td>
              <td>${it.color}</td> <td>${it.name}</td>
            </tr>
          </g:each>               
         </table>           
         </div>
     </body>
</html>

  与我之前使用的方式类似,您现在也可以使用run-app 命令运行应用程序,或者创建一个war文件并将其部署到Tomcat。您应该在http://localhost:8080/ClothesMgt/display/下看到新的视图,如图4所示。

Groovy和Grails简介图-4

  图4:新创建的列出衬衫和裤子清单的视图

  现在让我们快速讨论一下Grails服务。
服务

  如果您想知道如何分开业务逻辑以及放置业务逻辑的位置,答案在Grails 服务中。服务以SomeNameService.groovy 格式命名,且被置于 /grails-app/services/目录。服务可利用依赖注入特性,您能够轻松地从控制器内部调用这些服务。

  让我们来看一个使用服务的例子。首先,使用create-service 命令创建新服务。运行此命令并命名服务Order。Grails将创建两个文件——grails-app/services /OrderService.groovy 和 grails-tests/OrderTests.groovy。

  现在编辑OrderService.groovy,如清单7所示。当引入新的orderGoods() 方法时会自动生成serviceMethod() 。

  清单7:OrderService.groovy

class OrderService {
   boolean transactional = true
   def serviceMethod() {
     // TODO
   }
   def orderGoods() {
     return "Order Placed - New shirts and trousers /
                               will be sent shortly."
   }
}

  现在编辑DisplayController,如清单8所示。引入使用OrderService的重排闭包。请注意服务将由Groovy注入。

  清单8:DisplayController.groovy

class DisplayController {
   OrderService orderService    
    
   def index = {redirect(action:list,params:params)}
    
   def list = {
         params['max'] = 10
         return [ shirtList: Shirt.list( params )
             , trouserList: Trouser.list( params )]
   }    
  
   def reorder = {
          render(orderService.orderGoods())
   }
    
}

  现在当您访问URL http://localhost:8080/ClothesMgt/display/reorder时,重排闭包将调用 OrderService,响应会被发回到浏览器。您能够以类似方式将全部业务逻辑移入服务,然后使用Grails的注入功能非常轻松地使用它们。
动态方法和属性

  正如之前提到的,域类没有能够从数据库获取数据或更新/删除现有数据的任何方法,例如find()、 findAll() 或 save() 。在控制器中您也没有编写诸如 redirect() 或 render() 之类的方法。但是域类和控制器有它们的计划目的,且允许所有要求的操作。原因是Grails中动态方法和属性的存在。动态方法被动态添加到类,就好像功能 是在程序中编译的一样。

  这些是可用的方法和属性,无需编写。这些动态方法涵盖了大多数Web应用程序开发中会碰到的常见情况。对于域类来说,存在诸如find()、 findAll()、list()、executeQuery()、save()和 delete()之类的动态方法。控制器具有诸如session、request和response之类的动态属性,以及诸如chain()、 render()和 redirect()之类的方法。要真正利用Grails的强大功能,您需要了解所有这些动态方法和属性的功能。
顺便介绍一下:自动重载和@Property

  Grails的一个重要特性是能够在开发过程中进行了更改时自动重载文件。因此只需编辑和保存gsp文件,就会自动重载新文件。然而这里创建 的类似OrderService 的事务服务不会被重载。您会在服务器控制台看到以下消息"[groovy] Cannot reload class [class OrderService] reloading of transactional service classes is not currently possible. Set class to non-transactional first. "。

  Grails的自动重载功能会为您节省许多时间,您就无需浪费时间来重启服务器了。我碰到过一些Grails不能自动重载的案例,例如将一个jsp文件重命名到gsp。然而,Grails的这项功能有望在未来版本中得到进一步改进。

  在Groovy JSR 06 的之前版本中,您必须使用@Property 来定义Groovy中的新属性。因此您会在线看到许多使用@Property的旧的Groovy例子。然而请注意,@Property已经从Groovy JSR 06中移除,在Grails 0.2和之后的版本中也不会再需要它。请参阅@Property 建议来获得更多细节。
结束语

  在本文中,我介绍了Grails框架的基本特性,并使用Grails创建了一个应用程序。Groovy和Grails最大的好处是一切都运行 在优秀的旧Java和Java EE上——因此您能够使用Groovy和Grails的RAD特性快速开发应用程序,然后将应用程序部署到可靠的Java EE服务器上。考虑到关于Ruby和Rails的宣传噪音,显然需要一个Java备选方案。Groovy和Grails看起来非常适合这个角色。

你可能感兴趣的:(java,javaee,服务器,grails,groovy,redirect)