groovy @Category(Object)的作用是将一个Groovy类或对象作为一个扩展类或对象添加到现有的Java类或对象中,可以扩展现有类的功能或添加新的方法。

举例说明:

假设有一个Java类Person,我们可以使用Groovy的@Category注解来添加一个扩展类,增加一个方法sayHello:

class Person {
    String name

    Person(String name) {
        this.name = name
    }
}

@Category(Person)
class PersonExtension {
    String sayHello() {
        "Hello, ${delegate.name}!"
    }
}

def person = new Person("Jack")
assert person.sayHello() == "Hello, Jack!"

在这个例子中,我们使用@Category注解将PersonExtension类作为Person类的扩展类添加进去,可以通过实例化Person类并调用sayHello方法来得到输出结果。

现在,我们来编写一个基于HttpClient的自定义DSL来实现get、post、delete等请求方法,内部管理一个连接池,支持Http和Https协议,单个请求支持是否使用代理,请求异常时自动重试,入参和出参类型转换等功能。

首先,我们需要引入HttpClient的依赖:

@Grab(group='org.apache.httpcomponents', module='httpclient', version='4.5.13')

然后,我们可以使用Groovy的DSL语法来编写HttpRequest类:

class HttpRequest {
    private final CloseableHttpClient httpClient
    private final String url
    private final HttpMethod method
    private final ContentType contentType
    private final Map<String, String> headers
    private final Map<String, Object> params
    private final boolean useProxy
    private final int maxRetry
    private final int retryInterval
    private final Map<Class, Class> convertTypeMap

    HttpRequest(CloseableHttpClient httpClient, String url, HttpMethod method, ContentType contentType,
                Map<String, String> headers, Map<String, Object> params, boolean useProxy, int maxRetry,
                int retryInterval, Map<Class, Class> convertTypeMap) {
        this.httpClient = httpClient
        this.url = url
        this.method = method
        this.contentType = contentType
        this.headers = headers ?: [:]
        this.params = params ?: [:]
        this.useProxy = useProxy
        this.maxRetry = maxRetry ?: 0
        this.retryInterval = retryInterval ?: 0
        this.convertTypeMap = convertTypeMap ?: [:]
    }

    def execute() {
        def request = new HttpUriRequestBuilder(method, url)
                .contentType(contentType)
                .headers(headers)
                .params(params)
                .useProxy(useProxy)
                .build()

        def retryCount = 0
        while (retryCount <= maxRetry) {
            try {
                def response = httpClient.execute(request)
                def entity = response.entity
                def statusCode = response.statusLine.statusCode

                if (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) {
                    def content = entity.content
                    def contentType = entity.contentType
                    def charset = contentType?.charset?.name() ?: "UTF-8"
                    def result = content.text(charset)

                    if (convertTypeMap.containsKey(result?.getClass())) {
                        result = result as convertTypeMap[result.getClass()]
                    }

                    return result
                } else {
                    throw new RuntimeException("HTTP request failed with status code ${statusCode}")
                }
            } catch (Exception e) {
                if (retryCount < maxRetry) {
                    retryCount++
                    Thread.sleep(retryInterval)
                } else {
                    throw e
                }
            }
        }
    }
}

在这个类中,我们使用了Groovy的默认参数和Map默认值的特性,使得实例化HttpRequest类时可以省略一些参数。execute方法中,我们使用了HttpClient的CloseableHttpClient、HttpUriRequestBuilder和HttpResponse等类来执行HTTP请求,并添加了重试和类型转换等功能。

接下来,我们可以编写一个DSL类HttpDSL,提供get、post、delete等方法,以及连接池、代理、重试、类型转换等配置:

class HttpDSL {
    private final CloseableHttpClient httpClient
    private final boolean usePool
    private final int maxPoolSize
    private final int connectionTimeout
    private final int socketTimeout
    private final Map<String, Object> defaultParams
    private final boolean useProxy
    private final String proxyHost
    private final int proxyPort
    private final int maxRetry
    private final int retryInterval
    private final Map<Class, Class> convertTypeMap

    HttpDSL(boolean usePool = true, int maxPoolSize = 50, int connectionTimeout = 5000, int socketTimeout = 5000,
            Map<String, Object> defaultParams = [:], boolean useProxy = false, String proxyHost = null, int proxyPort = 0,
            int maxRetry = 0, int retryInterval = 5000, Map<Class, Class> convertTypeMap = [:]) {
        def builder = HttpClientBuilder.create()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectTimeout(connectionTimeout)
                        .setSocketTimeout(socketTimeout)
                        .build())

        if (usePool) {
            builder.setConnectionManager(new PoolingHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build()))
                    .setMaxConnTotal(maxPoolSize)
                    .setMaxConnPerRoute(maxPoolSize)
        }

        httpClient = builder.build()

        this.usePool = usePool
        this.maxPoolSize = maxPoolSize
        this.connectionTimeout = connectionTimeout
        this.socketTimeout = socketTimeout
        this.defaultParams = defaultParams
        this.useProxy = useProxy
        this.proxyHost = proxyHost
        this.proxyPort = proxyPort
        this.maxRetry = maxRetry
        this.retryInterval = retryInterval
        this.convertTypeMap = convertTypeMap
    }

    def get(String url, Map<String, Object> params = [:], Map<String, String> headers = [:], ContentType contentType = null) {
        new HttpRequest(httpClient, url, HttpMethod.GET, contentType, headers,
                defaultParams + params, useProxy, maxRetry, retryInterval, convertTypeMap)
                .execute()
    }

    def post(String url, Map<String, Object> params = [:], Map<String, String> headers = [:], ContentType contentType = null) {
        new HttpRequest(httpClient, url, HttpMethod.POST, contentType, headers,
                defaultParams + params, useProxy, maxRetry, retryInterval, convertTypeMap)
                .execute()
    }

    def delete(String url, Map<String, Object> params = [:], Map<String, String> headers = [:], ContentType contentType = null) {
        new HttpRequest(httpClient, url, HttpMethod.DELETE, contentType, headers,
                defaultParams + params, useProxy, maxRetry, retryInterval, convertTypeMap)
                .execute()
    }

    def useProxy(String host, int port) {
        new HttpDSL(usePool, maxPoolSize, connectionTimeout, socketTimeout, defaultParams,
                true, host, port, maxRetry, retryInterval, convertTypeMap)
    }

    def maxRetry(int count) {
        new HttpDSL(usePool, maxPoolSize, connectionTimeout, socketTimeout, defaultParams,
                useProxy, proxyHost, proxyPort, count, retryInterval, convertTypeMap)
    }

    def retryInterval(int interval) {
        new HttpDSL(usePool, maxPoolSize, connectionTimeout, socketTimeout, defaultParams,
                useProxy, proxyHost, proxyPort, maxRetry, interval, convertTypeMap)
    }

    def convertType(Class fromType, Class toType) {
        new HttpDSL(usePool, maxPoolSize, connectionTimeout, socketTimeout, defaultParams,
                useProxy, proxyHost, proxyPort, maxRetry, retryInterval, convertTypeMap + [(fromType): toType])
    }

    def setDefaultParams(Map<String, Object> params) {
        new HttpDSL(usePool, maxPoolSize, connectionTimeout, socketTimeout, params,
                useProxy, proxyHost, proxyPort, maxRetry, retryInterval, convertTypeMap)
    }

    def close() {
        httpClient.close()
    }
}

在这个类中,我们使用了Groovy的方法链式调用和默认参数的特性,使得配置HttpDSL对象时可以省略一些参数。get、post、delete等方法中,我们使用了HttpRequest类来执行HTTP请求。useProxy、maxRetry、retryInterval、convertType和setDefaultParams等方法来配置连接池、代理、重试、类型转换和默认参数等选项。close方法用于关闭HttpClient的连接池。

现在,我们可以在Groovy脚本中使用HttpDSL来执行HTTP请求,例如:

def http = new HttpDSL(usePool: true, maxPoolSize: 50, maxRetry: 3)
def result = http.get("http://example.com", [q: "groovy"])
println result
http.close()

在这个例子中,我们使用HttpDSL类来创建一个HttpClient对象,并使用get方法来执行HTTP GET请求。请求参数包括查询字符串q=groovy,返回的结果会直接输出到控制台。最后,我们需要调用close方法来关闭HttpClient对象。

这样,我们就成功地使用Groovy DSL来实现了一个基于HttpClient的HTTP请求库,支持连接池、代理、重试、类型转换等功能

groovy CategoryObject作用是什么?举例说明编写一个基于HttpClient的自定义DSL来实现getpostdelete等请求方法内部管理一个连接池支持Http和Https协议单个请求支持是否使用代理请求异常时自动重试出入参类型转换等功能

原文地址: https://www.cveoy.top/t/topic/fDES 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录