httpclient封装

1.为什么需要封装

httpclient原生的使用方式:

public static JSONObject getSingleDataSetDataPostInvoke(
            String baseUrl, String token, Integer projectId, Integer datasetId,
            String filePath, Integer offset, Integer limit) {
        CloseableHttpClient httpClient = getDefaultHttpClient();

        MessageFormat dataSetDataPostInvokeUrlForm = new MessageFormat(GET_SINGLE_DATASET_DATA_POST_INVOKE);
        String[] args = new String[]{projectId.toString(), datasetId.toString()};
        String dataSetDataPostInvokeUrl = dataSetDataPostInvokeUrlForm.format(args);

        HttpPost httpPost = new HttpPost(baseUrl + dataSetDataPostInvokeUrl);
        httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
        httpPost.addHeader("token", token);

        Map<String, Object> body = Maps.newHashMap();
        body.put("filePath", filePath);
        body.put("offset", offset);
        body.put("limit", limit);
        httpPost.setEntity(new StringEntity(Objects.requireNonNull(JSON.toJSONString(body)), Charsets.UTF_8));

        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            JSONObject responseObj = JSON.parseObject(EntityUtils.toString(response.getEntity(), Charsets.UTF_8));
            CheckUniverseResponse(responseObj);
            response.close();
            return responseObj;
        } catch (IOException e) {
            logger.error("获取Universe数据集数据后置调用失败, url:{}.", httpPost.getURI().toString(), e);
            throw new AtlasException(UNIVERSE_FAIL_TO_GET_DATASET_DATA, e.getMessage());
        }
    }

缺点:硬编码设置header,params,body等,还需要解析返回值,代码的可维护性低。

钉钉和蚂蚁封装的httpclient

----DINGDING---
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>dingtalk</artifactId>
  <version>1.1.93</version>
</dependency>

---alipay-----
<dependency>
  <groupId>com.alipay.sdk</groupId>
  <artifactId>alipay-sdk-java</artifactId>
  <version>4.18.0.ALL</version>
</dependency>

