All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hecloud.runtime.common.restful.AbstractRestClient Maven / Gradle / Ivy

package com.hecloud.runtime.common.restful;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import com.hecloud.runtime.common.collections.Maps;
import com.hecloud.runtime.common.enums.HttpMethod;
import com.hecloud.runtime.common.enums.PostDataFormat;
import com.hecloud.runtime.common.model.Result;
import lombok.Getter;
import lombok.Setter;
import org.apache.http.*;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.AbstractHttpMessage;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static com.hecloud.runtime.common.utils.Common.*;

/**
 * 通用的HTTP请求客户端 主要有post,get,delete,put,patch,trace,doPost和doGet等几个方法,
 *
 * @author mingwei.LoveinBJ
 */
public abstract class AbstractRestClient {

    private static Logger logger = LoggerFactory.getLogger(AbstractRestClient.class);
    private static SSLConnectionSocketFactory socketFactory = null;
    private static PoolingHttpClientConnectionManager connectionManager = null;
    private static SSLContextBuilder contextBuilder;

    static {
        contextBuilder = new SSLContextBuilder();
        // 全部信任 不做身份鉴定
        try {
            contextBuilder.loadTrustMaterial(null, (x509Certificates, s) -> true);
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException", e);
        } catch (KeyStoreException e) {
            logger.error("KeyStoreException", e);
        }

    }

    /**
     * 默认post请求参数格式
     */
    @Getter
    @Setter
    protected PostDataFormat dataFormat = PostDataFormat.FORM_URLENCODED;
    protected ResultBuilder resultBuilder = new CommonResultBuilder();
    protected Result result = null;
    @Getter
    @Setter
    protected CloseableHttpClient httpClient = null;
    protected CloseableHttpResponse response = null;
    @Getter
    @Setter
    protected RequestConfig config = null;
    protected HttpHost proxy = null;
    protected UrlEncodedFormEntity formEntity = null;
    protected StringEntity stringEntity = null;
    protected HttpPost httpPost = null;
    protected HttpGet httpGet = null;
    protected HttpDelete httpDelete = null;
    protected HttpPut httpPut = null;
    protected HttpPatch httpPatch = null;
    protected HttpTrace httpTrace = null;
    @Getter
    private String[] supportedProtocols = {"TLSv1.2", "SSLv3", "TLSv1", "TLSv1.1"};
    /**
     * 默认超时时间
     */
    @Getter
    private Integer timeout = 1000 * 60;

    public AbstractRestClient(int timeout) {
        super();
        this.timeout = timeout;
        init();
    }

    public AbstractRestClient() {
        super();
        init();
    }

    public AbstractRestClient(String host, Integer port) {
        super();
        this.proxy = new HttpHost(host, port);
        init();
    }

    public AbstractRestClient(String[] supportedProtocols) {
        super();
        setSupportedProtocols(supportedProtocols);
        init();
    }

    /**
     * @param dataFormat 数据格式
     */
    public AbstractRestClient(PostDataFormat dataFormat) {
        this.dataFormat = dataFormat;
        init();
    }

    /**
     * @param timeout    超时时间
     * @param dataFormat 数据格式
     */
    public AbstractRestClient(Integer timeout, PostDataFormat dataFormat) {
        this.timeout = timeout;
        this.dataFormat = dataFormat;
        init();
    }

    /**
     * http的Post方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result post(Map header, Map params, String uri);

    /**
     * @param header 请求头参数
     * @param params 请求参数
     * @param uri    请求路径
     * @return 请求结果
     */
    public abstract Result post(Map header, String params, String uri);

    /**
     * http的PUT方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result put(Map header, Map params, String uri);

    /**
     * http的Delete方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result delete(Map header, Map params, String uri);

    /**
     * http的path方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result patch(Map header, Map params, String uri);

    /**
     * http的path方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result patch(Map header, String params, String uri);

    /**
     * http的trace方法
     *
     * @param header 请求头部消息体
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回{"success":false,"message":"异常信息"}
     */
    public abstract Result trace(Map header, Map params, String uri);

    /**
     * Get方法
     *
     * @param header 请求头部
     * @param params 请求参数
     * @param uri    请求路径
     * @return 返回的response,异常情况时返回null
     */
    public abstract Result get(Map header, Map params, String uri);

