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

top.jfunc.common.http.base.AbstractNativeHttpTemplate Maven / Gradle / Ivy

Go to download

http客户端请求工具类,有多种实现:OkHttp3、ApacheHttpClient、HttpURLConnection、Jodd-Http,可以随意切换http实现

There is a newer version: 1.2.12
Show newest version
package top.jfunc.common.http.base;

import top.jfunc.common.http.HttpConstants;
import top.jfunc.common.http.HttpStatus;
import top.jfunc.common.http.Method;
import top.jfunc.common.http.base.ssl.DefaultTrustManager;
import top.jfunc.common.http.base.ssl.SSLSocketFactoryBuilder;
import top.jfunc.common.http.base.ssl.TrustAnyHostnameVerifier;
import top.jfunc.common.utils.ArrayListMultimap;
import top.jfunc.common.utils.IoUtil;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.util.HashMap;
import java.util.Set;

/**
 * 使用URLConnection实现的Http公共父类
 * @author 熊诗言2018/6/6
 */
public abstract class AbstractNativeHttpTemplate extends AbstractConfigurableHttp implements HttpTemplate {
    @Override
    public  R template(String url, Method method, String contentType, ContentCallback contentCallback, ArrayListMultimap headers, Integer connectTimeout, Integer readTimeout, String resultCharset , boolean includeHeaders , ResultCallback resultCallback) throws IOException {
        //默认的https校验
        // 后面会处理的,这里就不需要了 initDefaultSSL(sslVer);

        HttpURLConnection connect = null;
        InputStream inputStream = null;
        try {
            //1.获取连接
            String completedUrl = addBaseUrlIfNecessary(url);
            connect = (HttpURLConnection)new java.net.URL(completedUrl).openConnection();

            //2.处理header
            setConnectProperty(connect, method, contentType,
                    mergeDefaultHeaders(headers),
                    getConnectionTimeoutWithDefault(connectTimeout),
                    getReadTimeoutWithDefault(readTimeout));

            ////////////////////////////////////ssl处理///////////////////////////////////
            if(connect instanceof HttpsURLConnection){
                //默认设置这些
                HttpsURLConnection con = (HttpsURLConnection)connect;
                initSSL(con , getHostnameVerifier() , getSSLSocketFactory());
            }
            ////////////////////////////////////ssl处理///////////////////////////////////

            //3.留给子类复写的机会:给connection设置更多参数
            doWithConnection(connect);

            //5.写入内容,只对post有效
            if(contentCallback != null && method.hasContent()){
                contentCallback.doWriteWith(connect);
            }

            //4.连接
            connect.connect();

            //6.获取返回值
            int statusCode = connect.getResponseCode();
            ///保留起非200抛异常的方式
//            if( HttpStatus.HTTP_OK == statusCode){
//                //6.1获取body
//                /*InputStream is = connect.getInputStream();
//                byte[] result = IoUtil.stream2Bytes(is);
//                is.close();
//
//                String s = new String(result, resultCharset);*/
//
//                //6.2获取header
//
//                inputStream = connect.getInputStream();
//
//                return resultCallback.convert(inputStream, resultCharset, includeHeaders ? connect.getHeaderFields() : new HashMap<>(0));
//
//            } else{
//                String err = errMessage(connect);
//                throw new HttpException(statusCode,err,connect.getHeaderFields());
//            }

            inputStream = getStreamFrom(connect , statusCode , false);

            return resultCallback.convert(statusCode , inputStream, getResultCharsetWithDefault(resultCharset), includeHeaders ? connect.getHeaderFields() : new HashMap<>(0));
        } catch (IOException e) {
            throw e;
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            //关闭顺序不能改变,否则服务端可能出现这个异常  严重: java.io.IOException: 远程主机强迫关闭了一个现有的连接
            //1 . 关闭连接
            disconnectQuietly(connect);
            //2 . 关闭流
            IoUtil.close(inputStream);
        }
    }

