关注公众号,一起交流,微信搜一搜: 潜行前行

HttpClient (apache)

apache HttpClient 是 java项目里 较为常用的组件之一;对接外部服务时,各个商家提供的接口是各式各样的,有自己的要求,因此要定制对应的请求客户端。httpClient是一个不错的选择

  • apache HttpClient 实现了 HTTP 1.0 和 HTTP 1.1。支持 HTTP 全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)

    • GET, POST 的实现是继承 HttpRequestBase,HttpRequestBase 实现 HttpUriRequest,HttpUriRequest 继承 HttpRequest;GET, POST 方法对应 java 类的 HttpGet 和 HttpPost
  • 支持 TLS,SSL 的 HTTPS。支持多线程操作
  • 基于阻塞的 I/0 实现,也就是说使用 HttpClient 的线程会被阻塞
  • 头部信息设置
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type","application/json; charset=utf-8");
  • 证书信息设置
private static SSLContext getSslContext() throws Exception {
//自身私钥
KeyStore identityKeyStore = KeyStore.getInstance("jks");
FileInputStream identityKeyStoreFile = new FileInputStream("/root/myServer.jks");
identityKeyStore.load(identityKeyStoreFile, "password1".toCharArray());
//服务端信任证书
KeyStore trustKeyStore = KeyStore.getInstance("jks");
FileInputStream trustKeyStoreFile = new FileInputStream("/root/trustKeyStore.jks");
trustKeyStore.load(trustKeyStoreFile, "password".toCharArray());
//构建SSLContexts
return SSLContexts.custom()
.loadKeyMaterial(identityKeyStore, "password1".toCharArray()) // load identity keystore
.loadTrustMaterial(trustKeyStore, null) // load trust keystore
.build();
}
public static void postWithSSL(String url, String jsonBody) throws Exception {
SSLContext sslContext = getSslContext();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext, new String[]{"TLSv1.2", "TLSv1.1", "TLSv1"}, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
/**
// HttpClients 产生的 client 都共用相同的证书秘钥
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
HttpClients.custom().setConnectionManager(connManager);
*/
....
}
  • 缓存 cookie 设置
//自定义 cookie
CookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("csc", "lwl");
cookieStore.addCookie(cookie);
// 从上一次请求获取
HttpPost httppost = ...
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
CookieStore cookiestore=httpclient.getCookieStore();
// DefaultHttpClient 使用 cookie
HttpPost httppost2 = ...
DefaultHttpClient httpclient2 = new DefaultHttpClient();
httpclient2.setCookieStore(cookiestore);
response = httpclient2.execute(httppost2);
  • RequestConfig 的使用
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(5000)
.setConnectionRequestTimeout(5000)
.setRedirectsEnabled(true)
.build();
//使用
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultRequestConfig(defaultRequestConfig)
.build();
  • HttpEntity 是对《请求或者响应》对象的封装,具体实现类有

    • BasicHttpEntity,InputStreamEntity:操作对象是数据流
    • BufferedHttpEntity:带缓冲区的 HttpEntity,其他HttpEntity的包装类,将内容存入一缓存区 可以重复读
    • FileEntity:文件对应的Entity FileEntity entity = new FileEntity(new File(""), "application/java-achive");
    • StringEntity:字符串 Entity。一般用 json ,text/plain,text/xml 类型的post请求
    • UrlEncodedFormEntity,一般用于 application/x-www-form-urlencoded 类型的post请求
  • HttpContext:它是 Http 请求上下文类,如果是同一个上下文,则两次请求间可以共享这个上线文的信息。虽然 HttpClient 本身就具备维护cookies的功能,但 HttpContext 的好处是在于多个 HttpClient 实例之间可以共享 HttpContext

一些建议

  • 1 释放资源:读取完响应后,我们需要尽快释放response本身和响应实体本身的流来对资源进行回收
  • 2 有时可能需要多次读取返回的响应内容,将响应内容进行缓冲。最简单的方法是用BufferedHttpEntity 类包装原始实体。这会让原始实体的内容被读入内存缓冲区
CloseableHttpResponse response = ...
HttpEntity entity = new BufferedHttpEntity(response.getEntity());
  • 3 HttpClient 的线程安全:使用同一个HttpClient的实例即可做到线程安全,因为 HttpClient 内部就有一个池化机制,支持多线程
  • 4 EntityUtils.toString(entity) : 把内容转成字符串

CloseableHttpClient 是 HttpClient 的子类。mvn 引入

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>

HttpClient 的API

