• 发送http请求总结


    最近在使用Apache的httpclient的时候,maven引用了最新版本4.3,发现Idea提示DefaultHttpClient等常用的类已经不推荐使用了,之前在使用4.2.3版本的时候,还没有被deprecated。去看了下官方文档,确实不推荐使用了:
    DefaultHttpClient —> CloseableHttpClient
    HttpResponse —> CloseableHttpResponse

    详细链接:http://www.httpclient.cn/archives/96.html

    这个说的也不错:https://www.jianshu.com/p/375be5929bed

    使用httpclient发送get请求(完整样例):

       public BestpayResult<String> doGetService(String Url, String param){
            //首先需要先创建一个DefaultHttpClient的实例
            HttpGet httpGet=null;
            try {
                //获得当前客户端对象, 用这种过时的方法创建客户端对象,只能用httpGet.abort();来关闭了,否则closeableHttpClient.close()来关闭
                HttpClient httpClient = new DefaultHttpClient();
                //备注:HttpClient httpClient = new DefaultHttpClient();已经过时了,new DefaultHttpClient();可以替换为HttpClients.createDefault();
                //HttpClients.createDefault()实现的实际就是HttpClientBuilder.create().build();
                //所以HttpClient httpClient =HttpClientBuilder.create().build();也是可以的
    
                //先创建一个HttpGet对象,传入目标的网络地址,然后调用HttpClient的execute()方法即可:
                //根据地址获取请求
                httpGet = new HttpGet(new StringBuilder(Url).append("?").append(param).toString());
                //通过请求对象,获取响应对象
                HttpResponse response = httpClient.execute(httpGet);
                //通过HttpResponse 的getEntity()方法获取返回信息
                //下面这个可以获得状态码
                int code=response.getStatusLine().getStatusCode();
                if(code!=200){
                    return new BestpayResult<>(String.valueOf(code),"调用HttpGet请求失败");
                }
                //获得返回的信息
                HttpEntity entity = response.getEntity();
                //防止空指针异常
                if (entity != null) {
                    //下面是读取返回信息内容的代码
                    InputStream is = entity.getContent();
                    BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String line = br.readLine();
                    StringBuilder sb = new StringBuilder();
                    while (line != null) {
                        sb.append(line + "
    ");
                        line = br.readLine();
                    }
                    br.close();
                    is.close();
                    return new BestpayResult<>("200000","成功",sb.toString());
                }
                return new BestpayResult<>("200999","HttpGet响应entity内容为空");
    
            }catch (Exception e){
                e.printStackTrace();
                return new BestpayResult<>("999999","HttpGt请求未知异常");
            }finally {
                //最后要记得关闭
                httpGet.abort();
    
            }
    
        }

    发送post请求

        public BestpayResult<String> doService(String Url, String request) {
            System.out.println("请求翼支付的URL地址:"+Url);
            System.out.println("发送给翼支付的http请求报文:" + request);
            HttpPost httpPost = new HttpPost(Url);
            //配置请求
            httpPost.setHeader("Content-Type","application/json");
            //request就是参数了
            StringEntity se = new StringEntity(request, "utf-8");
            httpPost.setEntity(se);
            //HttpClients.createDefault();实现的就是HttpClientBuilder.create().build();
            CloseableHttpClient closeableHttpClient= HttpClients.createDefault();
            try {
                HttpResponse httpResponse=closeableHttpClient.execute(httpPost);
                //获得状态码
                int code=httpResponse.getStatusLine().getStatusCode();
                if (200==code){
                    //获得响应消息
                    HttpEntity entity=httpResponse.getEntity();
                    if (entity!=null){
                        String responseStr=EntityUtils.toString(httpResponse.getEntity(), "utf-8");
                        System.out.println("收到翼支付的http响应报文:"+responseStr);
                        return new BestpayResult<>(String.valueOf(code),"调用Http服务成功!", responseStr);
                    }else{
                        System.out.println("收到翼支付的http响应,但报文为空");
                        return new BestpayResult<>(String.valueOf(code),"调用Http服务成功!", null);
                    }
                }else{
                    System.out.println("调用翼支付Http请求失败,失败码为:"+code);
                    return new BestpayResult<>(String.valueOf(code),"调用Http服务失败!", null);
    
                }
            }catch (Exception e){
                e.printStackTrace();
                return new BestpayResult<>("999","调用Http服务失败!位置异常", null);
            }
            finally {
                if (closeableHttpClient!=null){
                    try {
                        closeableHttpClient.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
    
        }
     httpGet.abort();表示终止终止此次get访问,意思就是此次请求终止

    上面是最基本的请求,如果并发较大的话,则需要加连接池
    连接池管理器默认的为2和20

    那么如何为httpclient增加连接池管理器呢:https://www.cnblogs.com/wgslucky/p/11270038.html

    package com.tencent.service;
    
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.io.xml.DomDriver;
    import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NoHttpResponseException;
    import org.apache.http.client.HttpRequestRetryHandler;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ConnectTimeoutException;
    import org.apache.http.conn.ConnectionPoolTimeoutException;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContextBuilder;
    import org.apache.http.conn.ssl.SSLContexts;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.apache.http.entity.StringEntity;
    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.protocol.HttpContext;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLHandshakeException;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.SocketTimeoutException;
    import java.security.*;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.io.InterruptedIOException;
    import java.net.UnknownHostException;
    import javax.net.ssl.SSLException;
    import org.apache.http.HttpEntityEnclosingRequest;
    import org.apache.http.HttpRequest;
    import org.apache.http.client.protocol.HttpClientContext;
    
    /**
     * User: rizenguo
     * Date: 2014/10/29
     * Time: 14:36
     */
    public class HttpsRequest implements IServiceRequest {
    
    
        private static final Logger log = LoggerFactory.getLogger(HttpsRequest.class);
    
        //表示请求器是否已经做了初始化工作
        private boolean hasInit = false;
    
        //连接超时时间,默认10秒
        private int socketTimeout = 10000;
    
        //传输超时时间,默认30秒
        private int connectTimeout = 30000;
    
        //请求器的配置
        private RequestConfig requestConfig;
    
        //HTTP请求器
        private CloseableHttpClient httpClient;
    
        private  PoolingHttpClientConnectionManager poolConnManager = new PoolingHttpClientConnectionManager();
    
        public HttpsRequest() throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
            this(false,null,null);
        }
    
        public HttpsRequest(boolean is_cert, String sslcert_path, String sslcert_password) throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
            init(is_cert,sslcert_path,sslcert_password);
        }
    
        private void init(boolean is_cert, String sslcert_path, String sslcert_password) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
            SSLContext sslcontext = null;
            if(is_cert)
            {
                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                FileInputStream instream = new FileInputStream(new File(sslcert_path));//加载本地的证书进行https加密传输
                try {
                    keyStore.load(instream, sslcert_password.toCharArray());//设置证书密码
                } catch (CertificateException e) {
                    log.error(e.getMessage(),e);
                } catch (NoSuchAlgorithmException e) {
                    log.error(e.getMessage(),e);
                } finally {
                    instream.close();
                }
    
                // Trust own CA and all self-signed certs
                sslcontext = SSLContexts.custom()
                        .loadKeyMaterial(keyStore, sslcert_password.toCharArray())
                        .build();
            }
            else
            {
                try {
                    sslcontext = new SSLContextBuilder().loadTrustMaterial(
                            null, new TrustStrategy() {
                                // 信任所有
                                @Override
                                public boolean isTrusted(X509Certificate[] chain,
                                                         String authType) throws CertificateException {
                                    return true;
                                }
                            }).build();
                } catch (KeyManagementException e) {
                    log.error(e.getMessage(),e);
                } catch (NoSuchAlgorithmException e) {
                    log.error(e.getMessage(),e);
                } catch (KeyStoreException e) {
                    log.error(e.getMessage(),e);
                }
    
            }
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            // 设置最大连接数
            poolConnManager.setMaxTotal(200);
            // 设置每个连接的路由数
            poolConnManager.setDefaultMaxPerRoute(200);
    
            //根据默认超时限制初始化requestConfig
            requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                    .setConnectTimeout(connectTimeout)
                    .setConnectionRequestTimeout(connectTimeout).build();
            //请求失败时,进行请求重试
            HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
                @Override
                public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
                    if (i > 3){
                        //重试超过3次,放弃请求
                        log.info("retry has more than 3 time, give up request");
                        return false;
                    }
                    if (e instanceof NoHttpResponseException){
                        //服务器没有响应,可能是服务器断开了连接,应该重试
                        log.info("receive no response from server, retry");
                        return true;
                    }
                    if (e instanceof SSLHandshakeException){
                        // SSL握手异常
                        log.info("SSL hand shake exception");
                        return false;
                    }
                    if (e instanceof InterruptedIOException){
                        //超时
                        log.info("InterruptedIOException");
                        return false;
                    }
                    if (e instanceof UnknownHostException){
                        // 服务器不可达
                        log.info("server host unknown");
                        return false;
                    }
                    if (e instanceof ConnectTimeoutException){
                        // 连接超时
                        log.info("Connection Time out");
                        return false;
                    }
                    if (e instanceof SSLException){
                        log.info("SSLException");
                        return false;
                    }
    
                    HttpClientContext context = HttpClientContext.adapt(httpContext);
                    HttpRequest request = context.getRequest();
                    if (!(request instanceof HttpEntityEnclosingRequest)){
                        //如果请求不是关闭连接的请求
                        return true;
                    }
                    return false;
                }
            };
        
            httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
              //添加加连接池管理器
              .setConnectionManager(poolConnManager)
              //为客户端配置超时时间。个人理解,这儿配置了,和在具体的post上请求是一样的,这:
    httpPost.setConfig(requestConfig);
              .setDefaultRequestConfig(requestConfig)
              //重试机制:https://www.jianshu.com/p/6a41c95855e3
              .setRetryHandler(handler)
              //连接池共享
              
    .setConnectionManagerShared(true).build();
              hasInit = true;
        }
    
        /**
         * 通过Https往API post xml数据
         *
         * @param url    API地址
         * @param xmlObj 要提交的XML数据对象
         * @return API回包的实际数据
         * @throws IOException
         * @throws KeyStoreException
         * @throws UnrecoverableKeyException
         * @throws NoSuchAlgorithmException
         * @throws KeyManagementException
         */
    
        public String sendPost(String url, boolean is_cert, String sslcert_path, String sslcert_password, Object xmlObj) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
    
            if (!hasInit) {
                init(is_cert,sslcert_path,sslcert_password);
            }
    
            String result = null;
    
            HttpPost httpPost = new HttpPost(url);
    
            //解决XStream对出现双下划线的bug
            XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
    
            xStreamForRequestPostData.alias("xml",xmlObj.getClass());
    
            //将要提交给API的数据对象转换成XML格式数据Post给API
            String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
    
    //        log.info("API,POST过去的数据是:{}",postDataXML);
    
            //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
            StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
            httpPost.addHeader("Content-Type", "text/xml");
    //        httpPost.addHeader("Connection","Keep-Alive");
    //        httpPost.addHeader("Keep-alive","19000");
            httpPost.setEntity(postEntity);
    
            //设置请求器的配置
            httpPost.setConfig(requestConfig);
    
            //log.info("executing request " + httpPost.getRequestLine());
            CloseableHttpResponse response=null;
            try {
                 response = httpClient.execute(httpPost);
    
    //            HttpResponse response = httpClient.execute(httpPost);
    
                HttpEntity entity = response.getEntity();
    
                result = EntityUtils.toString(entity, "UTF-8");
    
            } catch (ConnectionPoolTimeoutException e) {
                log.info("http get throw ConnectionPoolTimeoutException(wait time out)");
    
            } catch (ConnectTimeoutException e) {
                log.info("http get throw ConnectTimeoutException");
    
            } catch (SocketTimeoutException e) {
                log.info("http get throw SocketTimeoutException");
    
            } catch (Exception e) {
                log.info("http get throw Exception");
                log.info("http get throw Exception异常信息为:"+e.getMessage());
                log.info("http get throw Exception异常信息为:"+e.getCause());
    
            } finally {
                try {
                    if(response != null) {
                        response.close();
                    }
                    if(httpClient!=null){
                        httpClient.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                httpPost.abort();
    
    
            }
    
            return result;
        }
    
        /**
         * 设置连接超时时间
         *
         * @param socketTimeout 连接时长,默认10秒
         */
        public void setSocketTimeout(int socketTimeout) {
            socketTimeout = socketTimeout;
            resetRequestConfig();
        }
    
        /**
         * 设置传输超时时间
         *
         * @param connectTimeout 传输时长,默认30秒
         */
        public void setConnectTimeout(int connectTimeout) {
            connectTimeout = connectTimeout;
            resetRequestConfig();
        }
    
        private void resetRequestConfig(){
            requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        }
    
        /**
         * 允许商户自己做更高级更复杂的请求器配置
         *
         * @param requestConfig 设置HttpsRequest的请求器配置
         */
        public void setRequestConfig(RequestConfig requestConfig) {
            requestConfig = requestConfig;
        }
    }




  • 相关阅读:
    人类登月不可或缺 大型机半个世纪发展史
    宽带上网知识(如何进行上网流程配置,路由器上网配置)
    团队项目第二阶段——第二天
    用户体验评价之QQ浏览器
    团队项目第二阶段——第一天
    第十四周学习进度总结
    《梦断代码》阅读笔记02
    第十三周学习进度总结
    第一阶段意见评论
    第十二周学习进度总结
  • 原文地址:https://www.cnblogs.com/cherishforchen/p/11102305.html
Copyright © 2020-2023  润新知