美文网首页Java web
Java HttpClient发送HTTP 请求

Java HttpClient发送HTTP 请求

作者: __元昊__ | 来源:发表于2019-08-06 15:16 被阅读0次

    apache httpclient不多介绍这个工具是什么,具体请看官网,不赘述。

    先看第一个demo,把这个东西用起来再说。

    /**
     * 使用httpclient-4.5.2发送请求
     * @author lyh
     * 2019.8.12
     */
    public class FirstHttpClientDemo {
    
        public static void main(String[] args) {
            try {
                String url = "http://www.baidu.com";
                // 使用默认配置创建httpclient的实例
                CloseableHttpClient client = HttpClients.createDefault();
                
                HttpPost post = new HttpPost(url);
    //          HttpGet get = new HttpGet(url);
                
                CloseableHttpResponse response = client.execute(post);
    //          CloseableHttpResponse response = client.execute(get);
                
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println("status_code = " + status_code);
                
                // 服务器返回内容
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    这个demo主要是完成基本的交互过程,发送请求,接收消息,如果只是做小程序或者不是特别大并发量的系统,基本已经够用了。

    跟服务器交互,更多的是发送数据,然后接收到服务器返回的数据,一般我们利用http-client中的实体(Entity),具体在org.apache.http.entity包下面的类来封装我们的请求,从服务器上接收的也是实体.

    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
    /**
     * 使用httpclient-4.5.2发送请求参数
     * @author lyh
     * 2019.8.12
     */
    public class RequestParameterDemo {
    
        public static void main(String[] args) {
            try {
                String url = "http://localhost:9090";
                // 使用默认配置创建httpclient的实例
                CloseableHttpClient client = HttpClients.createDefault();
                
                HttpPost post = new HttpPost(url);
                
                /**
                 * 设置参数,常用的有StringEntity,UrlEncodedFormEntity,MultipartEntity
                 * 具体看org.apache.http.entity包
                 */
                List<NameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("username", "张三"));
                params.add(new BasicNameValuePair("password", "123456"));
                UrlEncodedFormEntity e = new UrlEncodedFormEntity(params, "UTF-8");
                post.setEntity(e);
                
                CloseableHttpResponse response = client.execute(post);
                
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println(status_code);
                
                // 服务器返回内容
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    代码模拟了客户端向服务器发送一个表单数据,最常用的场景就是发送报文数据/登陆动作了。

    接着上面,我们在使用HttpClient的时候更多的是需要自己根据业务特点创建自己定制化的HttpClient实例,而不是像之前那样使用

    // 使用默认配置创建httpclient的实例
    CloseableHttpClient client = HttpClients.createDefault();
    

    废话不多说,直接上代码(Talk is cheap, show me the code!):

    import org.apache.http.HttpEntity;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    /**
     * 使用httpclient-4.5.2发送请求,配置请求定制化参数
     * @author lyh
     * 2019.8.12
     */
    public class RequestConfigDemo {
    
        public static void main(String[] args) {
            try {
                String url = "http://www.baidu.com";
                /**
                 *  请求参数配置
                 *  connectionRequestTimeout:
                 *                          从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
                 *                          会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                 *  connectTimeout:
                 *                  连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
                 *  socketTimeout:
                 *                  服务器返回数据(response)的时间,超过该时间抛出read timeout
                 */
                CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectionRequestTimeout(2000).setConnectTimeout(2000).setSocketTimeout(2000).build()).build();
                
                HttpPost post = new HttpPost(url);
    //          HttpGet get = new HttpGet(url);
                
                CloseableHttpResponse response = client.execute(post);
    //          CloseableHttpResponse response = client.execute(get);
                
                // 服务器返回码
                int status_code = response.getStatusLine().getStatusCode();
                System.out.println("status_code = " + status_code);
                
                // 服务器返回内容
                String respStr = null;
                HttpEntity entity = response.getEntity();
                if(entity != null) {
                    respStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("respStr = " + respStr);
                // 释放资源
                EntityUtils.consume(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    需要说明的是,需要自己定制HttpClient客户端的话,我们使用HttpClients.custom(),然后调用各种set方法即可,一般建议使用HttpClients.custom().setDefaultRequestConfig()org.apache.http.client.config.RequestConfig类提供了很多可定制的参数,我们可以根据自己的配置来使用相关配置。有几个参数我们自己必须设置一下

    connectionRequestTimeout:从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
    
    connectTimeout:连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
    
    socketTimeout:服务器返回数据(response)的时间,超过该时间抛出read timeout
    

    通过打断点的方式我们知道,HttpClients在我们没有指定连接工厂的时候默认使用的是连接池工厂org.apache.http.impl.conn.PoolingHttpClientConnectionManager.PoolingHttpClientConnectionManager(Registry<ConnectionSocketFactory>),所以我们需要配置一下从连接池获取连接池的超时时间。
    以上3个超时相关的参数如果未配置,默认为-1,意味着无限大,就是一直阻塞等待!

    创建https需要使用org.apache.http.conn.ssl.SSLConnectionSocketFactoryPlainConnectionSocketFactorySSLConnectionSocketFactory都实现了ConnectionSocketFactory
    好了,直接上代码,代码实现的功能是,组装一个发往银联的查询报文(查询交易结果)。

    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
    /**
     * This example demonstrates how to create secure connections with a custom SSL
     * context.
     */
    public class ClientCustomSSL {
        private static String reqStr = "txnType=00&signMethod=01&certId=68759663125&encoding=UTF-8&merId=777290058110048&bizType=000201&txnSubType=00&signature=k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D&orderId=20160309145206&version=5.0.0&txnTime=20160309145206&accessType=0";
        private static String url = "https://101.231.204.80:5000/gateway/api/queryTrans.do";
    
        // 信任管理器
        private static X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        
        public final static void main(String[] args) throws Exception {
            long starttime = System.currentTimeMillis();
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSL上下文
            sslContext.init(null, new TrustManager[] { tm }, null);
            // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
            /**
             * 通过setSSLSocketFactory(sslsf)保证httpclient实例能发送Https请求
             */
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setMaxConnTotal(50)
                    .setMaxConnPerRoute(50).setDefaultRequestConfig(RequestConfig.custom()
                            .setConnectionRequestTimeout(60000).setConnectTimeout(60000).setSocketTimeout(60000).build())
                    .build();
            try {
    
                HttpPost httppost = new HttpPost(url);
                
                // 设置参数,参数含义不需要理解
                Map<String, String> map = new HashMap<String, String>();
                map.put("txnType","00");
                map.put("signMethod","01");
                map.put("certId","68759663125");
                map.put("encoding","UTF-8");
                map.put("merId","777290058110048");
                map.put("bizType","000201");
                map.put("txnSubType","00");
                map.put("signature","k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D");
                map.put("orderId","20160309145206");
                map.put("version","5.0.0");
                map.put("txnTime","20160309145206");
                map.put("accessType","0");
                
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Entry<String, String> elem = (Entry<String, String>) iterator.next();
                    list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
                }
                if (list.size() > 0) {
                    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
                    httppost.setEntity(entity);
                }
                
                System.out.println("executing request " + httppost.getRequestLine());
    
                CloseableHttpResponse response = httpclient.execute(httppost);
                try {
                    HttpEntity entity = response.getEntity();
    
                    System.out.println("----------------------------------------");
                    System.out.println(response.getStatusLine());
                    if (entity != null) {
                        System.out.println("Response content length: " + entity.getContentLength());
                    }
                    String s = EntityUtils.toString(entity,"UTF-8");
                    System.out.println("应答内容:" + s);
                    
                    EntityUtils.consume(entity);
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
            
            long endtime = System.currentTimeMillis();
            System.out.println("耗时:" + (endtime-starttime) + "ms");
        }
    
    }
    

    使用注册器可以保证既能发送http请求也能发送httpsclient请求,代码块如下:

    int httpReqTimeOut = 60000;//60秒
    
    SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSL上下文
            sslContext.init(null, new TrustManager[] { tm }, null);
            // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
            // 注册http套接字工厂和https套接字工厂
            Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", sslsf)
                    .build();
            // 连接池管理器
            PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);
            pcm.setMaxTotal(maxConnTotal);//连接池最大连接数
            pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数
            /**
             *  请求参数配置
             *  connectionRequestTimeout:
             *                          从连接池中获取连接的超时时间,超过该时间未拿到可用连接,
             *                          会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
             *  connectTimeout:
             *                  连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
             *  socketTimeout:
             *                  服务器返回数据(response)的时间,超过该时间抛出read timeout
             */
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(httpReqTimeOut)
                    .setConnectTimeout(httpReqTimeOut)
                    .setSocketTimeout(httpReqTimeOut)
                    .build();
            /**
             * 构造closeableHttpClient对象
             */
            closeableHttpClient = HttpClients.custom()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(pcm)
                    .setRetryHandler(retryHandler)
                    .build();
    

    关键代码为:

    // 注册http套接字工厂和https套接字工厂
            Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", sslsf)
                    .build();
    

    样例通过Post发送soap1.1协议xml格式的请求

    pom

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.6</version>
    </dependency>
    
    import java.io.IOException;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.ResponseHandler;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    public class Znkf_soap_post {
        /**
         * post发送xml格式的soap1.1协议
         * @param irnonumber 查询参数
         * @param username 查询参数
         * @return 查询内容
         */
        public static String post_method(String irnonumber,String username) {
            String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                    "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                    "  <soap:Body>\n" +
                    "    <GetIrnoMessage xmlns=\"http://tempuri.org/\">\n" +
                    "      <irnonumber>"+irnonumber+"</irnonumber>\n" +
                    "      <username>"+username+"</username>\n" +
                    "    </GetIrnoMessage>\n" +
                    "  </soap:Body>\n" +
                    "</soap:Envelope>";
            try {
                CloseableHttpClient httpclient = HttpClients.createDefault();
    
                HttpPost httpPost = new HttpPost("http://10.6.187.27:8081/WsIrnoSelect/Service.asmx");
                httpPost.addHeader("Content-Type","text/xml;charset=UTF-8");
                httpPost.addHeader("SOAPAction","http://tempuri.org/GetIrnoMessage");
                //解决中文乱码问题
                StringEntity stringEntity = new StringEntity(xml,"UTF-8");
                stringEntity.setContentEncoding("UTF-8");
    
                httpPost.setEntity(stringEntity);
    
               /* HttpResponse response = httpclient.execute(httpPost);
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    String result = EntityUtils.toString(response.getEntity());
                    return HttpStatus.SC_OK + result;
                }*/
    
    
                //   Create a custom response handler
                ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                    @Override
                    public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {//
                        int status = response.getStatusLine().getStatusCode();
                        if (status >= 200 && status < 300) {
                            HttpEntity entity = response.getEntity();
                            return entity != null ? EntityUtils.toString(entity) : null;
                        } else {
                            throw new ClientProtocolException(
                                    "Unexpected response status: " + status);
                        }
                    }
                };
                String responseBody = httpclient.execute(httpPost, responseHandler);
                System.out.println("----------------------------------------");
                System.out.println(responseBody);
                int startIndex = responseBody.indexOf("<GetIrnoMessageResult>");
                int endIndex = responseBody.indexOf("</GetIrnoMessageResult>");
                return responseBody.substring(startIndex+22, endIndex);
            } catch (Exception e) {
                e.printStackTrace();
                return "出现异常";
            }
        }
    
        public static void main(String[] args) {
            String s = post_method("1200", "12");
            System.out.println(s);
        }
    }
    

    相关文章

      网友评论

        本文标题:Java HttpClient发送HTTP 请求

        本文链接:https://www.haomeiwen.com/subject/nxxwdctx.html