考虑这个现实世界的例子,这是编写的代码,使“GET”和“POST”呼吁通过REST客户端生成器(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;
}
Groovy的1.8封添加成分,因此,如果您使用的是版本的Grails的,它使用Groovy的1.8或更高版本:
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
}
这是否会足够?
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方法。
还要注意,而不是创造, RestBuilder
每个HTTP调用,我建议把它作为一个bean如上所示resources.groovy
并在使用时它注入到类。 如果它是一个Grails神器(控制器,服务),那么它就会自动连接,否则豆rest
必须适当接线。 您可以通过使用抽象doGetCall
和doPostCall
或完全如果需要删除它们。
文章来源: How to refactor duplication out of closures that are an argument to a method call in Groovy?