你如何在不同的grails控制器中共享常用方法?

时间:2010-11-16 15:00:16

标签: model-view-controller grails grails-controller

目前,当我需要在不同控制器之间共享类似processParams(params)的方法时,我使用继承或服务。 这两种解决方案都有一些不便之处:

  • 使用继承,您不能使用多重继承,这意味着您需要将所有控制器实用程序方法放在一个位置。而且,grails中存在一个错误,它在开发模式下没有检测到基本控制器类中的任何代码更改(您需要重新启动应用程序)
  • 使用服务,您无法访问所有注入的属性,如params,session,flush ...

所以我的问题是:有没有其他方法可以使用一些可用于多个控制器的常用方法?

5 个答案:

答案 0 :(得分:22)

我喜欢的一个选项是将常用方法编写为类别,然后根据需要将其混合到控制器中。它提供了比继承更多的灵活性,可以访问诸如params之类的东西,并且代码简单易懂。

这是一个很小的例子:

@Category(Object)
class MyControllerCategory {
    def printParams() {
        println params
    }
}

@Mixin(MyControllerCategory)
class SomethingController {

    def create = {
        printParams()
        ...
    }

    def save = {
        printParams()
    }
}

答案 1 :(得分:3)

这对您重新启动开发模式问题没有帮助,但这是我解决此问题的方法。这很丑陋,可能不是很好的做法,但我将公共代码作为闭包考虑在内。然后我可以做类似的事情:

new ControllerClosures().action(this)

和来自controllerClosures类的

def action={
    it.response.something
    return [allYourData]
}

答案 2 :(得分:3)

通用功能是对新类的调用,不一定是共同的祖先。问题的提法缺少责任声明。毋庸置疑,我们为此创建一个新类是一个单一的责任。我根据课堂责任做出进一步的决定。

我更喜欢混合使用 robbbert Jared 的答案:我构建了额外的类,将必要的控制器内部作为参数传递给它们。有时课程从method objects开始。 像:

def action = {
  def doer = SomeResponsibilityDoer(this.request, this.response)
  render doer.action()
}

不是那么简短,但是让你在测试中获得代码并保持低耦合。

由于SomeResponsibilityDoer只会有几个字段 - 请求回复 - 每次请求构建它都不是一件大事。

在开发者的控制器更改中没有重新加载SomeResponsibilityDoer也没什么大不了的,因为:

  1. 最初,您可以在某些Controller文件中声明它 - 它将被重新加载。完成后,希望它不会经常更改,因此请将其移至src/groovy
  2. 更重要的是,在单元测试下开发设计比在运行和重新加载控制器的应用程序下更快更好。

答案 3 :(得分:2)

您可以使用Delegation design pattern

class Swimmer {
    def swim() { "swimming" }
}

class Runner {
    def run() { "running" }
}

class Biker {
    def bike() { "biking" }
}

class Triathlete { 
    @Delegate Swimmer swimmer
    @Delegate Runner runner
    @Delegate Biker biker
}

def triathlete = new Triathlete(
    swimmer: new Swimmer(),
    runner: new Runner(),
    biker: new Biker()
)

triathlete.swim()
triathlete.run()
triathlete.bike()

如果是控制器,直接在实例字段(或在nullary构造函数中)分配助手类:

class HelperClass {
    def renderFoo() { render 'foo' }
}

class FooController {
    private @Delegate HelperClass helperClass = new HelperClass()

    def index = { this.renderFoo() }
}

delegate的类型信息被编译到包含类中。

答案 4 :(得分:1)

您可以在commonService中编写所有常用方法 并使用该服务来调用commmon方法