支付宝源码部分:

  public <T extends AlipayResponse> T execute(AlipayRequest<T> request) throws AlipayApiException {
        return this.execute(request, (String)null);
    }

    public <T extends AlipayResponse> T execute(AlipayRequest<T> request, String accessToken) throws AlipayApiException {
        return this.execute(request, accessToken, (String)null);
    }

    public <T extends AlipayResponse> T execute(AlipayRequest<T> request, String accessToken, String appAuthToken) throws AlipayApiException {
        return this.execute(request, accessToken, appAuthToken, (String)null);
    }

    public <T extends AlipayResponse> T execute(AlipayRequest<T> request, String accessToken, String appAuthToken, String targetAppId) throws AlipayApiException {
        if (!StringUtils.isEmpty(this.alipayRootCertSN)) {
            throw new AlipayApiException("检测到证书相关参数已初始化,证书模式下请改为调用certificateExecute");
        } else {
            AlipayParser<T> parser = null;
            if ("xml".equals(this.format)) {
                parser = new ObjectXmlParser(request.getResponseClass());
            } else {
                parser = new ObjectJsonParser(request.getResponseClass());
            }

            return this._execute(request, (AlipayParser)parser, accessToken, appAuthToken, targetAppId);
        }
    }

    public BatchAlipayResponse execute(BatchAlipayRequest request) throws AlipayApiException {
        long beginTime = System.currentTimeMillis();
        Map<String, Object> rt = this.doPost(request);
        if (rt == null) {
            return null;
        } else {
            Map<String, Long> costTimeMap = new HashMap();
            if (rt.containsKey("prepareTime")) {
                costTimeMap.put("prepareCostTime", (Long)((Long)rt.get("prepareTime")) - beginTime);
                if (rt.containsKey("requestTime")) {
                    costTimeMap.put("requestCostTime", (Long)((Long)rt.get("requestTime")) - (Long)((Long)rt.get("prepareTime")));
                }
            }

            AlipayParser<BatchAlipayResponse> parser = null;
            if ("xml".equals(this.format)) {
                parser = new ObjectXmlParser(request.getResponseClass());
            } else {
                parser = new ObjectJsonParser(request.getResponseClass());
            }

            BatchAlipayResponse batchAlipayResponse = null;

            try {
                ResponseEncryptItem responseItem = this.decryptResponse(request, rt, (AlipayParser)parser);
                batchAlipayResponse = (BatchAlipayResponse)((AlipayParser)parser).parse(responseItem.getRealContent());
                batchAlipayResponse.setBody(responseItem.getRealContent());
                this.checkResponseSign(request, (AlipayParser)parser, responseItem.getRespContent(), batchAlipayResponse.isSuccess());
                if (costTimeMap.containsKey("requestCostTime")) {
                    costTimeMap.put("postCostTime", System.currentTimeMillis() - (Long)((Long)rt.get("requestTime")));
                }

                List<AlipayParser<?>> parserList = new ArrayList();
                List<AlipayRequestWrapper> requestList = request.getRequestList();
                Iterator var11;
                AlipayRequestWrapper aRequestList;
                if ("xml".equals(this.format)) {
                    var11 = requestList.iterator();

                    while(var11.hasNext()) {
                        aRequestList = (AlipayRequestWrapper)var11.next();
                        parserList.add(new ObjectXmlParser(aRequestList.getAlipayRequest().getResponseClass()));
                    }
                } else {
                    var11 = requestList.iterator();

                    while(var11.hasNext()) {
                        aRequestList = (AlipayRequestWrapper)var11.next();
                        parserList.add(new ObjectJsonParser(aRequestList.getAlipayRequest().getResponseClass()));
                    }
                }

                if (!batchAlipayResponse.isSuccess()) {
                    return batchAlipayResponse;
                } else {
                    String[] responseArray = batchAlipayResponse.getResponseBody().split("#S#");

                    for(int index = 0; index < responseArray.length; ++index) {
                        AlipayResponse alipayResponse = ((AlipayParser)parserList.get(index)).parse(responseArray[index]);
                        alipayResponse.setBody(responseArray[index]);
                        batchAlipayResponse.addResponse(alipayResponse);
                    }

                    AlipayLogger.logBizDebug((String)rt.get("rsp"));
                    return batchAlipayResponse;
                }
            } catch (RuntimeException var14) {
                AlipayLogger.logBizError((String)rt.get("rsp"), costTimeMap);
                throw var14;
            } catch (AlipayApiException var15) {
                AlipayLogger.logBizError((String)rt.get("rsp"), costTimeMap);
                throw new AlipayApiException(var15);
            }
        }
    } 
    .......

使用:

//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.open.public.template.message.industry.modify 
AlipayOpenPublicTemplateMessageIndustryModifyRequest request = new AlipayOpenPublicTemplateMessageIndustryModifyRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数
//此次只是参数展示,未进行字符串转义,实际情况下请转义
request.setBizContent("  {" +
"    \"primary_industry_name\":\"IT科技/IT软件与服务\"," +
"    \"primary_industry_code\":\"10001/20102\"," +
"    \"secondary_industry_code\":\"10001/20102\"," +
"    \"secondary_industry_name\":\"IT科技/IT软件与服务\"" +
" }");
AlipayOpenPublicTemplateMessageIndustryModifyResponse response = alipayClient.execute(request); 
//调用成功,则处理业务逻辑
if(response.isSuccess()){
    //.....
}

