📚专栏
「Java数据集成」专栏
- 《Java发起HTTP请求并解析JSON返回数据》:下图简称为《请求和解析》
- 《基于MyBatis实现依次、批量、分页增删改查操作》:下图简称为《依批分增删改查》
- 《用Python根据JSON生成Java类代码和数据库建表SQL语句》:下图简称为《生成代码脚本》
- 《基于SpringBoot+MyBatis的数据增删改查模板》:下图简称为《增删改查模板》
- 《Java发起同异步HTTP请求和处理数据》:下图简称为《同异步请求和处理》
- 《基于SpringBoot+MyBatis的数据集成模板》:下图简称为《数据集成模板》
- 《JavaHTTP请求工具类HTTPUtils》:下图简称为《HTTP请求工具类》
- 《JavaJSON处理工具类JSONUtils》:下图简称为《JSON处理工具类》
- 《JavaXML处理工具类XMLUtils》:下图简称为《XML处理工具类》
- 《用Python生成随机JSON数据》:下图简称为《生成随机数据脚本》
💬相关
http 协议
https://www.cnblogs.com/mqy1/p/13884964.html
💬相关
本文进阶的博客文章《Java发起同异步HTTP请求和处理数据》,看完本文后感兴趣可以再查看
https://blog.csdn.net/weixin_42077074/article/details/129601132
发起 HTTP 请求并获得返回信息
在 requestHTTPContent()
函数中借助 HttpURLConnection
类实现发送请求
📑来源
代码改进自博客《JAVA如何调用对方http接口得到返回数据》
https://cloud.tencent.com/developer/article/2081582
public static String requestHTTPContent(String strURL, String method) throws Exception {
URL url = new URL(strURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
// 设置请求方法,为 "GET" 或 "POST"
// GET 请求只能传 query 参数,query 参数都是拼在请求地址上的
// POST 可以传 body 和 query 两种形式的参数
httpConn.setRequestMethod(method);
// 请求时是否使用缓存
httpConn.setUseCaches(false);
// POST 请求必须设置下面两项
// 设置是否从 HttpUrlConnection 的对象写
httpConn.setDoOutput(true);
// 设置是否从 HttpUrlConnection 的对象读入
httpConn.setDoInput(true);
httpConn.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
httpConn.disconnect();
String res = buffer.toString();
// 输出字符串形式的返回数据
System.out.println(res);
return res;
}
添加 HTTP 请求头
根据需求决定是否需要
- 设置接受内容类型
- 设置发送内容类型
- 设置编码方式(字符集)
- 添加自定义请求头
添加请求头在下面方法二选一
直接添加请求头
在前文 HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
和 httpConn.connect();
之间添加以下代码
此处以发送和接受内容均为 JSON 格式,UTF-8 编码方式为例
// 设置发送内容类型
httpConn.setRequestProperty("Content-Type","application/json;charset=UTF-8");
// 设置接收内容类型
httpConn.setRequestProperty("Accept","application/json");
// 设置编码方式(字符集)
httpConn.setRequestProperty("charset", "UTF-8");
// 添加自定义请求头,key 和 value 是你需要添加的头信息的键与值,如用于鉴权
httpConn.setRequestProperty(key,value);
注意,如果服务器的安全设置不接受 Java 程序作为客户端访问,则可以加上下面的代码
// 设置访问者系统引擎版本、浏览器信息的字段信息,此处伪装成用户通过浏览器访问
httpConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
借助 Map 添加请求头
如果复用率比较高的话,也可以考虑将请求头的键与值写进 Map 的对象里,Map 中键值对(key-value pair)被称作项(entry)
Map<String, String> headers = new HashMap<String, String>(){{
// 设置接收内容类型
put("Accept","application/json");
// 设置发送内容类型
put("Content-Type","application/json;charset=UTF-8");
// 设置字符集
put("charset", "UTF-8");
// 设置访问者系统引擎版本、浏览器信息的字段信息,此处伪装成用户通过浏览器访问
put("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 添加自定义请求头,key 和 value 是你需要添加的头信息的键与值,如用于鉴权
put(key,value);
}};
通过函数 addHeadersToRequest()
遍历 Map 的对象添加请求头
// 将请求头键值对添加到 HTTP 请求中
public static void addHeadersToRequest(HttpURLConnection httpConn, Map<String, ?> headers) {
if (headers != null) {
for (Map.Entry<String, ?> entry : headers.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value.getClass().isArray()) {
// 如果是数组类型,则遍历数组并添加请求头
for (Object v : (Object[]) value) {
httpConn.setRequestProperty(key, v.toString());
}
} else {
// 如果不是数组类型,则直接添加请求头
httpConn.setRequestProperty(key, value.toString());
}
}
}
}
忽略验证 HTTPS 中 SSL 证书
一般用于 SSL 证书失效,却又不得不以 HTTPS 去请求的情况,如报错 java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xxx.xxx.xxx found
在发起 HTTPS 请求前调用下文 disableSSLVerification()
函数
📑来源
代码源自博客
https://www.cnblogs.com/Springmoon-venn/p/7504901.html
// 禁用 SSL 验证
public static void disableSSLVerification() {
try {
// 创建不验证证书链的 TrustManager
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// 安装 TrustManager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// 创建验证所有主机名的 HostnameVerifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// 安装 HostnameVerifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
添加 query 请求参数
query 请求参数是拼接在请求 URL 上的,下面方法二选一
字符串拼接进 URL
如果想简单粗暴,则直接手敲含有请求参数的字符串,通过函数 concatParamsToURL()
直接拼接在 URL 字符串末尾
public String concatParamsToURL(String staticURL, String paramsStr) throws Exception {
return staticURL + paramsStr;
}
Map 键值对拼接进 URL
如果想将变量作为请求参数,则可以考虑将参数名和参数值放进 Map 的对象
// 无重复同名参数
Map<String, String> params1 = new HashMap<String, String>(){{
put("param1","value1");
put("param2","value2");
put("param3","value3");
}};
// 含重复同名参数,但一般不推荐
Map<String, String[]> params2 = new HashMap<String, String[]>(){{
put("param1",new String[]{"value11","value12"});
put("param2",new String[]{"value21","value22"});
put("param3",new String[]{"value31","value32"});
}};
通过函数 concatParamsToURL()
把参数拼接在 URL 字符串末尾
public static String concatParamsToURL(String staticURL, Map<String, ?> params) throws Exception {
// staticURL 是字符串形式的静态 URL
// params 键与值分别是参数名与参数值,URL 有重复同名参数时将多个值放进数组
// 判断参数是否为空
if (params.isEmpty()) {
return staticURL;
}
StringBuilder sb = new StringBuilder(staticURL);
// 判断 URL 中是否已经包含参数
boolean hasParams = staticURL.indexOf("?") != -1;
// 遍历参数
for (Map.Entry<String, ?> entry : params.entrySet()) {
String key = entry.getKey(); // 参数名
Object value = entry.getValue(); // 参数值
// 判断参数值是否为数组
if (value.getClass().isArray()) {
// 如果是数组,遍历数组并添加参数
for (Object v : (Object[]) value) {
sb.append(hasParams ? "&" : "?")
.append(URLEncoder.encode(key, "utf-8"))
.append("=")
.append(URLEncoder.encode(v.toString(), "utf-8"));
hasParams = true;
}
} else {
// 如果不是数组,直接添加参数
sb.append(hasParams ? "&" : "?")
.append(URLEncoder.encode(key, "utf-8"))
.append("=")
.append(URLEncoder.encode(value.toString(), "utf-8"));
hasParams = true;
}
}
return sb.toString();
}
添加 body 请求参数
此处以添加 JSON 形式的 body 请求参数为例,由于 JSON 不推荐出现重复键,因而此处暂时没有考虑重复同名参数的情况
💬相关
网页——Java 中 JSON 的使用,菜鸟教程
https://www.runoob.com/w3cnote/java-json-instro.html
需先在 Maven 的 pom.xml
加上依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
后在 Java 中引入包
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
body 请求参数只能使用 POST 方法进行请求,需要将前文的 httpConn.connect();
替换成下面的代码,二选一
手动生成 JSON 对象
如果想手动生成 JSON 对象,那么选这个
JSONObject paramsJSON = new JSONObject();
// 发送的 JSON 的属性与值
paramsJSON.put("attr1", "value1");
paramsJSON.put("attr2", "value2");
// 发送请求
OutputStream out = new DataOutputStream(httpConn.getOutputStream());
// getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
out.write(paramsJSON.toJSONString().getBytes("UTF-8"));
out.flush();
Map 对象转化成 JSON 对象
如果想将含有请求参数的 Map 的对象转化成 JSON 对象,那么选这个
// 发送的 JSON 对象的键与值
Map<String, String> paramsMap = new HashMap<String, String>(){{
put("attr1", "value1");
put("attr2", "value2");
}};
OutputStream out = new DataOutputStream(httpConn.getOutputStream());
// getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
out.write(JSON.toJSONString(paramsMap).getBytes("UTF-8"));
out.flush();
解析 JSON 字符串形式的返回数据
添加前文 JSON 所需的相关依赖,并在前文 String res = buffer.toString();
和 return res;
之间调用函数 printJSON()
,函数内解析 JSON 的三种方法自行视情况而选择
📑来源
代码改进自博客
https://blog.csdn.net/qq_43370892/article/details/114805511
public void printJSON(String jsonStr) {
// 给定字符串类型的JSON数据,如 {"code":"0","error":null,"message":"success","data":[{"x":"1","y":"2"},{"x":"3","y":"4"}]}
//先转换成 JSONObject 类型
JSONObject jsonObj = JSON.parseObject(jsonStr);
//1.全部输出,直接遍历 JSONObject 中的键与值
if(jsonObj != null) for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
//2.指定属性输出,通过 JSONObject 中的getString("key")方法,得到对应的值
if(jsonObj != null) System.out.println("message:"+jsonObj.getString("message"));
//3.指定属性输出,但属性含有数组的,下文以 data 为例
if(jsonObj != null){
JSONArray jsonInfo = JSONObject.parseArray(jsonObj.getString("data"));//将jsonObj解析成json数组
if(jsonInfo != null) for (int i = 0; i < jsonInfo.size(); i++) {//遍历数组
JSONObject jsonDetailInfo = jsonInfo.getJSONObject(i);//根据下标以此拿数据,每一个数组元素又是一个 JSONObject 对象,所以用JSONObject接收
String x = jsonDetailInfo.getString("x");
String y = jsonDetailInfo.getString("y");
//输出当前获取的数据
System.out.println("x="+x+";y="+y);
}
}
}
💬相关
更为详细的 JSON 处理方法可以查看博客文章《JavaJSON处理工具类JSONUtils》
https://blog.csdn.net/weixin_42077074/article/details/129364274
综合改进后的发起 HTTP 请求并获得返回信息
综合改进后的请求函数 requestHTTPContent()
,其中有调用前后文的
- 添加请求头函数:
addHeadersToRequest()
- 参数拼接函数:
concatParamsToURL()
- 忽略 SSL 验证函数:
disableSSLVerification()
- 读取函数:
readResponseContent()
- 输出函数:
outputResponseContent()
// 发起 HTTP 请求并获取响应内容
// 重载 requestHTTPContent(),相当于参数有默认值
public static String requestHTTPContent(String strURL) throws Exception {
return requestHTTPContent(strURL, "GET", null, null);
}
public static String requestHTTPContent(String strURL, String method) throws Exception {
return requestHTTPContent(strURL, method, null, null);
}
public static String requestHTTPContent(String strURL, String method, Map<String, ?> headers) throws Exception {
return requestHTTPContent(strURL, method, headers, null);
}
public static String requestHTTPContent(String strURL, String method, Map<String, ?> headers, Map<String, ?> params) throws Exception {
// strURL 是 String 类型的 URL
// method 是 String 类型的请求方法,为 "GET" 或 "POST"
// headers 键与值分别是请求头名与请求头值,有重复同名请求头时将多个值放进数组
// params 键与值分别是参数名与参数值,URL 有重复同名参数时将多个值放进数组
// 忽略验证 https 中 SSL 证书
disableSSLVerification();
// GET 方法下,query 参数拼接在 URL 字符串末尾
if(method.equals("GET") && params != null) {
strURL = concatParamsToURL(strURL, params);
}
System.out.println(strURL);
URL url = new URL(strURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod(method);
// 添加 HTTP 请求头
addHeadersToRequest(httpConn, headers);
// 请求时是否使用缓存
httpConn.setUseCaches(false);
// POST 方法请求必须设置下面两项
// 设置是否从 HttpUrlConnection 的对象写
httpConn.setDoOutput(true);
// 设置是否从 HttpUrlConnection 的对象读入
httpConn.setDoInput(true);
// 此处默认 POST 方法发送的内容就是 JSON 形式的 body 参数,可以自行更改
if(method.equals("POST") && params!=null) {
// 发送请求
OutputStream out = new DataOutputStream(httpConn.getOutputStream());
// getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
out.write(JSON.toJSONString(params).getBytes("UTF-8"));
out.flush();
}
else{
//发送请求
httpConn.connect();
}
String contentType = httpConn.getContentType();
String result = readResponseContent(httpConn);
// 输出响应内容
outputResponseContent(result, contentType);
return result;
}
// 读取响应内容
private static String readResponseContent(HttpURLConnection httpConn) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
return buffer.toString();
}
// 输出响应内容
public void outputResponseContent(String responseContent, String contentType){
// contentType 是接收内容类型,如"application/json"、"application/xml"、"text/html"、"text/plain"等,此处自定义输出方法
if(contentType.contains("application/json")){
JSONObject jsonObj = JSON.parseObject(responseContent);
if(jsonObj != null) for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
else{
System.out.println(responseContent);
}
}
💬相关
更为全面的输出响应内容函数可以查看博客文章《JavaHTTP请求工具类HTTPUtils》
https://blog.csdn.net/weixin_42077074/article/details/129625934