1. 引入httpclient依赖

首先,需要确认项目中是否已引入过httpclient依赖,如果没有引入过,需要在pom.xml中添加以下代码引入httpclient依赖:

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

2. 发送GET请求

2.1 发送GET请求(无参数)

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doGet() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet("https://www.example.com/getDataList"); try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

2.2 发送GET请求(带参数)

第一种方法是直接在url上拼接上参数,如下所示:

HttpGet httpGet = new HttpGet("https://www.example.com/getDataList?pageIndex=1&pageSize=20");

第二种方法是使用URIBuilder添加参数,如下所示:

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doGet() throws IOException, URISyntaxException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { URIBuilder uriBuilder = new URIBuilder("https://www.example.com/getDataList");
uriBuilder.addParameter("pageIndex", "1");
uriBuilder.addParameter("pageSize", "20"); HttpGet httpGet = new HttpGet(uriBuilder.build()); try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

3. 发送POST请求

3.1 发送POST请求(无参数)

import org.apache.http.HttpStatus;
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.util.EntityUtils; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doPost() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost("https://www.example.com/updateData"); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

3.2 发送POST请求(带参数、form表单方式)

import org.apache.http.HttpStatus;
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; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List; public class HttpClientUtils {
public static String doPost() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost("https://www.example.com/updateData"); List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("id", "1"));
params.add(new BasicNameValuePair("name", "新名字")); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
httpPost.setEntity(formEntity); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

3.3 发送POST请求(带参数、json方式)

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
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; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doPost() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost("https://www.example.com/updateData"); String jsonBody = "{\"id\":\"1\",\"name\":新名字}";
StringEntity stringEntity = new StringEntity(jsonBody);
stringEntity.setContentType("application/json;charset=utf-8");
httpPost.setEntity(stringEntity); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

4. 发送PUT请求

4.1 发送PUT请求(无参数)

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doPut() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPut httpPut = new HttpPut("https://www.example.com/updateData"); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPut)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

4.2 发送PUT请求(带参数、form表单方式)

import org.apache.http.HttpStatus;
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.HttpPut;
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; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List; public class HttpClientUtils {
public static String doPut() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPut httpPut = new HttpPut("https://www.example.com/updateData"); List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("id", "1"));
params.add(new BasicNameValuePair("name", "新名字")); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
httpPut.setEntity(formEntity); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPut)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

4.3 发送PUT请求(带参数、json方式)

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
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; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doPut() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPut httpPut = new HttpPut("https://www.example.com/updateData"); String jsonBody = "{\"id\":\"1\",\"name\":新名字}";
StringEntity stringEntity = new StringEntity(jsonBody);
stringEntity.setContentType("application/json;charset=utf-8");
httpPut.setEntity(stringEntity); try (CloseableHttpResponse httpResponse = httpClient.execute(httpPut)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

5. 发送DELETE请求

5.1 发送DELETE请求(无参数)

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import java.io.IOException;
import java.nio.charset.StandardCharsets; public class HttpClientUtils {
public static String doDelete() throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpDelete httpDelete = new HttpDelete("https://www.example.com/updateData"); try (CloseableHttpResponse httpResponse = httpClient.execute(httpDelete)) {
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
} return null;
}
}
}
}

6. 添加请求头

一般情况下,请求第三方接口都需要签名、时间戳等请求头,以POST请求为例,添加请求头的代码如下所示:

httpPost.setHeader("Content-Type", "application/json;charset=utf-8");
httpPost.setHeader("signature", "3045022100875efcef9eb54626bb0168a6baa7c61265d0001d49243f");
httpPost.setHeader("timestamp", String.valueOf(System.currentTimeMillis()));

GET请求、PUT请求、DELETE请求添加请求头的方法同上。

7. 超时时间设置

如果需要自定义HTTP请求的连接超时时间和数据传输超时时间,代码如下所示(以POST请求为例):

RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(10000)
.build();
httpPost.setConfig(requestConfig);

GET请求、PUT请求、DELETE请求设置超时时间的方法同上。

8.工具类封装

