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

cn.xishan.oftenporter.bridge.http.HttpUtil Maven / Gradle / Ivy

Go to download

转接远程的http接口,服务器响应正确的数据格式必须是JResponse定义的格式。 客户端websocket使用"org.java-websocket:Java-WebSocket:1.5.2",项目地址https://github.com/TooTallNate/Java-WebSocket; 对Java-WebSocket做了适当修改。

The newest version!
package cn.xishan.oftenporter.bridge.http;


import cn.xishan.oftenporter.porter.core.JResponse;
import cn.xishan.oftenporter.porter.core.ResultCode;
import cn.xishan.oftenporter.porter.core.annotation.MayNull;
import cn.xishan.oftenporter.porter.core.annotation.NotNull;
import cn.xishan.oftenporter.porter.core.base.*;
import cn.xishan.oftenporter.porter.core.exception.OftenCallException;
import cn.xishan.oftenporter.porter.core.util.OftenTool;
import cn.xishan.oftenporter.porter.core.util.ResourceUtil;
import cn.xishan.oftenporter.servlet.ContentType;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import okio.BufferedSink;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Created by 宇宙之灵 on 2015/9/12.
 */
public class HttpUtil {

    public interface OnBuilding {
        void onBuild(OkHttpClient.Builder builder);
    }

    public static class TimeoutKey implements Cloneable {
        private long connTimeout = -1;
        private long writeTimeout = -1;
        private long readTimeout = -1;
        private long callTimeout = -1;

        public TimeoutKey() {
        }

        public TimeoutKey(long connTimeout, long writeTimeout, long readTimeout) {
            this.connTimeout = connTimeout;
            this.writeTimeout = writeTimeout;
            this.readTimeout = readTimeout;
        }

        @Override
        public TimeoutKey clone() {
            try {
                TimeoutKey timeoutKey = (TimeoutKey) super.clone();
                return timeoutKey;
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public int hashCode() {
            return (int) (connTimeout + writeTimeout + readTimeout + callTimeout);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof TimeoutKey) {
                TimeoutKey timeoutKey = (TimeoutKey) obj;
                return this.connTimeout == timeoutKey.connTimeout && this.writeTimeout == timeoutKey.writeTimeout &&
                        this.readTimeout == timeoutKey.readTimeout && this.callTimeout == timeoutKey.callTimeout;
            } else {
                return false;
            }
        }

        public long getConnTimeout() {
            return connTimeout;
        }

        public void setConnTimeout(long connTimeout) {
            this.connTimeout = connTimeout;
        }

        public void setConnTimeout(long connTimeout, TimeUnit timeUnit) {
            this.setConnTimeout(timeUnit.toMillis(connTimeout));
        }

        public long getWriteTimeout() {
            return writeTimeout;
        }

        public void setWriteTimeout(long writeTimeout) {
            this.writeTimeout = writeTimeout;
        }

        public void setWriteTimeout(long writeTimeout, TimeUnit timeUnit) {
            this.setWriteTimeout(timeUnit.toMillis(writeTimeout));
        }

        public long getReadTimeout() {
            return readTimeout;
        }

        public void setReadTimeout(long readTimeout) {
            this.readTimeout = readTimeout;
        }

        public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
            this.setReadTimeout(timeUnit.toMillis(readTimeout));
        }

        public long getCallTimeout() {
            return callTimeout;
        }

        public void setCallTimeout(long callTimeout) {
            this.callTimeout = callTimeout;
        }

        public void setCallTimeout(long callTimeout, TimeUnit timeUnit) {
            this.setCallTimeout(timeUnit.toMillis(callTimeout));
        }
    }

    private static final TimeoutKey DEFAULT_TIMEOUT_KEY = new TimeoutKey(30 * 1000, 60 * 1000, 60 * 1000);