钉钉源码部分:

    public <T extends AliyunResponse> T _execute(AliyunRequest<T> request, AliyunParser<T> parser)  throws ApiException {
        if (this.needCheckRequest) {
            try {
                request.check();
            } catch (ApiRuleException e) {
                T localResponse = null;
                try {
                    localResponse = request.getResponseClass().newInstance();
                } catch (Exception xe) {
                    throw new ApiException(xe);
                }
                localResponse.setErrorCode(e.getErrCode());
                localResponse.setMessage(e.getErrMsg());
                return localResponse;
            }
        }

        Map<String, Object> rt = doPost(request);
        if (rt == null)
            return null;

        T tRsp = null;
        if (this.needEnableParser) {
            try {
                tRsp = parser.parse((String) rt.get("rsp"));
                tRsp.setBody((String) rt.get("rsp"));
            } catch (RuntimeException e) {
                AliyunLogger.logBizError((String) rt.get("rsp"));
                throw e;
            }
        } else {
            try {
                tRsp = request.getResponseClass().newInstance();
                tRsp.setBody((String) rt.get("rsp"));
            } catch (Exception e) {
            }
        }

        tRsp.setParams((TaobaoHashMap) rt.get("textParams"));
        if (!tRsp.isSuccess()) {
            AliyunLogger.logErrorScene(rt, tRsp, accessKeyId);
        }
        return tRsp;
    }
    
    public <T extends AliyunResponse> Map<String, Object> doPost(AliyunRequest<T> request) throws ApiException {
        Map<String, Object> result = new HashMap<String, Object>();
        RequestParametersHolder requestHolder = new RequestParametersHolder();
        TaobaoHashMap appParams = new TaobaoHashMap(request.getTextParams());
        requestHolder.setApplicationParams(appParams);

        // 
        TaobaoHashMap protocalMustParams = new TaobaoHashMap();
        try{
            addProtocalMustParams(request, protocalMustParams);
        }
        catch (Exception e) {
            throw new ApiException(e);
        }
        requestHolder.setProtocalMustParams(protocalMustParams);

        TaobaoHashMap protocalOptParams = new TaobaoHashMap();
        addProtocalOptParams(protocalOptParams);
        requestHolder.setProtocalOptParams(protocalOptParams);
        
        String url = null;
        try {
            // 
            protocalMustParams.put(AliyunConstants.SIGNATURE,
                    AliyunSignature.computeSignature(requestHolder.getAllParams(), accessKeySecret));
            
             String query = paramsToQueryString(requestHolder.getAllParams());
             url = (serverUrl.endsWith("/") ? serverUrl : (serverUrl + "/")) + "?" + query;
        } catch (Exception e) {
            throw  new ApiException(e);
        }
        
        String rsp = null;
        try {
            // 
            if (request instanceof AliyunUploadRequest) {
                AliyunUploadRequest<T> uRequest = (AliyunUploadRequest<T>) request;
                Map<String, FileItem> fileParams = TaobaoUtils.cleanupMap(uRequest.getFileParams());
                rsp =AliyunWebUtils.doPost(url, null, fileParams,Constants.CHARSET_UTF8, connectTimeout, readTimeout,request.getHeaderMap());
            } else {
                rsp = AliyunWebUtils.doPost(url, null,Constants.CHARSET_UTF8, connectTimeout, readTimeout,request.getHeaderMap());
            }
        } catch (IOException e) {
            throw new ApiException(e);
        }
        result.put("rsp", rsp);
        result.put("textParams", appParams);
        result.put("protocalMustParams", protocalMustParams);
        result.put("protocalOptParams", protocalOptParams);
        result.put("url", url);
        return result;
    }
...

参考支付宝和钉钉,我们也可以对httpclient进行简单封装,满足我们业务需要的同时,使使用起来更简单,可维护性更好。

2.封装源码

package com.alibaba.fetchdata.common.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fetchdata.common.http.base.BaseHttpRequest;
import com.alibaba.fetchdata.common.http.base.BaseHttpResponse;
import com.alibaba.fetchdata.common.http.common.HttpTemplateException;
import com.alibaba.fetchdata.common.http.common.HttpTemplateUtils;
import com.alibaba.fetchdata.common.http.common.Method;
import com.alibaba.fetchdata.common.http.config.HttpTemplateConfig;
import com.alibaba.fetchdata.common.http.config.RouteConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpTemplate {
    private CloseableHttpClient httpClient;
    private HttpTemplateHandler httpTemplateHandler;
    private Map<String, RouteConfig> routes;

    public HttpTemplate(HttpTemplateConfig httpTemplateConfig, HttpTemplateHandler httpTemplateHandler) {
        if (httpTemplateConfig == null) {
            this.httpClient = createHttpClient(new HttpTemplateConfig(null));
            this.routes = Collections.emptyMap();
        } else {
            this.httpClient = createHttpClient(httpTemplateConfig);
            this.routes = httpTemplateConfig.getRoutes();
        }
        if (httpTemplateHandler == null) {
            this.httpTemplateHandler = new HttpTemplateHandler() {
            };
        } else {
            this.httpTemplateHandler = httpTemplateHandler;
        }
    }

    public <T extends BaseHttpResponse> T execute(BaseHttpRequest<T> baseHttpRequest) throws Exception {
        HttpGet httpGet = null;
        HttpPost httpPost = null;
        BaseHttpResponse baseHttpResponse = null;
        if (baseHttpRequest == null)
            throw new IllegalArgumentException("request is null");
        if (baseHttpRequest.getResponseClass() == null)
            throw new IllegalArgumentException("HttpTemplate ResponseClass is null");
        if (!this.httpTemplateHandler.onStart(baseHttpRequest))
            return (T)HttpTemplateUtils.newResponse(baseHttpRequest, "HttpTemplate request deny");
        if (!baseHttpRequest.check())
            return (T) HttpTemplateUtils.newResponse(baseHttpRequest, "HttpTemplate request check fail");
        RouteConfig routeConfig = this.routes.get(baseHttpRequest.getRoute());
        if (routeConfig == null) {
            routeConfig = new RouteConfig(baseHttpRequest.getIp())
                    .setScheme(baseHttpRequest.getScheme())
                    .setPort(baseHttpRequest.getPort())
                    .setConnectionRequestTimeout(5000)
                    .setConnectTimeout(10000)
                    .setSocketTimeout(30000)
                    .setMaxPerRoute(400);
        }
        if (baseHttpRequest.getMethod() == Method.POST) {
            httpPost = buildHttpPost(baseHttpRequest, routeConfig);
        } else if (baseHttpRequest.getMethod() == Method.UPLOAD) {
            httpPost = buildHttpUpload(baseHttpRequest, routeConfig);
        } else {
            httpGet = buildHttpGet(baseHttpRequest, routeConfig);
        }
        try {
            if (httpGet != null) {
                baseHttpResponse = this.httpClient.execute(httpGet, response -> parseResponse(baseHttpRequest, response));
            } else if (httpPost != null) {
                baseHttpResponse = this.httpClient.execute(httpPost, response -> parseResponse(baseHttpRequest, response));
            }

        } catch (IOException e) {
            this.httpTemplateHandler.onFinish(baseHttpRequest, (T)HttpTemplateUtils.newResponse(baseHttpRequest, "exception occur"), e);
            throw e;
        }
        this.httpTemplateHandler.onFinish(baseHttpRequest, (T)baseHttpResponse, null);
        return (T)baseHttpResponse;
    }

    private <T extends BaseHttpResponse> T parseResponse(BaseHttpRequest<T> baseHttpRequest, HttpResponse httpResponse) throws IOException {
        HttpEntity httpEntity = httpResponse.getEntity();
        String body = EntityUtils.toString(httpEntity, "utf-8");
        try {
            BaseHttpResponse baseHttpResponse = JSON.parseObject(body, baseHttpRequest.getResponseClass());
            if (baseHttpResponse == null)
                return (T)HttpTemplateUtils.newResponse(baseHttpRequest, null);
            baseHttpResponse.addHttpInfo(httpResponse.getStatusLine(), httpResponse.getAllHeaders(), body);
            return (T)baseHttpResponse;
        } catch (Exception e) {
            log.error("返回的body为:{}", body);
            return (T)HttpTemplateUtils.newResponse(baseHttpRequest, body);
        }
    }

    private HttpPost buildHttpPost(BaseHttpRequest<?> request, RouteConfig routeConfig) throws HttpTemplateException {
        HttpPost httpPost = new HttpPost(getUri(request, routeConfig));
        Map<String, Object> body = request.getBody();
        if (null != body) {
            StringEntity entity = new StringEntity(JSON.toJSONString(body), "UTF-8");
            httpPost.setEntity(entity);
        }
        setRequestHeader(httpPost, request.getHeaders());
        setTimeout(httpPost, routeConfig);
        return httpPost;
    }

    private HttpPost buildHttpUpload(BaseHttpRequest<?> request, RouteConfig routeConfig) throws HttpTemplateException {
        HttpPost httpPost = new HttpPost(getUri(request, routeConfig));
        Map<String, File> fileItems = request.getFileItems();
        Set<Map.Entry<String, File>> entries = fileItems.entrySet();
        MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
        entries.forEach(s -> entityBuilder.addBinaryBody(s.getKey(), s.getValue()));
        httpPost.setEntity(entityBuilder.build());
        setRequestHeader(httpPost, request.getHeaders());
        setTimeout(httpPost, routeConfig);
        return httpPost;
    }

    private HttpGet buildHttpGet(BaseHttpRequest<?> request, RouteConfig routeConfig) throws HttpTemplateException {
        HttpGet httpGet = new HttpGet(getUri(request, routeConfig));
        setRequestHeader(httpGet, request.getHeaders());
        setTimeout(httpGet, routeConfig);
        return httpGet;
    }

    private URI getUri(BaseHttpRequest<?> request, RouteConfig routeConfig) throws HttpTemplateException {
        URIBuilder uriBuilder = new URIBuilder().setScheme(routeConfig.getScheme()).setHost(routeConfig.getHostname()).setPort(routeConfig.getPort()).setPath(request.getPath());
        Map<String, String> queryParams = request.getQueryParams();
        if (null != queryParams)
            for (Map.Entry<String, String> entry : queryParams.entrySet())
                uriBuilder.setParameter(entry.getKey(), entry.getValue());
        try {
            return uriBuilder.build();
        } catch (URISyntaxException e) {
            throw new HttpTemplateException("请求路径不合法", e);
        }
    }

    private void setRequestHeader(HttpRequestBase httpRequestBase, Map<String, String> header) {
        if (header != null)
            for (Map.Entry<String, String> entry : header.entrySet())
                httpRequestBase.setHeader(entry.getKey(), entry.getValue());
    }

    private void setTimeout(HttpRequestBase httpRequestBase, RouteConfig routeConfig) {
        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(routeConfig.getConnectionRequestTimeout()).setConnectTimeout(routeConfig.getConnectTimeout()).setSocketTimeout(routeConfig.getSocketTimeout()).build();
        httpRequestBase.setConfig(requestConfig);
    }

    private CloseableHttpClient createHttpClient(HttpTemplateConfig httpTemplateConfig) {

        RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.create();
        Registry<ConnectionSocketFactory> registry = registryBuilder
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory()).build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(httpTemplateConfig.getMaxTotal());
        cm.setDefaultMaxPerRoute(httpTemplateConfig.getDefaultMaxPerRoute());
        Map<String, RouteConfig> routes = httpTemplateConfig.getRoutes();
        if (routes != null)
            routes.forEach((name, routeConfig) -> {
                HttpRoute route = HttpTemplateUtils.determineRoute(routeConfig.getHostname(), routeConfig.getPort(), routeConfig.getScheme());
                cm.setMaxPerRoute(route, routeConfig.getMaxPerRoute());
            });
        return HttpClients.custom()
                .setConnectionManager(cm)

                .evictIdleConnections(30, TimeUnit.SECONDS)

                .evictExpiredConnections()

                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .build();
    }

    public CloseableHttpClient getClient() {
        return this.httpClient;
    }
}
package com.alibaba.fetchdata.common.http;