    protected InputStream getStreamFrom(HttpURLConnection connect , int statusCode , boolean ignoreResponseBody) throws IOException{
        //忽略返回body的情况下,直接返回空的
        if(ignoreResponseBody){
            return top.jfunc.common.http.IoUtil.emptyInputStream();
        }

        InputStream inputStream;
        if(HttpStatus.HTTP_OK == statusCode){
            inputStream = connect.getInputStream();
        }else {
            inputStream = connect.getErrorStream();
        }
        if(null == inputStream){
            inputStream = top.jfunc.common.http.IoUtil.emptyInputStream();
        }
        return inputStream;
    }

    /**子类复写需要首先调用此方法,保证http的功能*/
    protected void doWithConnection(HttpURLConnection connect) throws IOException{
        //default do nothing, give children a chance to do more config
    }

    /**
     * @see SSLSocketFactoryBuilder#build()
     * @see SSLSocketFactoryBuilder#build(String, String)
     */
    protected void initSSL(HttpsURLConnection con , HostnameVerifier hostnameVerifier , SSLSocketFactory sslSocketFactory) {
        // 验证域
        if(null != hostnameVerifier){
            con.setHostnameVerifier(hostnameVerifier);
        }
        if(null != sslSocketFactory){
            con.setSSLSocketFactory(sslSocketFactory);
        }
    }

    protected void setConnectProperty(HttpURLConnection connect, Method method, String contentType, ArrayListMultimap headers, int connectTimeout, int readTimeout) throws ProtocolException {
        connect.setRequestMethod(method.name());
        connect.setDoOutput(true);
        connect.setUseCaches(false);
        setRequestHeaders(connect , contentType , headers);
        connect.setConnectTimeout(connectTimeout);
        connect.setReadTimeout(readTimeout);
    }

    protected void setRequestHeaders(HttpURLConnection connection, String contentType, ArrayListMultimap headers) {
        if(null != headers) {
            Set keySet = headers.keySet();
            keySet.forEach((k)->headers.get(k).forEach((v)->connection.addRequestProperty(k,v)));
        }
        if(null != contentType){
            connection.setRequestProperty(top.jfunc.common.http.Header.CONTENT_TYPE.toString(), contentType);
        }
    }

    protected void writeContent(HttpURLConnection connect, String data, String bodyCharset) throws IOException {
        if (null == data || null == bodyCharset) {
            return;
        }
        OutputStream outputStream = connect.getOutputStream();
        outputStream.write(data.getBytes(bodyCharset));
        outputStream.close();
        /* PrintWriter out = new PrintWriter(connect.getOutputStream());
        if (null != data) {
            out.print(data);
            out.flush();
        }
        out.close();*/
    }

    /**
     * 获取输出流中的错误信息,针对HttpURLConnection
     * @param connect HttpURLConnection
     * @return 错误信息
     * @see HttpURLConnection
     * @throws IOException IO异常
     */
    protected String errMessage(HttpURLConnection connect) throws IOException {
        //如果服务器返回的HTTP状态不是HTTP_OK,则表示发生了错误,此时可以通过如下方法了解错误原因。
        // 通过getErrorStream了解错误的详情
        InputStream is = connect.getErrorStream();
        if(null==is){return "";}
        InputStreamReader isr = new InputStreamReader(is, HttpConstants.DEFAULT_CHARSET);
        BufferedReader in = new BufferedReader(isr);
        String inputLine;
        StringWriter bw = new StringWriter();
        while ((inputLine = in.readLine()) != null)
        {
            bw.write(inputLine);
            bw.write("\n");
        }
        bw.close();
        in.close();

        //disconnectQuietly(connect);

        return bw.getBuffer().toString();
    }

    public static void disconnectQuietly(HttpURLConnection connect) {
        if(null != connect){
            try {
                connect.disconnect();
            } catch (Exception e) {}
        }
    }

    protected void initDefaultSSL(String sslVer) {
        try {
            TrustManager[] tmCerts = new TrustManager[1];
            tmCerts[0] = new DefaultTrustManager();
            SSLContext sslContext = SSLContext.getInstance(sslVer);
            sslContext.init(null, tmCerts, null);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

            HostnameVerifier hostnameVerifier = new TrustAnyHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
        } catch (Exception e) {
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy