你使用什么动态Groovy功能?

时间:2013-02-03 22:16:19

标签: grails groovy

在开发Grails应用程序时,我没有进行任何元类编程或(明确地)利用Groovy的任何动态功能。我觉得我错过了。您能否举例说明在Grails项目中何时/何时/如何使用Groovy的动态功能(例如,您是否向域,控制器添加方法)?

2 个答案:

答案 0 :(得分:1)

不是Grails项目,但我在JBoss Seam项目中工作了两年,使用了大量的Groovy代码。我们通常有一些服务类,其第一个参数方法通常是模型类。通过类别,他们变得真正面向对象:

class InvoiceService {
  static void sendToWs(Invoice invoice, wsEndpoint) {
    // neat stuff
  }

  static void validate(Invoice invoice) throws InvoiceValidationException {
    // more neat stuff
  }

  static InternationalInvoice buildInternationalInvoice(Invoice invoice) {
    // builds new object
  }
}


def invoice = new Invoice()

use(InvoiceService) {
  invoice.validate()
  invoice.sendToWs endpoint
}

我相信同样适用于Grails。

我们还构建了很多位置文本文件,我们在类别下使用了很多groovy方法:

class PositionalFormatCategory {
  static String pad(String value, Integer times) {
    value.trim().padRight times, " "
  }
  static String pad(BigDecimal value, Integer times) {
    value.toString().padLeft times, " "
  }
}

但是Groovy在解析/编写XML方面真的很震撼。我们有一个模型类,必须转换为4种不同的XML格式

class XmlFormat1 {
  ServiceInvoice invoice

  String toXml() {
    new StreamingMarkupBuilder().bind {
      xml {
        price invoice.value
        date invoice.creationDate
        invoice.items.each { item ->
          invoiceItem {
            price item.price
            quantity item.qty
          }
        }
      }
    }
  }
}

我们使用元编程挂钩到一个小的lib方法,该方法连接到可能关闭的休息服务(我不记得lib名称)。我们联系它来定义超时,否则它将花费一整天而不会失败:

def oldConnect = RestConn.metaClass.&connect
RestConn.metaClass.connect = {
  try {
    delegate.setTimeout 5000
    oldConnect()
  } catch (TimeoutException t) {
    throw new BusinessException("Timeout connecting to the server")
  }
}

难以击败: - )

答案 1 :(得分:0)

我使用元编程功能来简化应用程序级别的工作。

E.G。我们有一个搜索引擎,需要在创建/更新时编制索引,还需要一些动态的查找器方法来从索引中获取内容。

class SearchableClass {
    static searchable = ['foo']

    String foo
}
def searchService = [ search:{ Class clazz, Map opts, String query ->  // This would be a real service
    // doSearch
    query.collect { it }
} ]

def searchBindService = [ bindSearch:{ Class clazz ->  // This would be a real service
    clazz.metaClass.static.with {
        search = searchService.search.curry(clazz, [:])
        searchOne = { String q ->
            searchService.search(clazz, [:], q).take(1)
        }
    }
} ]

[SearchableClass, String, Map, List].findAll { // Only get things that have the 'searchable' static prop
    try {
        it.searchable != null
    }catch(e){ }
}.each searchBindService.bindSearch


assert ["q", "u", "e", "r", "y"] == SearchableClass.search('query')
assert ["q"] == SearchableClass.searchOne('query')