import com.alibaba.fetchdata.common.http.base.BaseHttpRequest;
import com.alibaba.fetchdata.common.http.base.BaseHttpResponse;

public interface HttpTemplateHandler {

    default boolean onStart(BaseHttpRequest<?> baseHttpRequest) {
        return true;
    }

    default <T extends BaseHttpResponse> void onFinish(BaseHttpRequest<T> baseHttpRequest, T baseHttpResponse, Exception e) {}
}
package com.alibaba.fetchdata.common.http.config;

import java.util.HashMap;
import java.util.Map;

public class HttpTemplateConfig {
    private int maxTotal;

    private int defaultMaxPerRoute;

    private Map<String, RouteConfig> routes;

    public HttpTemplateConfig(Map<String, RouteConfig> routes) {
        if (routes == null) {
            this.routes = new HashMap<>(0);
        } else {
            this.routes = routes;
        }
        this.maxTotal = 100;
        this.defaultMaxPerRoute = 100;
    }

    public int getMaxTotal() {
        return this.maxTotal;
    }

    public HttpTemplateConfig setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
        return this;
    }

    public int getDefaultMaxPerRoute() {
        return this.defaultMaxPerRoute;
    }

    public HttpTemplateConfig setDefaultMaxPerRoute(int defaultMaxPerRoute) {
        this.defaultMaxPerRoute = defaultMaxPerRoute;
        return this;
    }

    public Map<String, RouteConfig> getRoutes() {
        return this.routes;
    }

    public HttpTemplateConfig setRoutes(Map<String, RouteConfig> routes) {
        this.routes = routes;
        return this;
    }
}
package com.alibaba.fetchdata.common.http.config;