HttpResponse execute(HttpUriRequest request)
HttpResponse execute(HttpUriRequest request, HttpContext context)
HttpResponse execute(HttpHost target, HttpRequest request)
HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context)
<T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler)
<T> T execute(HttpHost target,HttpRequest request, ResponseHandler<? extends T> responseHandler)
<T> T execute(HttpHost target, HttpRequest request,
ResponseHandler<? extends T> responseHandler, HttpContext context)

get 请求

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://localhost:8080/content/lwl");
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity));// 输出请求结果
httpResponse.close();

post 请求

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.baidu.com");
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("username", "csc"));
params.add(new BasicNameValuePair("password", "lwl"));
httpPost.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity));// 输出请求结果
httpResponse.close();

文件上传

CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("http://localhost:8080/lwl/upload"); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
File file1 = new File("C:\\Users\\csc\\Desktop\\data.jpg"); // 第一个文件
multipartEntityBuilder.addBinaryBody("files", file1);
File file2 = new File("C:\\Users\\csc\\Desktop\\头像.jpg"); // 第二个文件
// 为避免中文乱码问题,可以对文件名 urlDecode
multipartEntityBuilder.addBinaryBody("files", file2, ContentType.DEFAULT_BINARY, URLEncoder.encode(file2.getName(), "utf-8")); // 其它参数
multipartEntityBuilder.addTextBody("name", "lwl", ContentType.create("text/plain", Charset.forName("UTF-8"))); HttpEntity httpEntity = multipartEntityBuilder.build();
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
System.out.println(response.getStatusLine());
response.close();

HttpClient (jdk11)

java.net.http.HttpClient 是 jdk11 中正式启用的一个 http 工具类(在 jdk9 的时候就已经存在),官方想要取代 HttpURLConnection 和 Apache HttpClient 等比较古老的开发工具

HttpClient 的API

//创建一个 HttpClient
public static Builder newBuilder()
public static HttpClient newHttpClient() // HttpClient.newBuilder().build()
//webSocket协议的请求客户端的构建者
public WebSocket.Builder newWebSocketBuilder()
public abstract Optional<CookieHandler> cookieHandler() // 获取 CookieHandler
public abstract Optional<Duration> connectTimeout()
public abstract Redirect followRedirects()
public abstract Optional<ProxySelector> proxy()
public abstract SSLContext sslContext()
public abstract Optional<Executor> executor()
  • HttpClient.Builder 的 API
//缓存cookie设置
public Builder cookieHandler(CookieHandler cookieHandler);
//连接超时时间
public Builder connectTimeout(Duration duration);
// 证书信息设置
public Builder sslContext(SSLContext sslContext);
// SSL / TLS / DTLS连接的参数 设置
public Builder sslParameters(SSLParameters sslParameters);
//涉及到异步操作用到的 线程池
public Builder executor(Executor executor);
// 是否支持重定向 Redirect.SAME_PROTOCOL
public Builder followRedirects(Redirect policy);
// 协议版本,HTTP/1.1 还是 HTTP/2
public Builder version(HttpClient.Version version);
public Builder priority(int priority);
//配置代理
public Builder proxy(ProxySelector proxySelector);
//认证 Authenticator.getDefault()
public Builder authenticator(Authenticator authenticator);
  • HttpClient 调用 API
//阻塞调用
<T> HttpResponse<T> send(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler)
//相当于使用了多路复用I/O
<T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, BodyHandler<T> responseBodyHandler)
abstract <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request,
BodyHandler<T> responseBodyHandler, PushPromiseHandler<T> pushPromiseHandler)

HttpRequest 构建的 API

对于请求内容可以使用 BodyPublishers 封装的函数生成

HttpResponse 的API

对于响应的解析读取可以使用 BodyHandlers 或者 BodySubscribers 封装的函数处理

get 请求

HttpRequest request = HttpRequest.newBuilder(URI.create("http://localhost:8080/content/lwl"))
.GET()
.timeout(Duration.ofSeconds(10)) // 设置响应超时时间
.build();
HttpClient httpClient = HttpClient.newHttpClient();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

post 请求

String data = .....// json 请求数据
HttpRequest request = HttpRequest.newBuilder(URI.create("https://www.baidu.com"))
.POST(HttpRequest.BodyPublishers.ofString(data, Charset.defaultCharset()))
.header("Content-Type", "application/json") //设置头部信息
.timeout(Duration.ofSeconds(10)) // 设置响应超时时间
.build();
HttpClient httpClient = HttpClient.newHttpClient();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

欢迎指正文中错误

参考文章

工具篇:apache-httpClient 和 jdk11-HttpClient的使用的更多相关文章

  1. 170314、工具:apache httpClient多线程并发情况下安全实用及工具类分享

    简单用法介绍:介绍来源网络 建立连接:在HttpClient中使用多线程的一个主要原因是可以一次执行多个方法.在执行期间,每一个方法都使用一个HttpConnection实例.由于在同一时间多个连接只 ...

  2. 工具篇-Java中一些utils

    下边是整理的一些Java开发的utils,顺便吐槽下新浪博客的编辑器排版跟我写的博客一样 烂,所以改用博客园 一.字符串 1. Java中String与其他类型之间的转换 String与日期对象 pu ...

  3. 大数据工具篇之Hive与HBase整合完整教程

    大数据工具篇之Hive与HBase整合完整教程 一.引言 最近的一次培训,用户特意提到Hadoop环境下HDFS中存储的文件如何才能导入到HBase,关于这部分基于HBase Java API的写入方 ...

  4. 工具篇-MAT(Memory Analyzer Tool)

    --- layout: post title: 工具篇-MAT(Memory Analyzer Tool) description: 让内存泄漏无所遁形 2015-10-08 category: bl ...

  5. 工具篇-TraceView

    --- layout: post title: 工具篇-TraceView  description: 让我们远离卡顿和黑屏 2015-10-09 category: blog --- ## 让我们远 ...

  6. 【工具篇】利用DBExportDoc V1.0 For MySQL自动生成数据库表结构文档

    对于DBA或开发来说,如何规范化你的数据库表结构文档是灰常之重要的一件事情.但是当你的库,你的表排山倒海滴多的时候,你就会很头疼了. 推荐一款工具DBExportDoc V1.0 For MySQL( ...

  7. css,js工具篇

    4. web前端开发分享-css,js工具篇   web前端开发乃及其它的相关开发,推荐sublime text, webstorm(jetbrains公司系列产品)这两个的原因在于,有个技术叫emm ...

  8. 大数据工具篇之Hive与MySQL整合完整教程

    大数据工具篇之Hive与MySQL整合完整教程 一.引言 Hive元数据存储可以放到RDBMS数据库中,本文以Hive与MySQL数据库的整合为目标,详细说明Hive与MySQL的整合方法. 二.安装 ...

  9. Linux工具XFTP、Xshell(centos配置java环境 工具篇 总结一)

    ♣Xmanager5是什么? ♣安装XFTP ♣安装Xshell 1.Xmanager5(官网:https://www.netsarang.com/download/software.html)是全新 ...

随机推荐

  1. CF346E-Doodle Jump【类欧】

    正题 题目链接:https://www.luogu.com.cn/problem/CF346E 题目大意 给出\(a,n,p,h\),在每个\(ax\%p(x\in[0,n])\)的位置有一个关键点, ...

  2. 推荐一款 Python 微服务框架 - Nameko

    1. 前言 大家好,我是安果! 考虑到 Python 性能及效率性,Python Web 端一直不温不火,JAVA 和 Golang 的微服务生态一直很繁荣,也被广泛用于企业级应用开发当中 ​本篇文章 ...

  3. FTP和TFTP

    文件传输协议 FTP概述: 文件传输协议FTP(File Transfer Protocol)[RFC 959]是互联网上使用最广泛的文件传输协议, FTP提供交互式的访问,允许用户知指明文件类型与格 ...

  4. Python:PNG图像生成MP4

    Python:PNG图像生成MP4 需求 需要将多张*.PNG图像,生成mp4格式的视频文件. 实现 利用Python中image库生成*.gif格式图像,但是图片未经压缩,文件体量较大. movie ...

  5. 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?

    通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...

  6. Azure Bicep(三)变量控制

    一,引言 当我们在使用 Azure Bicep 的时候会出现以下几个问题: 1)文件中有很多地方会重用很多相同的值 2)输入参数可以在统一的地方进行修改 带着这些问题,我们开始今天的内容,学习如何在 ...

  7. 用C++生成solidity语言描述的buchi自动机的初级经验

    我的项目rvtool(https://github.com/Zeraka/rvtool)中增加了生成solidity语言格式的监控器的模块. solidity特殊之处在于,它是运行在以太坊虚拟机环境中 ...

  8. jmeter基础功能及认识

    1.基础知识: JMeter是免费开源的,纯java开发的性能测试工具,可以测试静态和动态的资源,例如:静态文件.java服务小程序.CGI脚本.java对象.数据库.FTP服务器.邮件服务器和Per ...

  9. pycharm安装第三方库

    https://jingyan.baidu.com/article/4853e1e54b845e1909f7268f.html

  10. JDK 8中重要的函数式接口(必知必会)

    JDK 8 提供的重要函数式接口: Consumer (消费者) 功能:接收一个对象,返回void. 定义:void accept(T t) 默认方法:Consumer andThen(Consume ...