栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【HTTP 通信】HttpClient 进阶篇

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【HTTP 通信】HttpClient 进阶篇

更新日期:2022/03/24
愿你如阳光,明媚不忧伤。

目録

1. Header 消息头2. RequestConfig 请求配置3. HttpContext HTTP 执行上下文4. HttpRequestRetryHandler 请求重试处理5. HttpEntity 内容实体

5.1 streamed(流式)5.2 self-contained(自包含式)5.3 wrapping(包装式) 6. UrlEncodedFormEntity HTML 表单7. MultipartEntityBuilder 上传文件

7.1 流文件上传 8. ResponseHandler 响应处理程序

友情链接 【HTTP 通信】HttpClient 基础篇

 


1. Header 消息头

HTTP 标头字段是客户端程序和服务器在每个 HTTP 请求和响应中发送和接收的字符串列表。这些标头通常对最终用户不可见,仅由服务器和客户端应用程序处理或记录。

*************************************************************************
public static void main(String[] args) throws IOException {
    HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
    response.addHeader("Access-Control-Allow-Origin", "*");
    response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.addHeader("Cache-Control", "max-age=3600");
    response.addHeader("Date", "Mon, 21 Mar 2022 08:12:31 GMT");

    HeaderIterator it = response.headerIterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}
【Console】--------------------------------------------------------------
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Cache-Control: max-age=3600
Date: Mon, 21 Mar 2022 08:12:31 GMT
*************************************************************************

2. RequestConfig 请求配置

RequestConfig.java
用于获取和配置一些外部的网络环境,它下面有一个嵌套类 RequestConfig.Builder。

参考文献 https://www.cnblogs.com/chengxiansheng/p/13232686.html

*****************************************************************
// 是否期望能够继续:主要用于发送首先请求标头,以查看服务器是否允许(接受)请求。如果服务器显示OK,则发送100-continue,客户端继续请求正文。否则,服务器响应417(期望失败)
private boolean expectContinueEnabled;
// 设置代理 IP
private HttpHost proxy;
// InetAddress 类的对象用于 IP 地址和域名,取决于它是用主机名构造的,还是已经完成了反向主机名解析。"ouseki/192.168.2.6"
private InetAddress localAddress;
// 是否启用陈旧连接检查
private boolean staleConnectionCheckEnabled = false;
// cookie 规格
private String cookieSpec;
// 是否启用重定向
private boolean redirectsEnabled = true;
// 是否允许相对重定向
private boolean relativeRedirectsAllowed = true;
// 是否允许循环重定向
private boolean circularRedirectsAllowed;
// 设置最大重定向
private int maxRedirects = 50;
// 是否启用身份验证
private boolean authenticationEnabled = true;
// 目标首选身份验证方案
private Collection targetPreferredAuthSchemes;
// 代理首选身份验证方案
private Collection proxyPreferredAuthSchemes;
// 设置连接请求超时
private int connectionRequestTimeout = -1;
// 设置连接超时
private int connectTimeout = -1;
// 设置 socket 读写超时
private int socketTimeout = -1;
// 是否启用内容压缩
private boolean contentCompressionEnabled = true;
// 是否标准化 Uri
private boolean normalizeUri = true;
*****************************************************************

RequestConfig 应用实例

*****************************************************************
public class TestHttpClient {
    public static void main(String[] args) throws IOException {
        // 新建一个RequestConfig
        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setConnectTimeout(1)
                .setSocketTimeout(1)
                .setConnectionRequestTimeout(1)
                .build();
        // 这个超时可以设置为客户端级别,作为所有请求的默认值
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();
        System.out.println(httpclient.execute(new HttpGet("http://localhost:8080/")));
    }
}
【Console】------------------------------------------------------
17:52:30.792 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {}->http://localhost:8080][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
Exception in thread "main" org.apache.http.conn.ConnectTimeoutException: Connect to localhost:8080 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: connect timed out
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at com.ouseki.itgodroad.controller.TestHttpClient.main(TestHttpClient.java:50)
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.base/java.net.PlainSocketImpl.waitForConnect(Native Method)
	at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:107)
	at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
	at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
	at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
	at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
	at java.base/java.net.Socket.connect(Socket.java:608)
	at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	... 10 more
*****************************************************************

3. HttpContext HTTP 执行上下文

HttpContext 功能与 java.util.Map 类似,它是一组任意值的集合。一个应用程序可以在请求执行之前填充上下文属性或者在请求执行完成后检查上下文。多个请求序列使用同一个 HttpContext 实例就可以让会话信息和状态信息在多个请求之间自动广播。

HttpClientContext.java
可以使用 HttpClientContext 这个适配器类来简化操作上下文状态。

*************************************************************************
public class TestHttpClient extends LogBean {
    public static void main(String[] args) throws IOException {
        HttpContext context=new BasicHttpContext();
        context.setAttribute(HttpClientContext.HTTP_TARGET_HOST,new HttpHost("localhost", 8080, "http"));
        context.setAttribute(HttpClientContext.HTTP_ROUTE,new HttpRoute(new HttpHost("localhost", 80, "http")));
        HttpClientContext clientContext = HttpClientContext.adapt(context);
        System.out.println(clientContext.getTargetHost());
        System.out.println(clientContext.getHttpRoute());
    }
}
【Console】--------------------------------------------------------------
http://localhost:8080
{}->http://localhost:80
*************************************************************************

发送端
第二次请求没有携带参数,但还是读取到了内容,因为使用了相同的上下文,第一次请求过后,就将 jsessionid 保存起来了。

*************************************************************************
public class TestHttpClient extends LogBean {
    public static void main(String[] args) throws IOException {
        HttpContext httpContext = new BasicHttpContext();
        HttpClientContext httpClientContext = HttpClientContext.adapt(httpContext);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost("http://localhost:8080/ITGodRoad/testHttpContext.do");
        // 第一次请求,设置请求参数
        List formParams = new ArrayList<>();
        formParams.add(new BasicNamevaluePair("name", "ouseki"));
        formParams.add(new BasicNamevaluePair("collect", "人世间"));
        formParams.add(new BasicNamevaluePair("collect", "ITGodRoad"));
        httpPost.setEntity(new UrlEncodedFormEntity(formParams));
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpPost, httpClientContext);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity);
                System.out.println("第一次请求响应:" + result);
            }
        } finally {
            assert response != null;
            response.close();
        }

        System.out.println("=================第二次请求====================");
        // 重新创建一个 HttpPost 对象,但是此次该对象中不设置请求参数
        httpPost = new HttpPost("http://localhost:8080/ITGodRoad/testHttpContext.do");
        try {
            response = httpclient.execute(httpPost, httpClientContext);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity);
                System.out.println("第二次请求响应:" + result);
            }
        } finally {
            response.close();
        }
    }
}
【Console】--------------------------------------------------------------
第一次请求响应:login success!B503DAD69B10A4BACBEF44B037F1518E
=================第二次请求====================
第二次请求响应:Having been login ouseki	B503DAD69B10A4BACBEF44B037F1518E
*************************************************************************

目标服务端

*************************************************************************
@RequestMapping("/testHttpContext.do")
public void testHttpContext(HttpServletRequest request, HttpServletResponse response) {
    HttpSession session = request.getSession();
    String jsessionid = session.getId();
    // 从 session 中获取 name
    String name = (String) session.getAttribute("name");
    String result;
    if (name == null) {
        // 从请求参数中获取 name 的值
        name = request.getParameter("name");
        session.setAttribute("name", name);
        result = "login success!" + jsessionid;
    } else {
        result = "Having been login " + name + "t" + jsessionid;
    }
    // 将 result 内容写回到 response 响应体中
    ServletOutputStream outputStream = null;
    PrintWriter printWriter = null;
    try {
        outputStream = response.getOutputStream();
        printWriter = new PrintWriter(outputStream);
        printWriter.write(result);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (printWriter != null) {
            printWriter.close();
        }
        try {
            if (outputStream != null) {
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
*************************************************************************

4. HttpRequestRetryHandler 请求重试处理

默认情况下 HttpClient 尝试从 I/O exception 中自动恢复。默认的自动恢复机制只局限于少数已知的安全的异常。

    HttpClient 不会试图从任何逻辑或 HTTP 协议错误(衍生自 HttpException 类)中恢复。HttpClient 将自动重试那些被认为是幂等的方法。为了保证 HTTP 传输层的安全性,系统必须保证应用层中的 HTTP 方法是幂等的。HttpClient 将自动重试那些因传输异常而失败但是 HTTP 请求仍然会被发送到目标服务器的方法。即请求还没有完全被发送到服务器端

createHttpclientWithRetryHandler.java
为了使自定义异常恢复机制有效,实现了HttpRequestRetryHandler接口

*************************************************************************
public static HttpClient createHttpclientWithRetryHandler() {
    HttpRequestRetryHandler customRetryHandler = (exception, executionCount, context) -> {
        if (executionCount >= 5) {
            // Do not retry if over max retry count
            return false;
        }
        if (exception instanceof InterruptedIOException) {
            // Timeout
            return false;
        }
        if (exception instanceof UnknownHostException) {
            // Unknown host
            return false;
        }
        if (exception instanceof SSLException) {
            // SSL handshake exception
            return false;
        }

        HttpClientContext clientContext = HttpClientContext.adapt(context);
        HttpRequest request = clientContext.getRequest();
        boolean idempotent = request instanceof HttpEntityEnclosingRequest;
        if (!idempotent) {
            // Retry if the request is considered idempotent
            return true;
        }
        return false;
    };

    return HttpClients.custom()
            .setRetryHandler(customRetryHandler)
            .build();
}
*************************************************************************

5. HttpEntity 内容实体

HTTP 消息可以携带与其相关联的请求或响应的内容实体(它们是可选的)。
使用了实体的请求被称为封闭实体请求。当执行一次封闭实体请求或者是请求成功后,响应体被当做返回结果发回客户端的时候创建实体。
HttpClient 根据其内容来源分为三种类型的实体:streamed(流式)、self-contained(自包含式)、wrapping(包装式)

HttpEntity.java
HashApple.txt 是序列化后的二进制(字节)文件,需要反序列化才能正确显示其内容,乱码是对的。

*************************************************************************
public class TestHttpClient extends LogBean {

    public static void main(String[] args) throws IOException {
        FileEntity fileEntity = new FileEntity(new File("E:\HashApple.txt"), ContentType.DEFAULT_BINARY);
        // 告知此实体是否依赖于基础流。
        System.out.println("isStreamingt" + fileEntity.isStreaming());
        // 告知实体是否能够多次生成其数据。
        System.out.println("isRepeatablet" + fileEntity.isRepeatable());
        
        System.out.println("isChunkedt" + fileEntity.isChunked());
        
        InputStream content = fileEntity.getContent();
        System.out.println("getContentt" + new String(content.readAllBytes()));
        // 也可以调用 EntityUtils 工具类中方法(默认字符编码为 ISO_8859_1)
        System.out.println("getContentt" + EntityUtils.toString(fileEntity));
        
        System.out.println("getContentTypet" + fileEntity.getContentType());
        
        System.out.println("getContentLengtht" + fileEntity.getContentLength());
        
        System.out.println("getContentEncodingt" + fileEntity.getContentEncoding());
    }
}
【Console】--------------------------------------------------------------
isStreaming	false
isRepeatable	true
isChunked	false
getContent	�� sr )com.ouseki.itgodroad.controller.HashApple        L colort Ljava/lang/String;L gramt Ljava/lang/Double;L shapeq ~ xpt redsr java.lang.Double���J)k� D valuexr java.lang.Number������  xp@i��Q�t circle
getContent	¬í sr )com.ouseki.itgodroad.controller.HashApple        L colort Ljava/lang/String;L gramt Ljava/lang/Double;L shapeq ~ xpt redsr java.lang.Double€³ÂJ)kû D valuexr java.lang.Number†¬•”à‹  xp@i
¸Qìt circle
getContentType	Content-Type: application/octet-stream
getContentLength	227
getContentEncoding	null
*************************************************************************
5.1 streamed(流式)

内容是从流中接收的,或者是动态生成的。流式实体是不可重复生成的。

*************************************************************************

InputStream is = new ByteArrayInputStream("streamed".getBytes());
BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
basicHttpEntity.setContent(is);


InputStreamEntity inputStreamEntity = new InputStreamEntity(is);


SerializableEntity serializableEntity = new SerializableEntity("ouseki",true);
*************************************************************************
5.2 self-contained(自包含式)

内容在内存中或通过独立于连接或其他实体的方式获得。自包含实体可以重复生成(意味着它的内容可以被多次读取)。这种类型的实体将主要被用于封闭 HTTP 请求。

*************************************************************************

ByteArrayEntity byteArrayEntity = new ByteArrayEntity("self-contained".getBytes());


FileEntity fileEntity = new FileEntity(new File("E:\exercise.gif"), ContentType.IMAGE_GIF);


String str = "self-contained";
StringEntity stringEntity2 = new StringEntity(str, StandardCharsets.UTF_8);
*************************************************************************
5.3 wrapping(包装式)

内容是从另一个实体获取的。

*************************************************************************

HttpEntity httpEntity = new StringEntity("wrapping");
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpEntity);


DecompressingEntity decompressingEntity = new DecompressingEntity(httpEntity,GZIPInputStreamFactory.getInstance());


GzipCompressingEntity gzipCompressingEntity = new GzipCompressingEntity(httpEntity);
*************************************************************************

6. UrlEncodedFormEntity HTML 表单

许多应用程序需要模拟一个提交 HTML 表单的过程,HttpClient 提供了实体类 UrlEncodedFormEntity 它使用 URL 编码来编码参数,生成如下的内容:param1=value1¶m2=value2

发送端

*************************************************************************
public class TestHttpClient extends LogBean {
    public static void main(String[] args) throws IOException {
        List formParams = new ArrayList<>();
        formParams.add(new BasicNamevaluePair("name", "ouseki"));
        formParams.add(new BasicNamevaluePair("collect", "人世间"));
        formParams.add(new BasicNamevaluePair("collect", "ITGodRoad"));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8);
        HttpPost httppost = new HttpPost("http://localhost:8080/ITGodRoad/testUrlEncodedFormEntity.do");
        httppost.setEntity(entity);
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        CloseableHttpResponse response = httpclient.execute(httppost);
        HttpEntity responseEntity = response.getEntity();
        if (responseEntity != null) {
            System.out.println("HTTPS响应内容长度为:" + responseEntity.getContentLength());
            String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
            System.out.println("HTTPS响应内容为:" + responseStr);
        }
    }
}
【Console】--------------------------------------------------------------
HTTPS响应内容长度为:47
10:07:19.257 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 0][route: {}->http://localhost:8080] can be kept alive for 20.0 seconds
10:07:19.257 [main] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: set socket timeout to 0
10:07:19.257 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {}->http://localhost:8080][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
HTTPS响应内容为:name : [ouseki]collect : [人世间, ITGodRoad]
*************************************************************************

目标服务端
如果后端响应返回的中文乱码,肯定是编码问题,有两种解决方案:
1.修改注解:produces = { “text/plain;charset=utf-8” }
2.配置拦截器并设置 response.setContentType(“application/json;charset=utf-8”);

*************************************************************************
@RestController
public class Test {

    @RequestMapping(value = "/testUrlEncodedFormEntity.do", produces = { "text/plain;charset=utf-8" })
    public String test(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        Map parameterMap = request.getParameterMap();
        StringBuilder stringBuilder = new StringBuilder();
        for (String key : parameterMap.keySet()) {
            String[] value = parameterMap.get(key);
            stringBuilder.append(key).append(" : ").append(Arrays.toString(value));
        }
        return stringBuilder.toString();
    }
}
*************************************************************************

7. MultipartEntityBuilder 上传文件

pom.xml
即便不引入 httpmime 依赖,也是能传输文件的,不过功能不够强大。


    org.apache.httpcomponents
    httpmime
    4.5.13

发送端

*************************************************************************
public class TestHttpClient extends LogBean {
    public static void main(String[] args) {
        List params = new ArrayList<>();
        params.add(new BasicNamevaluePair("name", "ouseki"));
        params.add(new BasicNamevaluePair("age", "25"));
        URI uri = null;
        try {
            uri = new URIBuilder().setScheme("http").setHost("localhost")
                    .setPort(8080).setPath("/ITGodRoad/testDoUpload.do")
                    .addParameters(params)
                    .build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        doUpload(uri);
    }
.........................................................................
    public static void doUpload(URI uri) {
        String filesKey = "files";
        File file = new File("E:\uploadFiles");
        File[] files = file.listFiles();
        assert files != null;
        ClientCustomSSLUtil.doUpload(uri, filesKey, files);
    }
}
*************************************************************************
public class ClientCustomSSLUtil {
    public static void doUpload(URI uri, String filesKey, File[] files) {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost httppost = new HttpPost(uri);
        CloseableHttpResponse response = null;
        try {
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            for (File file : files) {
                
                multipartEntityBuilder.addBinaryBody(filesKey, file, ContentType.DEFAULT_BINARY, URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));
            }
            
            HttpEntity httpEntity = multipartEntityBuilder.build();
            httppost.setEntity(httpEntity);
            response = httpclient.execute(httppost);
            HttpEntity responseEntity = response.getEntity();
            System.out.println(("HTTPS 响应状态为:" + response.getStatusLine()));
            if (responseEntity != null) {
                System.out.println("HTTPS 响应内容长度为:" + responseEntity.getContentLength());
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("HTTPS 响应内容为:" + responseStr);
            }
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                assert response != null;
                httpclient.close();
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
【Console】--------------------------------------------------------------
HTTPS 响应状态为:HTTP/1.1 200 
HTTPS 响应内容长度为:200
HTTPS 响应内容为:ouseki25
文件信息
	文件名:cat.jpeg	文件大小:40kb	文件类型:application/octet-stream
文件信息
	文件名:HashApple.txt	文件大小:0kb	文件类型:application/octet-stream
*************************************************************************

目标服务端

*************************************************************************
@RequestMapping(value = "/testUrlEncodedFormEntity.do", produces = { "text/plain;charset=utf-8" }, method = RequestMethod.POST)
public String testDoUpload(@RequestParam("name") String name, @RequestParam("age") String age,
        @RequestParam("files") List multipartFilesList) throws UnsupportedEncodingException {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(name).append(age);
    String fileName;
    for (MultipartFile file : multipartFilesList) {
        stringBuilder.append("n文件信息n");
        fileName = file.getOriginalFilename();
        if (fileName == null) {
            continue;
        }
        fileName = URLDecoder.decode(fileName, Constant.UTF_8);
        stringBuilder.append("t文件名:").append(fileName);
        stringBuilder.append("t文件大小:").append(file.getSize() / 1024).append("kb");
        stringBuilder.append("t文件类型:").append(file.getContentType());
    }
    return stringBuilder.toString();
}
*************************************************************************

 

7.1 流文件上传

发送端

*************************************************************************
public class TestHttpClient extends LogBean {
    public static void main(String[] args) {
        List params = new ArrayList<>();
        params.add(new BasicNamevaluePair("name", "ouseki"));
        params.add(new BasicNamevaluePair("age", "25"));
        URI uri = null;
        try {
            uri = new URIBuilder().setScheme("http").setHost("localhost")
                    .setPort(8080).setPath("/ITGodRoad/testDoUploadStream.do")
                    .addParameters(params)
                    .build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        doUploadStream(uri);
    }
.........................................................................
    public static void doUploadStream(URI uri) {
        InputStream inputStream = new ByteArrayInputStream("流文件上传".getBytes());
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost httppost = new HttpPost(uri);
        CloseableHttpResponse response = null;
        try {
            InputStreamEntity ise = new InputStreamEntity(inputStream);
            httppost.setEntity(ise);
            response = httpclient.execute(httppost);
            HttpEntity responseEntity = response.getEntity();
            System.out.println("HTTPS 响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("HTTPS 响应内容长度为:" + responseEntity.getContentLength());
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("HTTPS 响应内容为:" + responseStr);
            }
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                assert response != null;
                httpclient.close();
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
【Console】--------------------------------------------------------------
HTTPS 响应状态为:HTTP/1.1 200 
HTTPS 响应内容长度为:50
HTTPS 响应内容为:ouseki25输入流中的数据为:流文件上传
*************************************************************************

目标服务端

*************************************************************************
@RequestMapping(value = "/testDoUploadStream.do", produces = { "text/plain;charset=utf-8" }, method = RequestMethod.POST)
public String testDoUploadStream(@RequestParam("name") String name, @RequestParam("age") String age, InputStream inputStream) throws IOException {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(name).append(age).append("输入流中的数据为:");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Constant.UTF_8));
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        stringBuilder.append(line);
    }
    return stringBuilder.toString();
}
*************************************************************************

8. ResponseHandler 响应处理程序

处理响应最简单方便的方式是使用 ResponseHandler 接口,它包含了 handleResponse(HttpResponse response) 方法。
这个方法彻底的解决了用户对于连接管理的困扰。当使用 ResponseHandler 接口时, 无论是否请求执行成功或引发异常,HttpClient 都会自动关闭来确保释放的连接返回到连接管理器。

*************************************************************************
public class TestHttpClient extends LogBean {

    public static void main(String[] args) throws IOException {
        System.out.println(customResponseHandler());
    }
.........................................................................
    public static String customResponseHandler() throws IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httppost = new HttpPost("http://localhost:8080/ITGodRoad/testUrlEncodedFormEntity.do");
        ResponseHandler responseHandler = (response) -> {
            StatusLine statusLine = response.getStatusLine();
            HttpEntity entity = response.getEntity();
            if (statusLine.getStatusCode() >= 300) {
                throw new HttpResponseException(
                        statusLine.getStatusCode(),
                        statusLine.getReasonPhrase());
            }
            if (entity == null) {
                throw new ClientProtocolException("Response contains no content");
            }
            return "请求访问成功";
        };

        return httpclient.execute(httppost, responseHandler);
    }
}
【Console】--------------------------------------------------------------
请求访问成功
*************************************************************************
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778323.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号