考虑一下这个真实世界的例子,这个例子是为了使“GET'和' POST'通过Rest Client Builder(Grails插件)调用相同的REST服务端点。我不喜欢重复,因为标头和内容类型设置是相同的,但我不知道如何重构常见的部分,因为它们正在调用传递给get()或post()方法调用的闭包上的方法。请提供一个具体的例子,说明你的答案中重复的重构。
private def doGetCall(String endpoint, def config) {
def response = new RestBuilder().get(config.baseURI+endpoint) {
contentType("application/json")
header("Authorization", "ApiKey " + config.base64EncodedApiKey)
header("ClientId", config.clientId)
}
handleResponse(response, config, endpoint);
return response;
}
private def doPostCall(String endpoint, def payload, def config) {
def response = new RestBuilder().post(config.baseURI+endpoint) {
contentType("application/json")
header("Authorization", "ApiKey " + config.base64EncodedApiKey)
header("ClientId", config.clientId)
json(payload)
}
handleResponse(response, config, endpoint, payload)
return response;
}
答案 0 :(得分:2)
这样就够了吗?
class RestTestService {
def rest
def methodMissing(String name, args) {
if( !( name in ['get', 'post'] ) ) { // can add PUT & DELETE in future
// throw missing method exception for method names other than above
throw new MissingMethodException(
"Http Method $name does not exist or not yet implemented.")
}
def (endpoint, config, payload) = args?.toList()
def response = rest."$name"(config.baseURI + endpoint) {
contentType( "application/json" )
header("Authorization", "ApiKey " + config.base64EncodedApiKey )
header( "ClientId", config.clientId )
if ( name == 'post' && payload ) {
json( payload )
}
}
handleResponse(response, config, endpoint)
return response
}
private void handleResponse(def response, def config, def endpoint) { ... }
public def doGetCall(String endpoint, def config) {
get( endpoint, config )
}
public def doPostCall(String endpoint, def payload, def config) {
post( endpoint, config, payload )
}
}
//resources.groovy
beans = {
rest(grails.plugins.rest.client.RestBuilder)
}
上面使用methodMissing
来决定在运行时调用哪个http方法
另请注意,我建议不要为每个http调用创建RestBuilder
,而是将其用作resources.groovy
中所示的bean,并在使用它时将其注入类中。如果它是一个grails工件(控制器,服务),那么它将自动装配,否则必须适当地连接bean rest
。
您可以使用doGetCall
和doPostCall
进行抽象,也可以根据需要将其删除。
答案 1 :(得分:2)
Groovy 1.8添加了Closure组合,因此如果您使用的是使用Groovy 1.8或更高版本的Grails版本:
private def doGetCall(String endpoint, def config) {
def response = new RestBuilder().get(config.baseURI+endpoint, composeRequest(config))
handleResponse(response, config, endpoint);
return response;
}
private def doPostCall(String endpoint, def payload, def config) {
def response = new RestBuilder().post(config.baseURI+endpoint, composeRequest(config, { json(payload) }))
handleResponse(response, config, endpoint, payload)
return response;
}
private def composeRequest(def config, Closure clos = null) {
def request = {
contentType("application/json")
header("Authorization", "ApiKey " + config.base64EncodedApiKey)
header("ClientId", config.clientId)
}
if (clos != null) {
request = request << clos
}
request
}