Model view controller 如何在不同的grails控制器中共享通用方法?

Model view controller 如何在不同的grails控制器中共享通用方法?,model-view-controller,grails,grails-controller,Model View Controller,Grails,Grails Controller,目前,当我需要在不同的控制器之间共享类似于processParams(params)的方法时,我使用继承或服务。 这两种解决方案都有一些不便之处: 对于继承,您不能使用多重继承,这意味着您需要将所有控制器实用程序方法放在一个位置。此外,grails中还有一个bug,在开发模式下无法检测到基本控制器类中的任何代码更改(您需要重新启动应用程序) 使用服务,您无法访问所有注入的属性,如参数、会话、刷新 所以我的问题是:有没有其他方法可以使用一些可供多个控制器访问的常用方法?这无助于解决在开发模式下

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

  • 对于继承,您不能使用多重继承,这意味着您需要将所有控制器实用程序方法放在一个位置。此外,grails中还有一个bug,在开发模式下无法检测到基本控制器类中的任何代码更改(您需要重新启动应用程序)
  • 使用服务,您无法访问所有注入的属性,如参数、会话、刷新

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

这无助于解决在开发模式下重新启动的问题,但这是我解决这个问题的方法。这很难看,可能不是好的做法,但我将公共代码作为闭包考虑到类中。然后我可以做一些类似的事情:

new ControllerClosures().action(this)
从controllerClosures类中的

def action={
    it.response.something
    return [allYourData]
}
您可以使用:

对于控制器,请直接在实例字段(或空构造函数)中分配帮助器类:


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

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

这里有一个小例子:

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

@Mixin(MyControllerCategory)
class SomethingController {

    def create = {
        printParams()
        ...
    }

    def save = {
        printParams()
    }
}

公共功能是对新类的调用,而不一定是对公共祖先的调用。问题表述缺少对其的责任陈述。不用说,我们为其创建一个新类是一项单独的责任。我会根据班级责任做出进一步的决定

我更喜欢混合使用RobbertJared的答案:我构造额外的类,将必要的控制器内部作为参数传递给它们。有时,课程是从一开始发展起来的。 比如:

不那么简单,但可以让您在测试中获得代码并保持低耦合

由于
SomeResponsibilityDoer
只会有几个字段-请求一个响应-用每个请求构造它并不是什么大问题

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

  • 最初,您可以在一些控制器文件中声明它-它将被重新加载。完成后,希望它不会经常更改,所以将其移动到
    src/groovy
  • 更重要的是,对于设计来说,在单元测试下开发比在应用程序运行和重新加载控制器下开发更快更好

  • 您可以在commonService中编写所有常用方法
    并将该服务用于envoke commmon method

    委托类无权访问所有者类的内部,例如render方法或params。不幸的是,这是事实,因此在这种情况下,
    @delegate
    将不是选择的方法。实际上,使用
    @Mixin
    注释不需要
    @Category
    注释。-只有在使用替代方法
    SomethingController.mixin([MyControllerCategory])
    时才需要它(这需要
    MyControllerCategory
    提供一个
    static
    方法
    printParams()
    )。Groovy文档提供了与您类似的示例,但这不是必需的。-这种误解可能是因为类别的使用经历了一个进化过程——曾经语法笨拙,现在被
    @Mixin
    注释所取代。最后,
    @Mixin
    @Delegate
    之间的主要区别在于委托方法是静态编译到目标类中的,而Mixin方法是在运行时调用的。有没有办法使
    MyControllerCategory
    服从依赖项注入?如果使用此模式,并使用Spock运行问题测试,如果混合类在Spock测试之间重置,请在此处查看解决方案:
    traits
    正在替换
    @Mixin
    ,而
    @Mixin
    已被Groovy 2.3弃用。更多关于特质的信息:&
    class HelperClass {
        def renderFoo() { render 'foo' }
    }
    
    class FooController {
        private @Delegate HelperClass helperClass = new HelperClass()
    
        def index = { this.renderFoo() }
    }
    
    @Category(Object)
    class MyControllerCategory {
        def printParams() {
            println params
        }
    }
    
    @Mixin(MyControllerCategory)
    class SomethingController {
    
        def create = {
            printParams()
            ...
        }
    
        def save = {
            printParams()
        }
    }
    
    def action = {
      def doer = SomeResponsibilityDoer(this.request, this.response)
      render doer.action()
    }