    private static final X509TrustManager X509_TRUST_MANAGER = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates,
                String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates,
                String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    };

    static class StreamBody extends RequestBody {

        private MediaType mediaType;
        private InputStream inputStream;

        public StreamBody(MediaType mediaType, InputStream inputStream) {
            this.mediaType = mediaType;
            this.inputStream = inputStream;
        }

        @Override
        public MediaType contentType() {
            return mediaType;
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            try (InputStream in = this.inputStream) {
                byte[] buf = new byte[2048];
                int n;
                while ((n = in.read(buf)) != -1) {
                    sink.write(buf, 0, n);
                }
            } finally {
                this.inputStream = null;
            }
        }
    }


    private static OkHttpClient _getClient(SSLSocketFactory sslSocketFactory, X509TrustManager x509TrustManager,
            boolean hasCookie, TimeoutKey timeoutKey, OnBuilding building) {

        try {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            if (x509TrustManager == null) {
                x509TrustManager = X509_TRUST_MANAGER;
            }

            if (sslSocketFactory == null) {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
                sslSocketFactory = sslContext.getSocketFactory();
            }
            builder.sslSocketFactory(sslSocketFactory, x509TrustManager);
            if (timeoutKey.connTimeout != -1) {
                builder.connectTimeout(timeoutKey.connTimeout, TimeUnit.MILLISECONDS);
            }
            if (timeoutKey.readTimeout != -1) {
                builder.readTimeout(timeoutKey.readTimeout, TimeUnit.MILLISECONDS);
            }
            if (timeoutKey.writeTimeout != -1) {
                builder.writeTimeout(timeoutKey.writeTimeout, TimeUnit.MILLISECONDS);
            }
            if (timeoutKey.callTimeout != -1) {
                builder.callTimeout(timeoutKey.callTimeout, TimeUnit.MILLISECONDS);
            }

            if (hasCookie) {
                builder.cookieJar(new CookieJar() {
                    private final Map> cookieStore = new ConcurrentHashMap<>();

                    @Override
                    public void saveFromResponse(HttpUrl url, List cookies) {
                        cookieStore.put(url, cookies);
                    }

                    @Override
                    public List loadForRequest(HttpUrl url) {
                        List cookies = cookieStore.get(url);
                        return cookies != null ? cookies : Collections.emptyList();
                    }
                });
            } else {
                builder.cookieJar(CookieJar.NO_COOKIES);
            }

            if (x509TrustManager == X509_TRUST_MANAGER) {
                builder.hostnameVerifier((s, sslSession) -> true);
            }

            if (building != null) {
                building.onBuild(builder);
            }

            OkHttpClient okHttpClient = builder.build();

            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 忽略证书验证。
     *
     * @return
     */
    public static synchronized OkHttpClient getClient() {
        return getClient(null, null, false);
    }

    /**
     * 忽略证书验证。
     *
     * @return
     */
    public static synchronized OkHttpClient getClient(TimeoutKey timeoutKey) {
        return getClient(null, null, false, timeoutKey);
    }

    /**
     * 可以设置双向认证。
     *
     * @return
     */
    public static synchronized OkHttpClient getClient(SSLSocketFactory sslSocketFactory,
            X509TrustManager x509TrustManager, boolean hasCookie) {
        return getClient(sslSocketFactory, x509TrustManager, hasCookie, DEFAULT_TIMEOUT_KEY);
    }


    /**
     * 可以设置双向认证。
     *
     * @return
     */
    public static synchronized OkHttpClient getClient(SSLSocketFactory sslSocketFactory,
            X509TrustManager x509TrustManager, boolean hasCookie, TimeoutKey timeoutKey) {
        return getClient(sslSocketFactory, x509TrustManager, hasCookie, timeoutKey, null);
    }

    /**
     * 可以设置双向认证。
     *
     * @return
     */
    public static synchronized OkHttpClient getClient(SSLSocketFactory sslSocketFactory,
            X509TrustManager x509TrustManager, boolean hasCookie, TimeoutKey timeoutKey, OnBuilding building) {
        return _getClient(sslSocketFactory, x509TrustManager, hasCookie, timeoutKey, building);
    }


    /**
     * 移除末尾指定的字符(若存在的话)。
     *
     * @param sb
     * @param c  要移除的字符
     */
    private static void removeEndChar(StringBuilder sb, char c) {
        if (sb.length() > 0 && sb.charAt(sb.length() - 1) == c) {
            sb.deleteCharAt(sb.length() - 1);
        }
    }

    /**
     * 添加地址参数
     *
     * @param url        地址
     * @param nameValues 如name=123&age=12
     * @param afterSharp 是否放在#后面
     */
    public static String addUrlParam(String url, String nameValues, boolean afterSharp) {
        int index = url.lastIndexOf(afterSharp ? "#" : "?");
        if (index == -1) {
            return url + (afterSharp ? "#" : "?") + nameValues;
        } else {
            return url + "&" + nameValues;
        }
    }

    private static void addUrlParams(StringBuilder stringBuilder, InNames.Name[] names,
            Object[] values, String encoding) throws UnsupportedEncodingException {
        if (names == null || values == null) {
            return;
        }
        for (int i = 0; i < names.length; i++) {
            if (values[i] != null) {
                stringBuilder.append(URLEncoder.encode(names[i].varName, encoding)).append("=")
                        .append(URLEncoder.encode(values[i] + "", encoding)).append('&');
            }
        }
    }

    private static String dealUrlParams(OftenObject oftenObject, String url) throws UnsupportedEncodingException {
        if (oftenObject == null || (oftenObject._fInNames == null && oftenObject._cInNames == null)) {
            return url;
        }
        StringBuilder stringBuilder = new StringBuilder();
        String encoding = "utf-8";

        if (oftenObject._fInNames != null) {
            addUrlParams(stringBuilder, oftenObject._fInNames.nece, oftenObject._fn, encoding);
            addUrlParams(stringBuilder, oftenObject._fInNames.unece, oftenObject._fu, encoding);
        }
        if (oftenObject._cInNames != null) {
            addUrlParams(stringBuilder, oftenObject._cInNames.nece, oftenObject._cn, encoding);
            addUrlParams(stringBuilder, oftenObject._cInNames.unece, oftenObject._cu, encoding);
        }

        if (stringBuilder.length() > 0) {
            removeEndChar(stringBuilder, '&');
            if (url.indexOf('?') == -1) {
                url += "?" + stringBuilder;
            } else {
                url += "&" + stringBuilder;
            }
        }
        return url;
    }


    private static void addFormParams(FormBody.Builder builder, InNames.Name[] names, Object[] values) {
        if (names == null || values == null) {
            return;
        }
        for (int i = 0; i < names.length; i++) {
            if (values[i] != null) {
                builder.add(names[i].varName, String.valueOf(values[i]));
            }
        }
    }

    private static RequestBody dealBodyParams(OftenObject oftenObject, RequestData requestData) {

        RequestBody body;

        if (requestData != null) {
            MediaType mediaType = null;
            if (requestData.getContentType() != null) {
                if (requestData.getEncoding() != null) {
                    mediaType = MediaType.parse(requestData.getContentType().getType() + ";charset=" + requestData
                            .getEncoding());
                } else {
                    mediaType = MediaType.parse(requestData.getContentType().getType());
                }
            }

            if (requestData.getBodyContent() != null) {
                Object content = requestData.getBodyContent();


                if (content instanceof byte[]) {
                    byte[] bs = (byte[]) content;
                    body = RequestBody.create(mediaType, bs);
                } else if (content instanceof InputStream) {
                    body = new StreamBody(mediaType, (InputStream) content);
                } else if (content instanceof File) {
                    File file = (File) content;
                    body = RequestBody.create(mediaType, file);
                } else {
                    String strContent = String.valueOf(content);
                    body = RequestBody.create(mediaType, strContent);
                }

            } else if (requestData.getContentType() == ContentType.MULTIPART_FORM) {
                MultipartBody.Builder builder = new MultipartBody.Builder();
                builder.setType(mediaType);
                Map params = requestData.getParams();
                if (params != null) {
                    for (Map.Entry entry : params.entrySet()) {
                        String name = entry.getKey();
                        Object value = entry.getValue();
                        if (value == null) {
                            continue;
                        }
                        if (value instanceof File) {
                            File file = (File) value;
                            RequestBody fileBody = RequestBody
                                    .create(MediaType.parse(ResourceUtil.getMimeType(file.getName())), file);
                            builder.addFormDataPart(name, file.getName(), fileBody);
                        } else {
                            builder.addFormDataPart(name, String.valueOf(value));
                        }
                    }
                }
                body = builder.build();
            } else if (requestData.getContentType() == ContentType.APP_FORM_URLENCODED) {
                FormBody.Builder builder = new FormBody.Builder(mediaType.charset());
                Map params = requestData.getParams();
                if (params != null) {
                    for (Map.Entry entry : params.entrySet()) {
                        String name = entry.getKey();
                        Object value = entry.getValue();
                        if (value == null) {
                            continue;
                        } else {
                            builder.add(name, String.valueOf(value));
                        }

                    }
                }
                body = builder.build();
            } else {
                JSONObject jsonObject = new JSONObject();

                Map params = requestData.getParams();
                if (params != null) {
                    jsonObject.putAll(params);
                }

                body = RequestBody.create(mediaType, jsonObject.toString());
            }
        } else {
            FormBody.Builder builder = new FormBody.Builder(Charset.forName("utf-8"));
            if (oftenObject != null) {
                if (oftenObject._fInNames != null) {
                    addFormParams(builder, oftenObject._fInNames.nece, oftenObject._fn);
                    addFormParams(builder, oftenObject._fInNames.unece, oftenObject._fu);
                }
                if (oftenObject._cInNames != null) {
                    addFormParams(builder, oftenObject._cInNames.nece, oftenObject._cn);
                    addFormParams(builder, oftenObject._cInNames.unece, oftenObject._cu);
                }
            }

            body = builder.build();
        }

        return body;
    }


    /**
     * 把请求进行转发。
     *
     * @param requestData
     * @param method
     * @param okHttpClient
     * @param url
     * @param callback     为null表示同步,则返回response;否则表示异步,返回的response为null。
     * @return
     * @throws IOException
     */
    public static Response request(@NotNull RequestData requestData, PortMethod method,
            @MayNull OkHttpClient okHttpClient,
            String url, Callback callback) throws IOException {
        return request(requestData == null ? null : new OftenObjectImpl(method, requestData), method, okHttpClient, url,
                callback);
    }

    /**
     * 把请求进行转发。
     *
     * @param oftenObject  可以为null
     * @param method
     * @param okHttpClient
     * @param url
     * @param callback     为null表示同步,则返回response;否则表示异步,返回的response为null。
     * @return
     * @throws IOException
     */
    public static Response request(@MayNull OftenObject oftenObject, PortMethod method,
            @MayNull OkHttpClient okHttpClient, String url, Callback callback) throws IOException {
        if (okHttpClient == null) {
            okHttpClient = getClient(null, null, false);
        }
        Response response = null;
        try {
            RequestData requestData = null;
            Request.Builder builder = new Request.Builder();
            if (oftenObject instanceof OftenObjectImpl) {
                requestData = ((OftenObjectImpl) oftenObject).getRequestData();
                Map headers = requestData.getHeaders();
                if (OftenTool.notEmptyOf(headers)) {
                    for (Map.Entry entry : headers.entrySet()) {
                        builder.addHeader(entry.getKey(), entry.getValue());
                    }
                }
            }
            Request request;
            if (method == null) {
                method = PortMethod.GET;
            }
            switch (method) {
                case PUT: {
                    RequestBody requestBody = dealBodyParams(oftenObject, requestData);
                    request = builder.url(url).put(requestBody).build();
                }
                break;
                case POST: {
                    RequestBody requestBody = dealBodyParams(oftenObject, requestData);
                    request = builder.url(url).post(requestBody).build();
                }
                break;
                case GET: {
                    url = dealUrlParams(oftenObject, url);
                    request = builder.url(url).get().build();
                }

                break;
                case DELETE: {
                    url = dealUrlParams(oftenObject, url);
                    request = builder.url(url).delete().build();
                }
                break;
                default:
                    throw new RuntimeException("not support:" + method);
            }
            if (callback == null) {
                response = okHttpClient.newCall(request).execute();
            } else {
                okHttpClient.newCall(request).enqueue(callback);
            }
        } catch (IOException e) {
            throw e;
        }

        return response;
    }

    public static JResponse requestJResponse(@MayNull RequestData requestData, PortMethod method,
            @MayNull OkHttpClient okHttpClient, String url, JRCallback jrCallback) {
        return requestJResponse(requestData == null ? null : new OftenObjectImpl(method, requestData), method,
                okHttpClient,
                url,
                jrCallback);
    }

    public static String requestString(@MayNull RequestData requestData, PortMethod method,
            @MayNull OkHttpClient okHttpClient, String url) {
        ResponseBody responseBody = null;
        Response response = null;
        try {
            response = request(requestData, method, okHttpClient, url, null);
            int code = response.code();
            if (code == 200 || code == 201) {
                responseBody = response.body();
                return responseBody.string();
            } else if (code == 204) {
                return null;
            } else {
                throw new OftenCallException("errcode=" + code + ",msg=" + response.message());
            }
        } catch (OftenCallException e) {
            throw e;
        } catch (Throwable e) {
            throw new OftenCallException(e);
        } finally {
            OftenTool.close(responseBody);
            OftenTool.close(response);
        }
    }

    public static byte[] requestBytes(@MayNull RequestData requestData, PortMethod method,
            @MayNull OkHttpClient okHttpClient, String url) {
        ResponseBody responseBody = null;
        Response response = null;
        try {
            response = request(requestData, method, okHttpClient, url, null);
            int code = response.code();
            if (code == 200 || code == 201) {
                responseBody = response.body();
                return responseBody.bytes();
            } else if (code == 204) {
                return null;
            } else {
                throw new OftenCallException("errcode=" + code + ",msg=" + response.message());
            }
        } catch (OftenCallException e) {
            throw e;
        } catch (Throwable e) {
            throw new OftenCallException(e);
        } finally {
            OftenTool.close(responseBody);
            OftenTool.close(response);
        }
    }

    private static JResponse toJResponse(Response response) {
        JResponse jResponse;
        ResponseBody responseBody = null;
        try {
            int code = response.code();
            if (code == 200 || code == 201) {
                responseBody = response.body();
                String json = responseBody.string();
                jResponse = JResponse.fromJSON(json);
            } else if (code == 204) {
                jResponse = new JResponse(ResultCode.SUCCESS);
            } else {
                jResponse = new JResponse(code);
                jResponse.setDescription(response.message());
            }
        } catch (IOException e) {
            jResponse = onIOException(e);
        } catch (JResponse.JResponseFormatException e) {
            jResponse = new JResponse();
            jResponse.setCode(ResultCode.PARAM_DEAL_EXCEPTION);
            jResponse.setDescription(e.toString());
            jResponse.setExCause(e);
        } finally {
            OftenTool.close(responseBody);
            OftenTool.close(response);
        }
        return jResponse;
    }

    /**
     * 把数据发向服务器,并接受响应结果。(同步的)
     *
     * @param oftenObject  可以为null
     * @param method       像服务器发起的请求方法
     * @param okHttpClient
     * @param url          url地址
     * @param jrCallback
     * @return
     */
    public static JResponse requestJResponse(@MayNull OftenObject oftenObject, PortMethod method,
            @MayNull OkHttpClient okHttpClient, String url, final JRCallback jrCallback) {
        JResponse jResponse = null;
        try {

            if (jrCallback == null) {
                Response response = request(oftenObject, method, okHttpClient, url, null);
                jResponse = toJResponse(response);
            } else {
                request(oftenObject, method, okHttpClient, url, new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        jrCallback.onResult(onIOException(e));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        jrCallback.onResult(toJResponse(response));
                    }

                });
            }
        } catch (IOException e) {
            jResponse = onIOException(e);
            if (jrCallback != null) {
                jrCallback.onResult(jResponse);
            }
        }
        return jResponse;
    }

    private static JResponse onIOException(IOException e) {
        JResponse jResponse = new JResponse();
        jResponse.setCode(ResultCode.NET_EXCEPTION);
        jResponse.setDescription(e.toString());
        jResponse.setExCause(e);
        return jResponse;
    }


}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy