Groovy和Grails简介(对抗ruby的j2ee框架)

导读:
   摘要
  Java Web应用程序框架是企业Java得以成功的重要原因之一。人们怀疑如果没有Apache Struts框架Java EE是否能够如此成功。虽然底层编程语言很重要,但通常是框架使编程语言成为引人注目的中心的。如果您经常访问讨论论坛,就会注意到Ruby语言和Ruby On Rails框架之间也是这种情况。Ruby已经出现十多年了,然而只是在Ruby On Rails框架流行之后,开发人员才开始注意到Ruby语言。
  诸如Ruby、PHP和Python之类的脚本语言最近几年越来越流行,因此,需要开发一个Java脚本备选语言和类似Rails的针对Java环境的框架。Groovy就是这个脚本语言,而Grails就是这个框架。
  在本文中我将讨论Groovy的Web开发功能,然后继续讨论Grails框架。我将开发一个示例Grails Web应用程序,并讨论此框架的各种特性。
   Groovy是什么?
  Groovy是一种语言,其语法类似于Java,但比Java更简单。它通常被视为脚本/灵活/动态的语言,但是我不喜欢这类形容词,因为我认为它们只会令人困惑。如果说Java是一位明智的中年男子,那么Groovy就是他十几岁的儿子。Groovy具有父亲的许多特点,但是更为狂野且更为有趣。他们也可以很好地合作。
  Groovy的规则比Java少得多。例如,要在Java中获得标准的"Hello World"输出,您需要编写一个类、一个具有合适参数的主方法,等等。但是在Groovy中,如果不想编写所有样板代码,您可以抛开类定义和主方法,仅编写一行代码即可打印出"Hello World"。
  以下是打印Hello World的文件 Hello.groovy 的内容:
  println "Hello World"
  Java平台仅关心使字节码得到执行。同样,此平台不强迫您使用Java语言。只要提供了字节码,工作就会进行。Groovy代码会被编译为字节码,而对于Java平台来说,字节码是从Java代码还是Groovy代码生成的并没有任何区别。
  以下是一个Groovy例子,它显示了Groovy对清单、映射和范围的内置支持,并证明了Groovy的简单性及其利用Java的强大功能的能力:
  
  // Print Date
  def mydate = new java.util.Date()
  println mydate
  //Iterate through a map
  def numbersMAP = ['1':'ONE','2':'TWO']
  for (entry in numbersMAP) {
  println "${entry.key} = ${entry.value}"
  }
  //Introducing the range
  def range = 'a'..'d'
  //Lists
  def numberlist = [1,2,3,4,5,6,7,8]
  println numberlist;
  println "Maximum value: ${numberlist.max()}"
  
  请注意以上代码直接使用java.util.Date ,对收集的内置支持减少了使用清单、映射和范围所需的代码。还有许多其他有趣的Groovy特性,例如闭包和简化的XML处理。您可以在groovy.codehaus.org上找到详细清单。
  现在让我们来讨论如何将Groovy用于Web开发。
   使用Groovy进行Web开发
  大多数Java EE教程都从一个基本servlet例子开始。对于Groovy Web开发来说,您将从groovlet(在groovy中servlet的对应概念)开始。如果您在servlet中摆脱了类和doXX() 方法声明,那么剩下的内容就与groovlet很像了。以下是一个名为 Login.groovy 的groovlet例子,您需要将它置于Web应用程序的最高级目录:
  
  def username= request.getParameter("username")
  def password= request.getParameter("password")
  if (username == "java" &&password == "developer") {
  response.sendRedirect("home.jsp")
  session = request.getSession(true);
  session.setAttribute("name",username)
  }
  else {
  println """
  

Login Invalid


  

Your IP has been logged >${request.remoteHost}


  """
  paramMap = request.getParameterMap()
  println "

You Submitted:

"
  for (entry in paramMap) {
  println "${entry.key} = ${entry.value}
"
  }
  }
  
  您可以仅创建一个简单的HTML表单,然后将此表单的行为属性发送到 action="Login.groovy"。然后将以下标签添加到web.xml:
  
  
   Groovy
   groovy.servlet.GroovyServlet
  

  
   Groovy
   *.groovy
  

  
  现在只需将要求的Groovy jar 文件添加到WEB-INF/lib 目录,您的Groovy Web应用程序就准备好在任意Java EE应用服务器上运行了。
  您应该已经注意到代码中没有分号,而且使用了隐式变量如request和response。其他隐式变量有context、application、session、out、sout和 html。
  GSP是JSP在groovy中的对应概念。您无需使用println生成HTML;只需将Groovy代码嵌入HTML页面。本文中的例子将在提到Grails时使用GSP。
  请注意,因为所有代码最终都要转换为字节码,所以groovlet和GSP能够与servlet和JSP轻松协作。因此您无需区分groovlet和GSP或者servlet和JSP。
  现在让我们讨论前途无量的Grails框架。如果成功的话,Grails能够极大地改变开发Java Web应用程序的方式。Ruby on Rails对Ruby的影响,Grails也能够对Groovy实现。
   Grails特性和架构
  Grails试图使用Ruby On Rails的“规约编程”(coding by convention)范例来降低对配置文件和其他样板代码的需求。使用“规约编程” ,如果文件的名称本身就能说明此文件的用途,那么您就不需要在配置文件中再次声明这些内容了。此框架会查看文件名,并自己弄清文件用途。通过使用“规约编程” ,Grails还将自动生成Web应用程序中需要的许多内容。通过使用Grails,您将能够在很短的时间内、以最小的复杂性使Web应用程序就绪。请看以下例子。
  Grails基于开源技术,例如Spring、Hibernate和SiteMesh。如果您已经擅长这些技术,那么这是件好事;但是如果您由于某种原因不喜欢这些技术,或者您认为不仅需要学习Grails,还需要学习其他三种框架,那么这就不是件好事了。虽然这些技术能够帮助Grails执行得更好,但是学习四种框架对于大多数人来说是一个很高的门槛。Grails文档目前主要关注它与Spring、Hibernate和其他程序的集成,然而我认为它需要采用相反的方法,将Grails推行为一个简单快速的Web应用程序开发框架。开发人员无需担心或考虑底层发生了什么。
  幸运的是,一旦您开始使用Grails,您将发现Grails隐藏了这些框架的大多数底层复杂性。如果您忘掉在底层运行的是Spring、Hibernate和其他程序,那么事情就会变得简单。
  由视图和控制器组成的Web层
  由域类和服务组成的业务逻辑层
  由域类和数据源组成的持久层
  大多数框架都有数十种特性,其中只有很少几种得到了广泛使用。对于Grails来说,这种关键特性是指“规则编程”(coding by convention)范例和构件的自动生成。
  Grails的其他特性包括对Ajax、验证、单元测试和功能测试的内置支持。它使用免费的开源Canoo WebTest项目来实现Web应用程序的功能测试。Grails还提供与Quartz Scheduler的集成。
  现在是时候安装Grails框架并且编写您的第一个应用程序了。
   Grails安装
  安装过程非常简单。以下是Grails下载页面:http://grails.org/Download。您可以从http://dist.codehaus.org/grails/grails-bin-0.2.1.zip下载version 0.2.1。请注意Grails源代码和文档作为单独的下载提供。下载zip文件之后,只需将其内容解压缩到一个目录即可,在我的案例中此目录是 C:/groovy/grails-0.2.1/。
  创建一个名为GRAILS_HOME 的新环境变量,并将其值设为 C:/groovy/grails-0.2.1/。接下来将GRAILS_HOME/bin 添加到PATH 环境变量。这样安装就完成了。通过在命令提示符界面中运行grails 命令您可以检查安装是否成功。您应该获得此命令的使用信息。
  既然您有了一个运行中的Grails安装,那么您已经为创建Grails Web应用程序做好了准备。
   开发Grails应用程序:应用程序结构
  多年来我一直计划开发一个可以帮助我管理衣服的应用程序——这个应用程序应该能够告诉我我最喜欢的T恤衫放在哪里、是否洗过、是否熨过,等等。总有一天我会靠销售这个应用程序挣上几百万,但是现在我将把它用作Grails例子。
  第一步是创建一个Grails项目目录结构。在这一步我将在C:/groovy/grailsapps 创建一个新目录,并在此级别打开一个命令提示符窗口。在此窗口中,执行命令grails create-app。要求您输入应用程序名称。输入 ClothesMgt。Grails将显示它为您创建的全部目录和文件。图1显示了最后得到的命令结构。
  


  
  图1:Grails项目目录结构
  此命令将创建约800 KB大小的文件和目录。这里的想法是此框架遵循已经建立的Web应用程序开发惯例,因此它创建的文件和目录在大多数Web应用程序中是有用的。虽然有些人可能不喜欢这种强制使用某种结构的想法,但是这种基于惯例的自动生成正是Grails的RAD特性的基础。
  如果更仔细地看一下这些目录,您就会发现存在用于诸如控制器、视图、测试、配置文件和标签库之类东西的目录。您还会发现存在一些基本JavaScript和CSS文件。那么现在应用程序的基本结构已经有了。您只需做些填空,应用程序即可就绪。
  请注意自动生成目录和文件的命令是可选的。您可以手动创建全部文件和目录。如果熟悉Apache Ant,那么您甚至可以打开GRAILS_HOME 目录中的/src/grails/build.xml 文件,来仔细查看每个Grails命令的用途。
   数据库
  在此例中我将使用一个 运行于localhost的名为Clothes_Grails的MySQL数据库。Grails内置一个HSQL数据库,这对测试简单的应用程序或仅试用Grails非常有用。如果您使用HSQL DB,那么无需执行以下几步。我将使用MySQL来证明您能够非常轻松地使用HSQL之外的数据库。
  从http://www.mysql.com/products/connector/j/下载MySQL驱动器,并将mysql-connector-java- -stable-bin.jar 文件放置在ClothesMgt/lib 目录中。接下来您需要编辑 ClothesMgt/grails-app/conf/ApplicationDataSource.groovy文件。
  现在此文件的内容应该类似以下内容:
  
  class ApplicationDataSource {
  boolean pooling = true
  String dbCreate = "create-drop"
  String url = "jdbc:mysql://localhost/Clothes_Grails"
  String driverClassName = "com.mysql.jdbc.Driver"
  String username = "grails"
  String password = "groovy"
  }
  
  现在让我们看一下如何使用此数据库和对象关系映射。
   域类
  Grails的对象关系映射(GORM)功能在内部使用Hibernate 3,但是您无需了解或更改任何Hibernate设置。Grails具有称为“域类”的东西,这些域类的对象被映射到数据库。您可以使用关系来链接域类,它们也提供用于CRUD(创建/读取/更新/删除)操作的功能非常强大的动态方法。
  在此例中,我们将创建三个域类,其名称分别是Shirt、Trouser和Cabinet。要创建域类,只需运行命令 grails create-domain-class。请记住在您的项目目录(而不是它的上级目录)内运行此命令。这是一个常见错误,虽然我已经提醒了您,您还是会犯至少一次这样的错误。
  您必须提供给create-domain-class 命令的唯一输入是类的名称。运行此命令三次,将Shirt、Trouser和Cabinet作为三个域类的名称。Grails现在将在目录 grails-app/domain/中创建这些域类。它们将仅具有两个属性id 和 version。我将为这些类添加属性,以便使它们更能代表衬衫、裤子和衣橱。
  清单1:Cabinet.groovy
  
  class Cabinet {
  Long id
  Long version
  String name
  String location
  def relatesToMany = [ shirts : Shirt,trousers : Trouser ]
  Set shirts = new HashSet()
  Set trousers = new HashSet()
  
  String toString() { "${this.class.name} : $id" }
  
  boolean equals(other) {
  if(other?.is(this))return true
  if(!(other instanceof Cabinet)) return false
  if(!id || !other?.id || id!=other?.id) return false
  return true
  }
  
  int hashCode() {
  int hashCode = 0
  hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)) )
  }
  }
  
  清单2: Trouser.groovy
  
  class Trouser {
  Long id
  Long version
  String name
  String color
  Cabinet cabinet
  def belongsTo = Cabinet
  String toString() { "${this.class.name} : $id" }
  
  boolean equals(other) {
  if(other?.is(this))return true
  if(!(other instanceof Trouser)) return false
  if(!id || !other?.id || id!=other?.id) return false
  return true
  }
  
  int hashCode() {
  int hashCode = 0
  hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32) ) )
  }
  }
  
  清单3: Shirt.groovy
  
  class Shirt {
  Long id
  Long version
  String name
  String color
  Cabinet cabinet
  def belongsTo = Cabinet
  
  String toString() { "${this.class.name} : $id" }
  
  boolean equals(other) {
  if(other?.is(this))return true
  if(!(other instanceof Shirt)) return false
  if(!id || !other?.id || id!=other?.id) return false
  return true
  }
  
  int hashCode() {
  int hashCode = 0
  hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)))
  }
  }
  
  我添加的仅有的几行声明了字段名称和颜色,然后声明了Cabinet、Shirt和Trouser之间的关系。每个Shirt和Trouser都属于Cabinet,而Cabinet具有shirt和trouser的集合。belongsTo 属性在此案例中是可选的,因为在一对多关系中,Grails会将“一”这一方视为所有者。因此您就无需显式声明了。在这里我进行显式声明只是为了使这种关系更明显。
  接下来我们将讨论Grails应用程序的控制器和视图部分。
   控制器和视图
  既然域类已经就绪,让我们使用generate-all命令自动生成基本CRUD Web应用程序。运行grails generate-all 命令三次,当被询问时提供域类名称。generate-all 命令的目的是生成每个域类的控制器和视图,但是由于bug-245,Grails 0.2.1不能生成控制器。您必须手动生成控制器,其方法是对每个域类使用generate-controller 命令。
  现在您应该在grails-app/controllers 目录中看到三个控制器。这些控制器负责处理Web应用程序中针对特定域类的请求。因此ShirtController.groovy 将处理Web应用程序中与Shirt域类相关的CRUD请求,等等。现在控制器具有多个闭包,每个闭包映射到一个URI。闭包是Groovy语言很好的一个特性,然而要习惯它还是需要一些时间的。清单4显示了Shirtcontroller.groovy的一段摘录。
  清单4:ShirtController.groovy 摘录
  
  class ShirtController {
  def index = { redirect(action:list,params:params) }
  def list = {
  [ shirtList: Shirt.list( params ) ]
  }
  def show = {
  [ shirt : Shirt.get( params.id ) ]
  }
  def delete = {
  def shirt = Shirt.get( params.id )
  if(shirt) {
  shirt.delete()
  flash.message = "Shirt ${params.id} deleted."
  redirect(action:list)
  }
  else {
  flash.message = "Shirt not found with id ${params.id}"
  redirect(action:list)
  }
  }
  // ...
  }
  
  在此例中,ShirtController 中的list闭包将处理URI是/shirt/list的请求,等等。您可在控制器中使用您习惯在Java Web应用程序中使用的东西,例如请求、会话和servletContext。
   请注意:闭包也将值作为显式返回语句返回,或者作为闭包体中的最后一个语句的值返回。不要因为Grails生成的代码中没有return 而困惑。
  一旦控制器完成了对请求的处理,它必须委托给合适的视图。Grails使用惯例机制实现此操作。因此ShirtController 中的list闭包将委托给视图 /grails-app/views/shirt/list.gsp 或 /grails-app/views/shirt/list.jsp。 尽管您在使用Grails,全部视图可以是JSP文件而不是GSP。我几乎没有编写任何代码,但是我已经准备好了一个Web应用程序。
  让我们尝试部署和运行我们的应用程序。
   在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所示的屏幕。
  


  
  图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 文件中。
  
  
   grails
   /display/*
  

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


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

  

Shirt List


  




  





                          
Id Cabinet Color Name
${it.id} ${it.cabinet.name}${it.color} ${it.name}

  

Trouser List


  





  





                             
Id CabinetColor Name
${it.id} ${it.cabinet.name}${it.color} ${it.name}

  

  
  
  
  与我之前使用的方式类似,您现在也可以使用run-app 命令运行应用程序,或者创建一个war文件并将其部署到Tomcat。您应该在http://localhost:8080/ClothesMgt/display/下看到新的视图,如图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看起来非常适合这个角色。
   下载
  下载本文中的代码:
  本文中的代码(zip)。
  最新版本的SVN快照。
   参考资料
  Grails主页
  Groovy主页
  Grails Wiki
  Grails Mailing 清单
  Groovy,Java's New Scripting Language(ONJava,2004)
  Getting to Know Groovy(Sun,2005)
  Groovy bridges the scripting and the enterprise Java worlds(IndicThreads,2006)
   作者其它文章

本文转自
http://dev2dev.bea.com.cn/techdoc/200601194089.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


背景:    8月29日,凌晨4点左右,某服务告警,其中一个节点直接down掉,收到告警的同事让运维重启。    9点左右,内存监控上发现内存异常,堆内存涨速很快,即便GC也没有什么效果,频繁GC。    9点38,服务各种超时,影响整个app使用。处理方式:    当时由于很想要
https://support.smartbear.comeadyapi/docs/soapui/steps/groovy.htmlGettestcaseobjectToobtaintheobjectwhichreferstothecontainingtestcase,usethefollowingcodesnippet:Groovy def case=testRunner.testCase; Byusingthe tes
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能。查看最流行的扩展机制,比较性能并分析哪一个是最好的。  这是乐队之战,JMeter风格。 BeanshellV.JSR223V.JavaRequestSampler 在我们之前的帖子中,  JMeterPerformance和TuningTips  ( 由fantastik
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,同时支持面向对象Groovy:jvm上的脚本,较好兼容java语法,Groovy加强了Java集成。 可配置化的优势,可以将一些简单的逻辑公开给外部编辑和使用,增强了互操作性,复杂逻辑来说,可配置化代码的调试则会比较麻烦 Scala和Java
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部元件的访问testRunner.testCase开头1、向下访问testRunner.testCase.testSteps[testStepName]testRunner.testCase.getTestStepByName("新增一个空间")2、向上访问,用于访问同一项目中的其他testSuites和testCase下
在运行groovy的junit方法时,报了这个错误:java.lang.ExceptionInInitializerError atorg.codehaus.groovy.reflection.ClassInfo.isValidWeakMetaClass(ClassInfo.java:271) atorg.codehaus.groovy.reflection.ClassInfo.getMetaClassForClass(ClassInfo.java:241) atorg.codeha
基本语法1.Grovvy的注释分为//和/**/和java的一样.2.Grovvy语法可以不已分号结尾.3.单引号,里面的内容严格的对应java中的String,不对$符号进行转义.defs1='iamastudent$'printlns1iamastudent$4.双引号“”的内容中如果有$号的话,会先对表达式先求值.de
Tiobe发布了最新一期(3月份)编程语言欢迎度榜单,其榜单根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube统计出排名数据。TOP5几乎没有变化,Java和C语言牢牢占据前两名。Python相较去年上升一位进入TOP3,C++下
我有一个Google地图组件,作者可以在其中指定纬度和经度.我正在使用带有正则表达式的常规“输入”类型控件来验证它们是否是数字,但是,当试图解决指定范围的问题时(经度验证该值在[-180,180]内并且纬度[-90,90])但是,通过正则表达式进行验证似乎很麻烦,而且利用inputtype=“numb
我正在为未来的应用程序评估SpringBoot,并希望使用Groovy模板来实现其纯粹的可读性.不幸的是,我在迭代我添加到控制器返回的ModelAndView对象的对象列表时遇到了麻烦.这是我的控制器:@RestController@RequestMapping("/ships")publicclassShipsController{@Autowired
我有一个基于Spring的java应用程序,其中包含一些有用的组件.作为系统的一部分,我有一个groovy脚本,来处理一些报告.我想从groovy脚本中调用spring组件.当我用Java编写时,我需要在@Component中使用@Autowired注释,即@ComponentclassReporter{@AutowiredSearchServicesearchS
在Grailsi18n插件definedthusly中定义了一个messageSourcebean:messageSource(PluginAwareResourceBundleMessageSource){basenames=baseNames.toArray()fallbackToSystemLocale=falsepluginManager=manager....}是否可以覆盖我的resources.groovy中的fa
我正在寻找一种方法来反向工程RDBMS表(MSSQLServer)并生成JPA@EntityGroovy类.我们目前没有选择使用Grails和/或GORM,因此Grailsdb-reverse-engineer插件似乎很接近但不太正确.它生成符合GORM的类而不是JPA实体类.我们目前有一个gradle构建,它利用org.hibernate.tool.ant.Hibe
https://blog.csdn.net/Gdeer/article/details/83062523一、直接运行groovy程序因为groovy插件和android插件不兼容,所以不能在原始项目上使用groovy。 新建module,创一个JavaLibrary,取名lib。  修改lib/build.gradleapplyplugin:'java-library'depe
一、自动生成GET请求脚本1、配置Createascript在ngrinder管理台主页,点击script–>Createascript,并填写脚本名称和请求的url,如下所示:点击Create按钮,nGrinder会自动生成对应的脚本结构,如果没有参数需要设置的话,可以直接运行了。二、详细解析GET请求脚本ngrinder自动生成的脚本
我正在关注使用列表和地图作为构造函数的this博文.为什么以下列表无法强制反对?classTest{staticclassTestObject{privateinta=1;protectedintb=2;publicintc=3;intd=4;Strings="s";}stati
Information:java:Errorsoccurredwhilecompilingmodule'security'Information:javac1.8.0_131wasusedtocompilejavasourcesInformation:2019/6/98:31-Buildcompletedwith1errorand0warningsin3s116msError:java:读取E:\repository\org
ngrinder中的groovy脚本结构类似junit,同时在junit的基础之上封装了自己的注解,用来控制脚本的运行。一、运行逻辑图如下:此处只列出了groovy脚本的逻辑,jython脚本是类似的,在此不再单独介绍。二、各注解的使用比较三、关注点在ngrinder中,通常使用单进程多线程就足够大部分测试了,所以:
我有一个switch语句来处理javaenumfoo,并使用spock编写一些groovy单元测试.我已经添加了一个测试,它验证当前是否处理了每种类型的foo而没有抛出异常.现在我想测试一个无法识别的foo类型会导致抛出异常.要做到这一点,我将不得不嘲笑枚举,并已经看到这里概述的解决方案:MockingJ
我有一个groovy实体ClientInvoiceAttachmentExt,它扩展了java实体ClientInvoiceAttachment.ClientInvoiceAttachment具有@Id注释,但仍然看到“没有为实体指定的标识符”错误这是我的堆栈跟踪[Mar0317:11:54]ERROR|org.springframework.web.context.ContextLoader|Contex