完整的工具类代码如下所示:

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
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.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
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; import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; public class HttpClientUtils {
/**
* 连接建立超时时间(单位:毫秒)
*/
private static final int CONNECT_TIMEOUT = 5000; /**
* 数据传输超时时间(单位:毫秒)
*/
private static final int SOCKET_TIMEOUT = 10000; /**
* 执行GET请求
*
* @param url 请求地址
* @param headers 请求头
* @return 响应内容字符串
*/
public static String doGet(String url, Map<String, String> headers) throws IOException {
HttpGet httpGet = new HttpGet(url); // 设置请求头
setHeaders(httpGet, headers); return executeRequest(httpGet);
} /**
* 执行GET请求
*
* @param url 请求地址
* @param headers 请求头
* @param params 请求参数
* @return 响应内容字符串
*/
public static String doGet(String url, Map<String, String> headers, Map<String, String> params) throws IOException, URISyntaxException {
URIBuilder uriBuilder = new URIBuilder(url); // 设置请求参数
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
} HttpGet httpGet = new HttpGet(uriBuilder.build()); // 设置请求头
setHeaders(httpGet, headers); return executeRequest(httpGet);
} /**
* 执行POST请求(表单方式)
*
* @param url 请求地址
* @return 响应内容字符串
*/
public static String doPost(String url) throws IOException {
return doPost(url, null, null);
} /**
* 执行POST请求(表单方式)
*
* @param url 请求地址
* @param headers 请求头
* @return 响应内容字符串
*/
public static String doPost(String url, Map<String, String> headers) throws IOException {
return doPost(url, headers, null);
} /**
* 执行POST请求(表单方式)
*
* @param url 请求地址
* @param headers 请求头
* @param params 请求参数
* @return 响应内容字符串
*/
public static String doPost(String url, Map<String, String> headers, Map<String, String> params) throws IOException {
HttpPost httpPost = new HttpPost(url); // 设置请求头
setHeaders(httpPost, headers); // 构建表单参数
if (params != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) {
paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
httpPost.setEntity(new UrlEncodedFormEntity(paramList, StandardCharsets.UTF_8));
} return executeRequest(httpPost);
} /**
* 执行POST请求(JSON格式)
*
* @param url 请求地址
* @param headers 请求头
* @return 响应内容字符串
*/
public static String doPostJson(String url, Map<String, String> headers) throws IOException {
return doPostJson(url, headers, null);
} /**
* 执行POST请求(JSON格式)
*
* @param url 请求地址
* @param headers 请求头
* @param jsonBody JSON请求体字符串
* @return 响应内容字符串
*/
public static String doPostJson(String url, Map<String, String> headers, String jsonBody) throws IOException {
HttpPost httpPost = new HttpPost(url); // 添加JSON请求头
addJsonHeader(httpPost, headers);
// 添加自定义请求头
setHeaders(httpPost, headers); // 设置JSON请求体
if (jsonBody != null) {
StringEntity entity = new StringEntity(jsonBody,
ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
httpPost.setEntity(entity);
} return executeRequest(httpPost);
} /**
* 执行PUT请求(JSON格式)
*
* @param url 请求地址
* @param headers 请求头
* @param jsonBody JSON请求体字符串
* @return 响应内容字符串
*/
public static String doPut(String url, Map<String, String> headers, String jsonBody) throws IOException {
HttpPut httpPut = new HttpPut(url); // 添加JSON请求头
addJsonHeader(httpPut, headers);
// 添加自定义请求头
setHeaders(httpPut, headers); // 设置JSON请求体
if (jsonBody != null) {
StringEntity entity = new StringEntity(jsonBody,
ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
httpPut.setEntity(entity);
} return executeRequest(httpPut);
} /**
* 执行DELETE请求
*
* @param url 请求地址
* @param headers 请求头
* @return 响应内容字符串
*/
public static String doDelete(String url, Map<String, String> headers) throws IOException {
HttpDelete httpDelete = new HttpDelete(url); // 设置请求头
setHeaders(httpDelete, headers); return executeRequest(httpDelete);
} /**
* 创建带超时配置的HttpClient
*
* @return HttpClient实例
*/
private static CloseableHttpClient createHttpClient() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(CONNECT_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT)
.build(); return HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
} /**
* 添加JSON请求头
*
* @param httpRequest HTTP请求对象
* @param headers 请求头
*/
private static void addJsonHeader(HttpRequestBase httpRequest, Map<String, String> headers) {
if (headers == null || !headers.containsKey("Content-Type")) {
httpRequest.addHeader("Content-Type", "application/json;charset=utf-8");
}
} /**
* 设置请求头
*
* @param httpRequest HTTP请求对象
* @param headers 请求头
*/
private static void setHeaders(HttpRequestBase httpRequest, Map<String, String> headers) {
if (headers == null || headers.isEmpty()) {
return;
} for (Map.Entry<String, String> entry : headers.entrySet()) {
httpRequest.setHeader(entry.getKey(), entry.getValue());
}
} /**
* 统一执行请求并处理响应
*
* @param httpRequest HTTP请求对象
* @return 响应内容字符串
*/
private static String executeRequest(HttpRequestBase httpRequest) throws IOException {
try (CloseableHttpClient httpClient = createHttpClient()) {
try (CloseableHttpResponse response = httpClient.execute(httpRequest)) {
return handleResponse(response);
}
}
} /**
* 处理响应结果
*
* @param response HTTP响应对象
* @return 响应内容字符串
*/
private static String handleResponse(CloseableHttpResponse response) throws IOException {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new RuntimeException("HTTP请求失败,状态码:" + statusCode);
} HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toString(entity, StandardCharsets.UTF_8);
}
return null;
}
}