    /**
     * 抽象请求方法
     *
     * @param header 请求头部
     * @param param  请求参数
     * @param url    请求路径
     * @param method 请求方法
     * @return 请求结果
     */
    public abstract Map request(Map header, Map param, String url,
                                                HttpMethod method);

    /**
     * 抽象请求方法
     *
     * @param header 请求头部
     * @param param  请求参数
     * @param url    请求路径
     * @param method 请求方法
     * @return 请求结果
     */
    public abstract String request4String(Map header, Map param, String url,
                                          HttpMethod method);

    /**
     * 原始get方法
     *
     * @param uri 请求路径
     * @return 返回结果
     */
    public Result get(String uri) {
        return this.get(null, null, uri);
    }

    /**
     * 原始get对象
     *
     * @param header 请求头部
     * @param params 请求参数
     * @param uri    请求路径
     * @return 请求结果
     */
    public HttpGet rawGet(Map header, Map params, String uri) {
        uri = buildURL(uri, params);
        httpGet = new HttpGet(uri);
        buildHeader(httpGet, header);
        httpGet.setConfig(config);
        return httpGet;
    }

    /**
     * http的doPost方法
     *
     * @param header header参数
     * @param param  请求参数
     * @param url    请求路径
     * @return 返回的response,异常情况时返回空map
     */
    public Map doPost(Map header, Map param, String url) {
        Result result = post(header, param, url);
        return buildResult(result);
    }

    /**
     * doGet方法
     *
     * @param header header参数
     * @param param  请求参数
     * @param url    请求路径
     * @return 返回的response,异常情况时返回空map
     */
    public Map doGet(Map header, Map param, String url) {
        Result result = get(header, param, url);
        return buildResult(result);
    }

    private Map buildResult(Result result) {
        if (result.isSuccess()) {
            return JSONObject.parseObject(result.getMessage(), HashMap.class);
        } else {
            Map responseMap = Maps.single(SUCCESS, false);
            responseMap.put(ERROR, result.getErrorMsg());
            return responseMap;
        }
    }

    /**
     * 构建请求路径
     *
     * @param uri    请求路径
     * @param params 请求参数
     * @return 请求路径
     */
    public String buildURL(String uri, Map params) {
        final Map map = Optional.ofNullable(params).orElse(new HashMap<>(0));
        List parameters = new ArrayList();
        params.keySet().stream().filter(key -> null != map.get(key))
                .forEach(key -> parameters.add(new BasicNameValuePair(key, map.get(key).toString())));
        if (uri.endsWith(QUEST)) {
            return uri + "&" + URLEncodedUtils.format(parameters, "UTF-8");
        } else {
            return uri + QUEST + URLEncodedUtils.format(parameters, "UTF-8");
        }
    }

    protected void handleResponse() throws UnsupportedOperationException, IOException {
        int status = response.getStatusLine().getStatusCode();
        result = resultBuilder.build(status);
        if (null != response.getEntity()) {
            result.setMessage(CharStreams.toString(new InputStreamReader(response.getEntity().getContent(), Charsets.UTF_8)));
        }
    }

    /**
     * 构建请求实体
     *
     * @param request 请求对象
     * @param params  请求参数
     */
    public void buildEntity(HttpEntityEnclosingRequest request, Object params) {
        switch (dataFormat) {
            case RAW:
                buildRawEntity(params);
                request.setEntity(stringEntity);
                break;
            case FORM_URLENCODED:
                buildFormEntity(params);
                request.setEntity(formEntity);
                break;
            default:
                buildFormEntity(params);
                request.setEntity(formEntity);
                break;
        }
    }

    private void buildRawEntity(Object params) {
        if (params instanceof List) {
            buildRawEntity((List) params);
        } else if (params instanceof Map) {
            buildRawEntity((Map) params);
        } else if (params instanceof String) {
            buildStringEntity(params);
        }
    }

    private void buildFormEntity(Object params) {
        if (params instanceof List) {
            buildFormEntity((List) params);
        } else if (params instanceof Map) {
            buildFormEntity((Map) params);
        } else if (params instanceof String) {
            buildStringEntity(params);
        }
    }

    private void buildFormEntity(Map params) {
        params = Optional.ofNullable(params).orElse(new HashMap<>(1));
        List parameters = new ArrayList();
        for (Map.Entry entry : params.entrySet()) {
            parameters.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
        }
        try {
            formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.error("RestClient UnsupportedEncodingException:", e);
        }
    }

    private void buildFormEntity(List params) {
        params = Optional.ofNullable(params).orElse(new ArrayList<>(1));
        List parameters = new ArrayList<>(1);
        for (ParamEntry entry : params) {
            parameters.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
        }
        try {
            formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.error("RestClient UnsupportedEncodingException:", e);
        }
    }

    private void buildRawEntity(Map params) {
        params = Optional.ofNullable(params).orElse(new HashMap<>(0));
        buildStringEntity(params);
    }

    private void buildRawEntity(List params) {
        params = Optional.ofNullable(params).orElse(new ArrayList<>());
        buildStringEntity(params);
    }

    private void buildStringEntity(Object params) {
        try {
            switch (dataFormat) {
                case RAW:
                    stringEntity = new StringEntity(JSONObject.toJSONString(params), ContentType.APPLICATION_JSON);
                    break;
                default:
                    stringEntity = new StringEntity(JSONObject.toJSONString(params));
                    break;
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("RestClient UnsupportedEncodingException:", e);
        }
    }

    /**
     * 构建头部
     *
     * @param httpMessage 消息
     * @param header      头部对象
     */
    public void buildHeader(AbstractHttpMessage httpMessage, Map header) {
        header = Optional.ofNullable(header).orElse(new HashMap<>(0));
        header.entrySet().forEach(entry -> httpMessage.setHeader(new BasicHeader(entry.getKey(), String.valueOf(entry.getValue()))));
    }

    /**
     * 关闭HTTP请求
     */
    public void close() {
        try {
            if (null != response) {
                response.close();
                response = null;
            }
            if (null != httpClient) {
                httpClient.close();
            }
        } catch (IOException e) {
            logger.error("RestClient Get Finally Exception:", e);
        }
    }

    /**
     * 处理头部
     *
     * @param request HTTP请求
     */
    public void processWithHeaders(HttpRequestBase request) {
        try {
            response = httpClient.execute(httpPost);
            Header[] header = response.getAllHeaders();
            String responseHeaders = JSONObject.toJSONString(header);
            HttpEntity entity = response.getEntity();
            String content = CharStreams.toString(new InputStreamReader(entity.getContent(), Charsets.UTF_8));
            int status = response.getStatusLine().getStatusCode();
            result = resultBuilder.build(status);
            if (result.isSuccess()) {
                Map data = Maps.single("headers", responseHeaders);
                data.put("body", content);
                result.setMessage(JSONObject.toJSONString(data));
            } else {
                logger.warn(content);
            }
        } catch (IOException e) {
            logger.error("RestClient Exception:", e);
            result = new Result(false, e.getMessage(), e.getMessage());
        } finally {
            close();
        }

    }

    protected void init() {
        this.config = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).setProxy(proxy)
                .setCookieSpec(CookieSpecs.STANDARD_STRICT).build();
        try {
            socketFactory = new SSLConnectionSocketFactory(contextBuilder.build(), this.supportedProtocols, null,
                    NoopHostnameVerifier.INSTANCE);
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException", e);
        } catch (KeyManagementException e) {
            logger.error("KeyManagementException", e);
        }

        Registry socketFactoryRegistry = RegistryBuilder.create()
                .register(HTTP, PlainConnectionSocketFactory.INSTANCE).register(HTTPS, socketFactory).build();
        connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setMaxTotal(200);
        this.httpClient = HttpClients.custom().setConnectionManager(connectionManager).setConnectionManagerShared(true)
                .setDefaultRequestConfig(config).build();
    }

    /**
     * @param timeout the timeout to set
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
        config = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
    }

    /**
     * @param supportedProtocols the supportedProtocols to set
     */
    public void setSupportedProtocols(String[] supportedProtocols) {
        Optional.ofNullable(supportedProtocols).ifPresent(protocols -> this.supportedProtocols = protocols);
        init();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy