【问题标题】:Inject grails application configuration into service将 grails 应用程序配置注入服务
【发布时间】:2011-06-25 19:49:55
【问题描述】:

我正在创建一个 grails 服务,它将通过 Java 库与第 3 方 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. 在服务上提供某种形式的构造器,允许在实例化时将凭据传递给服务?

将凭据注入服务是理想的。这怎么可能?

【问题讨论】:

  • 如果有某种方法可以注入实际的配置属性而不是整个 grailsApplication 对象,那仍然会很好。

标签: grails grails-controller


【解决方案1】:

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();
    }
}

【讨论】:

  • 请注意,我发现您需要在方法中使用 grailsApplication.config.[...]。否则,如果您尝试从方法外部的配置文件中提取数据,您将看到一个空指针。
  • 谢谢@arcdegree。你的评论让我很沮丧。
【解决方案2】:

尽管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 都支持不同的环境配置。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      最好的选择是(来自grails docs):

      1 - 使用 Spring @Value 注释

      import org.springframework.beans.factory.annotation.Value
      
      class WidgetService {
      
          int area
      
          @Value('${widget.width}')
          int width
      
          def someServiceMethod() {
              // this method may use the width property...
          }
      }
      

      2 - 让你的班级实现GrailsConfigurationAware

      import grails.config.Config
      import grails.core.support.GrailsConfigurationAware
      
      class WidgetService implements GrailsConfigurationAware {
      
          int area
      
          def someServiceMethod() {
              // this method may use the area property...
          }
      
          @Override
          void setConfiguration(Config co) {
              int width = co.getProperty('widget.width', Integer, 10)
              int height = co.getProperty('widget.height', Integer, 10)
              area = width * height
          }
      }
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 1970-01-01
      相关资源
      最近更新 更多