HttpClient使用方法总结及工具类封装的更多相关文章

  1. JavaFx 生成二维码工具类封装

    原文地址: JavaFx 生成二维码工具类封装 - Stars-One的杂货小窝 之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http- ...

  2. Redis操作Set工具类封装,Java Redis Set命令封装

    Redis操作Set工具类封装,Java Redis Set命令封装 >>>>>>>>>>>>>>>>& ...

  3. Redis操作List工具类封装,Java Redis List命令封装

    Redis操作List工具类封装,Java Redis List命令封装 >>>>>>>>>>>>>>>> ...

  4. Redis操作Hash工具类封装,Redis工具类封装

    Redis操作Hash工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>> ...

  5. (转载) 百度地图工具类封装(包括定位,附近、城市、范围poi检索,反地理编码)

    目录视图 摘要视图 订阅 赠书 | 异步2周年,技术图书免费选      程序员8月书讯      项目管理+代码托管+文档协作,开发更流畅 百度地图工具类封装(包括定位,附近.城市.范围poi检索, ...

  6. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战

    笔记 4.Redis工具类封装讲解和实战     简介:高效开发方式 Redis工具类封装讲解和实战         1.常用客户端 https://redisdesktop.com/download ...

  7. flink---实时项目--day02-----1. 解析参数工具类 2. Flink工具类封装 3. 日志采集架构图 4. 测流输出 5. 将kafka中数据写入HDFS 6 KafkaProducer的使用 7 练习

    1. 解析参数工具类(ParameterTool) 该类提供了从不同数据源读取和解析程序参数的简单实用方法,其解析args时,只能支持单只参数. 用来解析main方法传入参数的工具类 public c ...

  8. 关于TornadoFx和Android的全局配置工具类封装实现及思路解析

    原文地址: 关于TornadoFx和Android的全局配置工具类封装实现及思路解析 - Stars-One的杂货小窝 目前个人开发软件存在设置页面,可以让用户自定义些设置,但我发现,存储数据的代码逻 ...

  9. Redis操作字符串工具类封装,Redis工具类封装

    Redis操作字符串工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>>& ...

  10. Android Sqlite 工具类封装

    鉴于经常使用 Sqlite 数据库做数据持久化处理,进行了一点封装,方便使用. 该封装类主要支持一下功能 支持多用户数据储存 支持 Sqlite数据库升级 支持传入 Sql 语句建表 支持 SQLit ...

随机推荐

  1. JVM监控工具使用

    1. 描述 ​ 程序在开发过程中,有可能会发生CPU飙高.内存溢出等问题或系统在后期调优阶段,不可避免的要监控JVM情况,JDK自带的Jconsole监控工具,结合Tomcat使用非常方便,占用内存小 ...

  2. RPC框架的实现原理,及RPC架构组件详解

    RPC的由来 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小时, ...

  3. 第七章 (Nginx+Lua)Web开发实战商品详情页

    本章以京东商品详情页为例,京东商品详情页虽然仅是单个页面,但是其数据聚合源是非常多的,除了一些实时性要求比较高的如价格.库存.服务支持等通过AJAX异步加载加载之外,其他的数据都是在后端做数据聚合然后 ...

  4. linux:项目上线

    服务器选择 项目上线服务器必须是外网服务器 真实服务器 成本过高.多用于测试 云服务器 阿里云.腾讯云.百度云.华为云.盛大云.新浪云.亚马逊云等 官网:阿里云 1.注册/登录后 2.支付成功即可![ ...

  5. ABC243

    ABC224 D 题目大意 有一个九个点的无向图棋盘,上面有八个棋子,一次操作能将一个棋子沿边移到空点上,问将每个棋子移到与它编号相同的点最少几步. 解题思路 考虑使用 BFS. 用 string 存 ...

  6. NAT原理:概念、使用场景、转发流程及规则

    本文分享自天翼云开发者社区<NAT原理:概念.使用场景.转发流程及规则>,作者:x****n 网络地址转换(NAT)是一种在计算机网络中将一个网络的IP地址转换为另一个网络的IP地址的技术 ...

  7. 释放全球互连的数字潜力!MWC 2024云网高峰论坛召开,中国电信天翼云扬帆起航!

    2月27日,在2024年世界移动通信大会(MWC 2024)期间,中国电信云网高峰论坛顺利召开.本次论坛以"释放全球互连的数字潜力"为主题,汇聚全球多个国家和地区的通信业领袖和重量 ...

  8. go的math/rand随机数生成器

    伪随机数生成器,默认情况下随机数种子是固定的, 注意:固定的随机数种子每次生成的随机数都是相同的随机数序列 一.基础用法 math/rand 包提供了随机数生成的方法.常用的函数包括: rand.In ...

  9. Q:查看服务器内存和cpu占用排名

    pid 表示进程 ID,cmd 表示进程命令行,%mem 表示进程占用内存百分比,%cpu 表示进程占用 CPU 百分比,--sort=-%mem 表示按照内存占用率从高到低排序. 1.内存占比排序 ...

  10. Flink同步mysql写入Iceberg异常,一秒写入一次

    1.现象 在Iceberg数据湖治理过程中发现,同步任务运行7天没有写入数据,运行7天后突然大批量产生Commit,一秒产生一个Commit. 2.问题 Flink写入checkpoint时会在che ...