public class RouteConfig {

    private String hostname;

    private int port;

    private String scheme;

    private int maxPerRoute;

    private int connectionRequestTimeout;

    private int connectTimeout;

    private int socketTimeout;

    public RouteConfig(String hostname) {
        this.hostname = hostname;
        this.port = -1;
        this.scheme = "https";
        this.maxPerRoute = 100;
        this.connectionRequestTimeout = 1000;
        this.connectTimeout = 3000;
        this.socketTimeout = 6000;
    }

    public RouteConfig(String hostname, int port, String scheme) {
        this.hostname = hostname;
        this.port = port;
        this.scheme = scheme;
        this.maxPerRoute = 100;
        this.connectionRequestTimeout = 1000;
        this.connectTimeout = 3000;
        this.socketTimeout = 6000;
    }

    public String getScheme() {
        return this.scheme;
    }

    public RouteConfig setScheme(String scheme) {
        this.scheme = scheme;
        return this;
    }

    public String getHostname() {
        return this.hostname;
    }

    public RouteConfig setHostname(String hostname) {
        this.hostname = hostname;
        return this;
    }

    public int getPort() {
        return this.port;
    }

    public RouteConfig setPort(int port) {
        this.port = port;
        return this;
    }

    public int getMaxPerRoute() {
        return this.maxPerRoute;
    }

    public RouteConfig setMaxPerRoute(int maxPerRoute) {
        this.maxPerRoute = maxPerRoute;
        return this;
    }

    public int getConnectionRequestTimeout() {
        return this.connectionRequestTimeout;
    }

    public RouteConfig setConnectionRequestTimeout(int connectionRequestTimeout) {
        this.connectionRequestTimeout = connectionRequestTimeout;
        return this;
    }

    public int getConnectTimeout() {
        return this.connectTimeout;
    }

    public RouteConfig setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    public int getSocketTimeout() {
        return this.socketTimeout;
    }

    public RouteConfig setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
        return this;
    }
}
package com.alibaba.fetchdata.common.http.base;

import com.alibaba.fetchdata.common.http.common.Method;

import java.io.File;
import java.util.Map;

public abstract class BaseHttpRequest<T extends BaseHttpResponse> {

    public abstract Map<String, String> getQueryParams();

    public abstract Map<String, Object> getBody();

    public abstract Map<String, File> getFileItems();

    public abstract Map<String, String> getHeaders();

    public abstract Map<String, String> getBizMap();

    public abstract String getName();

    public abstract String getRoute();

    public abstract Method getMethod();

    public abstract String getPath();

    public abstract Class<T> getResponseClass();

    public abstract boolean check();

    public String getDomain(){
        return null;
    }

