将grails应用程序配置注入服务

时间:2011-02-11 20:51:25

标签: grails grails-controller

我正在创建一个grails服务,它将通过Java库与第三方REST API进行交互。 Java库需要通过URL,用户名和密码来获取REST API的凭据。

我想将这些凭据存储在configuration/Config.groovy中,使它们可用于服务,并确保在服务需要之前可以使用凭据。

我感谢控制器可以使用grailsApplication.config,并且通过服务方法可以向服务提供相关的配置值,例如:

package example

class ExampleController {

    def exampleService

    def index = { }

    def process = {
        exampleService.setCredentials(grailsApplication.config.apiCredentials)
        exampleService.relevantMethod()
    }
}


package example

import com.example.ExampleApiClient;

class ExampleService {

    def credentials

    def setCredentials(credentials) {
        this.credentials = credentials
    }

    def relevantMethod() {

        def client = new ExampleApiClient(
            credentials.baseUrl,
            credentials.username,
            credentials.password
        )

        return client.action();
    }
}

我觉得这种方法有点缺陷,因为它取决于调用setCredentials()的控制器。将凭证自动提供给服务将更加健壮。

这两个选项中的任何一个都可行(我目前对grails不够熟悉):

  1. 创建服务时,将grailsApplication.config.apiCredentials注入控制器中的服务?

  2. 在服务上提供某种形式的构造函数,允许在实例化时将凭据传递给服务吗?

  3. 将凭据注入服务是理想的。怎么可以这样做?

3 个答案:

答案 0 :(得分:79)

grailsApplication对象在服务中可用,允许:

package example

import com.example.ExampleApiClient;

class ExampleService {

    def grailsApplication

    def relevantMethod() {

        def client = new ExampleApiClient(
            grailsApplication.config.apiCredentials.baseUrl
            grailsApplication.config.apiCredentials.username,
            grailsApplication.config.apiCredentials.password
        )

        return client.action();
    }
}

答案 1 :(得分:11)

尽管可以在服务中注入grailsApplication,但我认为服务不应该处理配置,因为它更难以测试并打破Single Responsibility principle。另一方面,Spring可以以更健壮的方式处理配置和实例化。 Grails在其文档中有a dedicated section

要使您的示例使用Spring,您应该在resources.groovy

中将服务注册为bean
// Resources.groovy
import com.example.ExampleApiClient

beans {
    // Defines your bean, with constructor params
    exampleApiClient ExampleApiClient, 'baseUrl', 'username', 'password'
}

然后,您将能够将依赖项注入您的服务

class ExampleService {
    def exampleApiClient

    def relevantMethod(){
        exampleApiClient.action()
    }
}

此外,在您的Config.groovy文件中,您可以使用Grails约定优先于配置语法覆盖任何bean属性:beans.<beanName>.<property>

// Config.groovy
...
beans.exampleApiClient.baseUrl = 'http://example.org'

Config.groovyresources.groovy都支持不同的环境配置。

答案 2 :(得分:4)

对于无法注入grailsApplication bean的上下文(服务不是其中之一,如Jon Cram所述),例如位于src / groovy中的帮助器类,您可以使用 Holders访问它类:

def MyController {
   def myAction() {
      render grailsApplication == grails.util.Holders.grailsApplication
   }
}