Java 調(diào)用Restful API接口的幾種方式(HTTPS)
摘要:最近有一個需求,為客戶提供一些Restful API 接口,QA使用postman進(jìn)行測試,但是postman的測試接口與java調(diào)用的相似但并不相同,于是想自己寫一個程序去測試Restful API接口,由于使用的是HTTPS,所以還要考慮到對于HTTPS的處理。由于我也是首次使用Java調(diào)用restful接口,所以還要研究一番,自然也是查閱了一些資料。
分析:這個問題與模塊之間的調(diào)用不同,比如我有兩個模塊front end 和back end,front end提供前臺展示,back end提供數(shù)據(jù)支持。之前使用過Hession去把back end提供的服務(wù)注冊成遠(yuǎn)程服務(wù),在front end端可以通過這種遠(yuǎn)程服務(wù)直接調(diào)到back end的接口。但這對于一個公司自己的一個項目耦合性比較高的情況下使用,沒有問題。但是如果給客戶注冊這種遠(yuǎn)程服務(wù),似乎不太好,耦合性太高。所以就考慮用一下方式進(jìn)行處理。
一、HttpClient
HttpClient大家也許比較熟悉但又比較陌生,熟悉是知道他可以遠(yuǎn)程調(diào)用比如請求一個URL,然后在response里獲取到返回狀態(tài)和返回信息,但是今天講的稍微復(fù)雜一點,因為今天的主題是HTTPS,這個牽涉到證書或用戶認(rèn)證的問題。
確定使用HttpClient之后,查詢相關(guān)資料,發(fā)現(xiàn)HttpClient的新版本與老版本不同,隨然兼容老版本,但已經(jīng)不提倡老版本是使用方式,很多都已經(jīng)標(biāo)記為過時的方法或類。今天就分別使用老版本4.2和最新版本4.5.3來寫代碼。
老版本4.2
需要認(rèn)證
在準(zhǔn)備證書階段選擇的是使用證書認(rèn)證
package com.darren.test.https.v42;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import org.apache.http.conn.ssl.SSLSocketFactory;
public class HTTPSCertifiedClient extends HTTPSClient {
public HTTPSCertifiedClient() {
}
@Override
public void prepareCertificate() throws Exception {
// 獲得密匙庫
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(
new File("C:/Users/zhda6001/Downloads/software/xxx.keystore"));
// FileInputStream instream = new FileInputStream(new File("C:/Users/zhda6001/Downloads/xxx.keystore"));
// 密匙庫的密碼
trustStore.load(instream, "password".toCharArray());
// 注冊密匙庫
this.socketFactory = new SSLSocketFactory(trustStore);
// 不校驗域名
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
}
跳過認(rèn)證
在準(zhǔn)備證書階段選擇的是跳過認(rèn)證
package com.darren.test.https.v42;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
public class HTTPSTrustClient extends HTTPSClient {
public HTTPSTrustClient() {
}
@Override
public void prepareCertificate() throws Exception {
// 跳過證書驗證
SSLContext ctx = SSLContext.getInstance("TLS");
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;
}
};
// 設(shè)置成已信任的證書
ctx.init(null, new TrustManager[] { tm }, null);
// 穿件SSL socket 工廠,并且設(shè)置不檢查host名稱
this.socketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
}
總結(jié)
現(xiàn)在發(fā)現(xiàn)這兩個類都繼承了同一個類HTTPSClient,并且HTTPSClient繼承了DefaultHttpClient類,可以發(fā)現(xiàn),這里使用了模板方法模式。
package com.darren.test.https.v42;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
public abstract class HTTPSClient extends DefaultHttpClient {
protected SSLSocketFactory socketFactory;
/**
* 初始化HTTPSClient
*
* @return 返回當(dāng)前實例
* @throws Exception
*/
public HTTPSClient init() throws Exception {
this.prepareCertificate();
this.regist();
return this;
}
/**
* 準(zhǔn)備證書驗證
*
* @throws Exception
*/
public abstract void prepareCertificate() throws Exception;
/**
* 注冊協(xié)議和端口, 此方法也可以被子類重寫
*/
protected void regist() {
ClientConnectionManager ccm = this.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, socketFactory));
}
}
下邊是工具類
package com.darren.test.https.v42;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class HTTPSClientUtil {
private static final String DEFAULT_CHARSET = "UTF-8";
public static String doPost(HTTPSClient httpsClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody) throws Exception {
return doPost(httpsClient, url, paramHeader, paramBody, DEFAULT_CHARSET);
}
public static String doPost(HTTPSClient httpsClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody, String charset) throws Exception {
String result = null;
HttpPost httpPost = new HttpPost(url);
setHeader(httpPost, paramHeader);
setBody(httpPost, paramBody, charset);
HttpResponse response = httpsClient.execute(httpPost);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, charset);
}
}
return result;
}
public static String doGet(HTTPSClient httpsClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody) throws Exception {
return doGet(httpsClient, url, paramHeader, paramBody, DEFAULT_CHARSET);
}
public static String doGet(HTTPSClient httpsClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody, String charset) throws Exception {
String result = null;
HttpGet httpGet = new HttpGet(url);
setHeader(httpGet, paramHeader);
HttpResponse response = httpsClient.execute(httpGet);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, charset);
}
}
return result;
}
private static void setHeader(HttpRequestBase request, Map<String, String> paramHeader) {
// 設(shè)置Header
if (paramHeader != null) {
Set<String> keySet = paramHeader.keySet();
for (String key : keySet) {
request.addHeader(key, paramHeader.get(key));
}
}
}
private static void setBody(HttpPost httpPost, Map<String, String> paramBody, String charset) throws Exception {
// 設(shè)置參數(shù)
if (paramBody != null) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
Set<String> keySet = paramBody.keySet();
for (String key : keySet) {
list.add(new BasicNameValuePair(key, paramBody.get(key)));
}
if (list.size() > 0) {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
httpPost.setEntity(entity);
}
}
}
}
然后是測試類:
package com.darren.test.https.v42;
import java.util.HashMap;
import java.util.Map;
public class HTTPSClientTest {
public static void main(String[] args) throws Exception {
HTTPSClient httpsClient = null;
httpsClient = new HTTPSTrustClient().init();
//httpsClient = new HTTPSCertifiedClient().init();
String url = "https://1.2.6.2:8011/xxx/api/getToken";
//String url = "https://1.2.6.2:8011/xxx/api/getHealth";
Map<String, String> paramHeader = new HashMap<>();
//paramHeader.put("Content-Type", "application/json");
paramHeader.put("Accept", "application/xml");
Map<String, String> paramBody = new HashMap<>();
paramBody.put("client_id", "ankur.tandon.ap@xxx.com");
paramBody.put("client_secret", "P@ssword_1");
String result = HTTPSClientUtil.doPost(httpsClient, url, paramHeader, paramBody);
//String result = HTTPSClientUtil.doGet(httpsClient, url, null, null);
System.out.println(result);
}
}
返回信息:
<?xml version="1.0" encoding="utf-8"?>
<token>jkf8RL0sw+Skkflj8RbKI5hP1bEQK8PrCuTZPpBINqMYKRMxY1kWCjmCfT191Zpp88VV1aGHW8oYNWjEYS0axpLuGAX89ejCoWNbikCc1UvfyesXHLktcJqyUFiVjevhrEQxJPHncLQYWP+Xse5oD9X8vKFKk7InNTMRzQK7YBTZ/e3U7gswM/5cvAHFl6o9rEq9cWPXavZNohyvnXsohSzDo+BXAtXxa1xpEDLy/8h/UaP4n4dlZDJJ3B8t1Xh+CRRIoMOPxf7c5wKhHtOkEOeXW+xoPQKKSx5CKWwJpPuGIIFWF/PaqWg+JUOsVT7QGdPv8PMWJ9DwEwjTdxguDg==</token>
新版本4.5.3
需要認(rèn)證
package com.darren.test.https.v45;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.ssl.SSLContexts;
public class HTTPSCertifiedClient extends HTTPSClient {
public HTTPSCertifiedClient() {
}
@Override
public void prepareCertificate() throws Exception {
// 獲得密匙庫
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(
new File("C:/Users/zhda6001/Downloads/software/xxx.keystore"));
// FileInputStream instream = new FileInputStream(new File("C:/Users/zhda6001/Downloads/xxx.keystore"));
try {
// 密匙庫的密碼
trustStore.load(instream, "password".toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, TrustSelfSignedStrategy.INSTANCE)
.build();
this.connectionSocketFactory = new SSLConnectionSocketFactory(sslcontext);
}
}
跳過認(rèn)證
package com.darren.test.https.v45;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
public class HTTPSTrustClient extends HTTPSClient {
public HTTPSTrustClient() {
}
@Override
public void prepareCertificate() throws Exception {
// 跳過證書驗證
SSLContext ctx = SSLContext.getInstance("TLS");
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;
}
};
// 設(shè)置成已信任的證書
ctx.init(null, new TrustManager[] { tm }, null);
this.connectionSocketFactory = new SSLConnectionSocketFactory(ctx);
}
}
總結(jié)
package com.darren.test.https.v45;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
public abstract class HTTPSClient extends HttpClientBuilder {
private CloseableHttpClient client;
protected ConnectionSocketFactory connectionSocketFactory;
/**
* 初始化HTTPSClient
*
* @return 返回當(dāng)前實例
* @throws Exception
*/
public CloseableHttpClient init() throws Exception {
this.prepareCertificate();
this.regist();
return this.client;
}
/**
* 準(zhǔn)備證書驗證
*
* @throws Exception
*/
public abstract void prepareCertificate() throws Exception;
/**
* 注冊協(xié)議和端口, 此方法也可以被子類重寫
*/
protected void regist() {
// 設(shè)置協(xié)議http和https對應(yīng)的處理socket鏈接工廠的對象
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", this.connectionSocketFactory)
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
// 創(chuàng)建自定義的httpclient對象
this.client = HttpClients.custom().setConnectionManager(connManager).build();
// CloseableHttpClient client = HttpClients.createDefault();
}
}
工具類:
package com.darren.test.https.v45;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class HTTPSClientUtil {
private static final String DEFAULT_CHARSET = "UTF-8";
public static String doPost(HttpClient httpClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody) throws Exception {
return doPost(httpClient, url, paramHeader, paramBody, DEFAULT_CHARSET);
}
public static String doPost(HttpClient httpClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody, String charset) throws Exception {
String result = null;
HttpPost httpPost = new HttpPost(url);
setHeader(httpPost, paramHeader);
setBody(httpPost, paramBody, charset);
HttpResponse response = httpClient.execute(httpPost);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, charset);
}
}
return result;
}
public static String doGet(HttpClient httpClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody) throws Exception {
return doGet(httpClient, url, paramHeader, paramBody, DEFAULT_CHARSET);
}
public static String doGet(HttpClient httpClient, String url, Map<String, String> paramHeader,
Map<String, String> paramBody, String charset) throws Exception {
String result = null;
HttpGet httpGet = new HttpGet(url);
setHeader(httpGet, paramHeader);
HttpResponse response = httpClient.execute(httpGet);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, charset);
}
}
return result;
}
private static void setHeader(HttpRequestBase request, Map<String, String> paramHeader) {
// 設(shè)置Header
if (paramHeader != null) {
Set<String> keySet = paramHeader.keySet();
for (String key : keySet) {
request.addHeader(key, paramHeader.get(key));
}
}
}
private static void setBody(HttpPost httpPost, Map<String, String> paramBody, String charset) throws Exception {
// 設(shè)置參數(shù)
if (paramBody != null) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
Set<String> keySet = paramBody.keySet();
for (String key : keySet) {
list.add(new BasicNameValuePair(key, paramBody.get(key)));
}
if (list.size() > 0) {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
httpPost.setEntity(entity);
}
}
}
}
測試類:
package com.darren.test.https.v45;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.client.HttpClient;
public class HTTPSClientTest {
public static void main(String[] args) throws Exception {
HttpClient httpClient = null;
//httpClient = new HTTPSTrustClient().init();
httpClient = new HTTPSCertifiedClient().init();
String url = "https://1.2.6.2:8011/xxx/api/getToken";
//String url = "https://1.2.6.2:8011/xxx/api/getHealth";
Map<String, String> paramHeader = new HashMap<>();
paramHeader.put("Accept", "application/xml");
Map<String, String> paramBody = new HashMap<>();
paramBody.put("client_id", "ankur.tandon.ap@xxx.com");
paramBody.put("client_secret", "P@ssword_1");
String result = HTTPSClientUtil.doPost(httpClient, url, paramHeader, paramBody);
//String result = HTTPSClientUtil.doGet(httpsClient, url, null, null);
System.out.println(result);
}
}
結(jié)果:
<?xml version="1.0" encoding="utf-8"?>
<token>RxitF9//7NxwXJS2cjIjYhLtvzUNvMZxxEQtGN0u07sC9ysJeIbPqte3hCjULSkoXPEUYGUVeyI9jv7/WikLrzxYKc3OSpaTSM0kCbCKphu0TB2Cn/nfzv9fMLueOWFBdyz+N0sEiI9K+0Gp7920DFEncn17wUJVmC0u2jwvM5FAjQKmilwodXZ6a0Dq+D7dQDJwVcwxBvJ2ilhyIb3pr805Vppmi9atXrVAKO0ODa006wEJFOfcgyG5p70wpJ5rrBL85vfy9WCvkd1R7j6NVjhXgH2gNimHkjEJorMjdXW2gKiUsiWsELi/XPswao7/CTWNwTnctGK8PX2ZUB0ZfA==</token>
二、HttpURLConnection
三、Spring的RestTemplate
其它方式以后補(bǔ)充
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis?ofType和javaType的區(qū)別說明
這篇文章主要介紹了MyBatis?ofType和javaType的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Java整數(shù)和字符串相互轉(zhuǎn)化實例詳解
這篇文章主要介紹了Java整數(shù)和字符串相互轉(zhuǎn)化實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-02-02
Spring AI Alibaba接入大模型時的依賴問題小結(jié)
文章介紹了如何在pom.xml文件中配置SpringAI Alibaba依賴,并提供了一個示例pom.xml文件,同時,建議將Maven倉庫鏡像設(shè)置為阿里云以提高下載速度,具體配置方法跟隨小編一起學(xué)習(xí)下吧2025-02-02
springboot如何使用@ConfigurationProperties封裝配置文件
springboot如何使用@ConfigurationProperties封裝配置文件的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringCloud網(wǎng)關(guān)Gateway架構(gòu)解析
這篇文章主要介紹了SpringCloud網(wǎng)關(guān)Gateway架構(gòu)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03