    public String getIp() {
        return null;
    }

    public Integer getPort() {
        return null;
    }

    public String getScheme() {
        return "https";
    }
}
package com.alibaba.fetchdata.common.http.base;

import org.apache.http.Header;
import org.apache.http.StatusLine;

public abstract class BaseHttpResponse {

    private StatusLine statusLine;

    private Header[] headers;

    private String body;

    public abstract boolean success();

    public abstract String code();

    public StatusLine statusLine() {
        return this.statusLine;
    }

    public Header[] headers() {
        return this.headers;
    }

    public String body() {
        return this.body;
    }

    public void addHttpInfo(StatusLine statusLine, Header[] headers, String body) {
        this.statusLine = statusLine;
        this.headers = headers;
        this.body = body;
    }
}
package com.alibaba.fetchdata.common.http.common;

public class Constants {

    public static final String SECURE_SCHEME = "https";

    public static final int DEFAULT_PORT = -1;

    public static final int MAX_TOTAL = 100;

    public static final int DEFAULT_MAX_PER_ROUTE = 100;

    public static final int MAX_PER_ROUTE = 100;

    public static final int CONNECTION_REQUEST_TIMEOUT = 1000;

    public static final int CONNECTION_TIMEOUT = 3000;

    public static final int SOCKET_TIMEOUT = 6000;
}
package com.alibaba.fetchdata.common.http.common;

public class HttpTemplateException extends Exception{

    public HttpTemplateException() {}

    public HttpTemplateException(String message) {
        super(message);
    }

    public HttpTemplateException(String message, Throwable cause) {
        super(message, cause);
    }

    public HttpTemplateException(Throwable cause) {
        super(cause);
    }
}
package com.alibaba.fetchdata.common.http.common;

import com.alibaba.fetchdata.common.http.base.BaseHttpRequest;
import com.alibaba.fetchdata.common.http.base.BaseHttpResponse;
import org.apache.http.HttpHost;
import org.apache.http.conn.routing.HttpRoute;

public class HttpTemplateUtils {

    public static <T extends BaseHttpResponse> T newResponse(BaseHttpRequest<T> baseHttpRequest, String message) {
        if (baseHttpRequest == null)
            throw new IllegalArgumentException("Request is null");
        if (baseHttpRequest.getResponseClass() == null)
            throw new IllegalArgumentException("ResponseClass is null");
        try {
            BaseHttpResponse baseHttpResponse = baseHttpRequest.getResponseClass().newInstance();
            baseHttpResponse.addHttpInfo(null, null, message);
            return (T)baseHttpResponse;
        } catch (Exception e) {
            throw new IllegalArgumentException("ResponseClass can't be instantiated", e);
        }
    }

    public static HttpRoute determineRoute(String hostname, int port, String scheme) {
        int determinePort;
        boolean secure = "https".equalsIgnoreCase(scheme);
        if (port < 0) {
            determinePort = secure ? 443 : 80;
        } else {
            determinePort = port;
        }
        HttpHost httpHost = new HttpHost(hostname, determinePort, scheme);
        return new HttpRoute(httpHost, null, secure);
    }
}
package com.alibaba.fetchdata.common.http.common;
public enum Method {
    GET, POST, UPLOAD;
}

3.项目中使用

1.配置路由:

package com.alibaba.fetchdata.controller.config;

import com.google.common.collect.Maps;
import com.alibaba.fetchdata.common.http.HttpTemplate;
import com.alibaba.fetchdata.common.http.HttpTemplateHandler;
import com.alibaba.fetchdata.common.http.base.BaseHttpRequest;
import com.alibaba.fetchdata.common.http.base.BaseHttpResponse;
import com.alibaba.fetchdata.common.http.config.HttpTemplateConfig;
import com.alibaba.fetchdata.common.http.config.RouteConfig;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * @author dxc
 **/
@Configuration
public class HttpConfig {

    private Logger logger = LoggerFactory.getLogger(HttpConfig.class);

    @Bean
    public HttpTemplateConfig getHttpTemplateConfig() {
        RouteConfig dingTalkRouteConfig = new RouteConfig("oapi.dingtalk.com")
                .setConnectionRequestTimeout(5000)
                .setConnectTimeout(3000)
                .setSocketTimeout(3000)
                .setMaxPerRoute(400);
        Map<String, RouteConfig> routes = Maps.newHashMap();
        routes.put("dingTalk", dingTalkRouteConfig);
        return new HttpTemplateConfig(routes).setMaxTotal(500).setDefaultMaxPerRoute(40);
    }

    @Bean
    public HttpTemplate httpTemplate() {
        return new HttpTemplate(getHttpTemplateConfig(), new HttpTemplateHandler() {
            @Override
            public boolean onStart(BaseHttpRequest<?> baseHttpRequest) {
                return true;
            }

            @Override
            public <T extends BaseHttpResponse> void onFinish(BaseHttpRequest<T> baseHttpRequest, T baseHttpResponse, Exception e) {
            }
        });
    }
}

2.request配置:

package com.alibaba.fetchdata.client.cloudpatrol;

import com.google.common.collect.Maps;
import com.alibaba.fetchdata.common.http.common.Method;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Map;

@Data
public class DingtalkRequest extends BaseCloudPatrolRequest<DingtalkResponse> {

    private String profile;
    private String authorization;

    @Override
    public Map<String, String> getQueryParams() {
        return null;
    }

    @Override
    public Map<String, Object> getBody() {
        Map<String, Object> body = Maps.newHashMap();
        body.put("profile", profile);
        return body;
    }

    @Override
    public Map<String, File> getFileItems() {
        return null;
    }

    @Override
    public Map<String, String> getHeaders() {
        Map<String, String> headers = Maps.newHashMap();
        headers.put("Accept", "application/json");
        headers.put("Content-Type", "application/json");
        headers.put("auth", authorization);
        return headers;
    }

    @Override
    public Map<String, String> getBizMap() {
        return null;
    }

    @Override
    public String getName() {
        return null;
    }

    @Override
    public Method getMethod() {
        return Method.POST;
    }

    @Override
    public String getPath() {
        return "/api/report/getLastSuccessReport";
    }

    @Override
    public Class<LastSuccessReportResponse> getResponseClass() {
        return LastSuccessReportResponse.class;
    }

    @Override
    public boolean check() {
        return StringUtils.isNotBlank(profile) && StringUtils.isNotBlank(authorization);
    }

    @Override
    public String getScheme() {
        return "http";
    }
}
package com.alibaba.fetchdata.client.cloudpatrol;

import com.alibaba.fetchdata.common.http.base.BaseHttpRequest;

public abstract class BaseDingtalkRequest<T extends BaseDingtalkResponse> extends BaseHttpRequest<T> {

    @Override
    public String getRoute() {
        return "dingtalk";
    }
}

3.response配置:

package com.alibaba.fetchdata.client.cloudpatrol;

public class DingtalkResponse extends BaseDingtalkResponse{
}
package com.alibaba.fetchdata.client.cloudpatrol;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fetchdata.common.http.base.BaseHttpResponse;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

@Data
public class BaseDingtalkResponse extends BaseHttpResponse {

    @JSONField(name = "code")
    private Integer code;

    @JSONField(name = "msg")
    private String msg;

    @JSONField(name = "data")
    private JSONObject data;

    @Override
    public boolean success() {
        return code != null  && code == 0 && (StringUtils.isBlank(msg) || ("success").equals(msg));
    }

    @Override
    public String code() {
        return null;
    }
}

4.调用方式:

@Autowired
private HttpTemplate httpTemplate;

public static void main(String[] args) {
       DingtalkRequest request = new DingtalkRequest();
      request.setProfile(profile.getProfile());
      request.setAuthorization("233444");
      DingtalkResponse response = httpTemplate.execute(request);
if (response == null || !response.success()) {
       String errorMsg = response == null ? null : response.getMsg();
       throw new FetchDataException(ErrorCode.UN_KNOW.getCode(), errorMsg);
  }
 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容