摘要:最近有一个需求,为客户提供一些Restful API 接口,QA使用postman进行测试,但是postman的测试接口与java调用的相似但并不相同,于是想自己写一个程序去测试Restful API接口,由于使用的是HTTPS,所以还要考虑到对于HTTPS的处理。由于我也是首次使用Java调用restful接口,所以还要研究一番,自然也是查阅了一些资料。

分析:这个问题与模块之间的调用不同,比如我有两个模块front end 和back end,front end提供前台展示,back end提供数据支持。之前使用过Hession去把back end提供的服务注册成远程服务,在front end端可以通过这种远程服务直接调到back end的接口。但这对于一个公司自己的一个项目耦合性比较高的情况下使用,没有问题。但是如果给客户注册这种远程服务,似乎不太好,耦合性太高。所以就考虑用一下方式进行处理。

一、HttpClient

HttpClient大家也许比较熟悉但又比较陌生,熟悉是知道他可以远程调用比如请求一个URL,然后在response里获取到返回状态和返回信息,但是今天讲的稍微复杂一点,因为今天的主题是HTTPS,这个牵涉到证书或用户认证的问题。

确定使用HttpClient之后,查询相关资料,发现HttpClient的新版本与老版本不同,随然兼容老版本,但已经不提倡老版本是使用方式,很多都已经标记为过时的方法或类。今天就分别使用老版本4.2和最新版本4.5.3来写代码。

老版本4.2

需要认证

在准备证书阶段选择的是使用证书认证

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);
}
}

跳过认证

在准备证书阶段选择的是跳过认证

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;
}
};
// 设置成已信任的证书
ctx.init(null, new TrustManager[] { tm }, null);
// 穿件SSL socket 工厂,并且设置不检查host名称
this.socketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
}

总结

现在发现这两个类都继承了同一个类HTTPSClient,并且HTTPSClient继承了DefaultHttpClient类,可以发现,这里使用了模板方法模式。

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 返回当前实例
* @throws Exception
*/
public HTTPSClient init() throws Exception {
this.prepareCertificate();
this.regist(); return this;
} /**
* 准备证书验证
*
* @throws Exception
*/
public abstract void prepareCertificate() throws Exception; /**
* 注册协议和端口, 此方法也可以被子类重写
*/
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) {
// 设置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 {
// 设置参数
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

需要认证

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);
} }

跳过认证

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;
}
};
// 设置成已信任的证书
ctx.init(null, new TrustManager[] { tm }, null);
this.connectionSocketFactory = new SSLConnectionSocketFactory(ctx);
}
}

总结

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 返回当前实例
* @throws Exception
*/
public CloseableHttpClient init() throws Exception {
this.prepareCertificate();
this.regist(); return this.client;
} /**
* 准备证书验证
*
* @throws Exception
*/
public abstract void prepareCertificate() throws Exception; /**
* 注册协议和端口, 此方法也可以被子类重写
*/
protected void regist() {
// 设置协议http和https对应的处理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); // 创建自定义的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) {
// 设置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 {
// 设置参数
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);
} }

结果:

二、HttpURLConnection

三、Spring的RestTemplate

其它方式以后补充

参考:

JAVA利用HttpClient进行POST请求(HTTPS)

CloseableHttpClient加载证书来访问https网站

Java 调用Restful API接口的几种方式--HTTPS的更多相关文章

  1. java调用CXF WebService接口的两种方式

    通过http://localhost:7002/card/services/HelloWorld?wsdl访问到xml如下,说明接口写对了. 2.静态调用 // 创建WebService客户端代理工厂 ...

  2. Python调用API接口的几种方式 数据库 脚本

    Python调用API接口的几种方式 2018-01-08 gaoeb97nd... 转自 one_day_day... 修改 微信分享: 相信做过自动化运维的同学都用过API接口来完成某些动作.AP ...

  3. Python调用API接口的几种方式

    Python调用API接口的几种方式 相信做过自动化运维的同学都用过API接口来完成某些动作.API是一套成熟系统所必需的接口,可以被其他系统或脚本来调用,这也是自动化运维的必修课. 本文主要介绍py ...

  4. Java调用.NET webservice方法的几种方式

    最近做项目,涉及到web-service调用,现学了一个星期,现简单的做一个小结.下面实现的是对传喜物流系统(http://vip.cxcod.com/PodApi/GetPodStr.asmx?ws ...

  5. java调用wsdl xfire和cxf两种方式

    xfire 如下: String spID = ""; String password = ""; String accessCode = "&quo ...

  6. SpringMVC Restful api接口实现

    [前言] 面向资源的 Restful 风格的 api 接口本着简洁,资源,便于扩展,便于理解等等各项优势,在如今的系统服务中越来越受欢迎. .net平台有WebAPi项目是专门用来实现Restful ...

  7. Http下的各种操作类.WebApi系列~通过HttpClient来调用Web Api接口

    1.WebApi系列~通过HttpClient来调用Web Api接口 http://www.cnblogs.com/lori/p/4045413.html HttpClient使用详解(java版本 ...

  8. Java调用第三方http接口的方式

    1. 概述 在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适.很多项目都会封装规定好本身项目的接口规范,所以大多数需要去调用对方提供的接口或第三方接口(短信.天气等). 在J ...

  9. 整合swagger2生成Restful Api接口文档

    整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...

随机推荐

  1. iOS 学习 - 17.Socket

    Socket 是应用层与 TCP / IP 协议通信的中间软件抽象层,它是一组接口   TCP:面向连接.传输可靠(保证数据正确性,保证数据顺序).用于传输大量数据(流模式).速度慢,建立连接需要开销 ...

  2. sql 泡沫 或者 递归查询

    if object_id('[tb]') is not null drop table [tb] go ),parentid int) insert [tb] ,N union all ,N unio ...

  3. angularJS快速入门

    1.引入脚本文件 <link rel="stylesheet" href="http://lib.sinaapp.com/js/bootstrap/v3.0.0/c ...

  4. using namespace cocos2d;

    忘记在头文件添加using namespace cocos2d; 导致一直出现问题,定义的精灵却一直报错. error C2143: 语法错误 : 缺少“;”(在“*”的前面)

  5. [QML] Connections元素介绍

    一个Connections对象创建一个了一个QML信号的连接.在QML中,我们连接信号通常是用使用"on<Signal>"来处理的,如下所示: MouseArea { ...

  6. spring整合mybatis(hibernate)配置

    一.Spring整合配置Mybatis spring整合mybatis可以不需要mybatis-config.xml配置文件,直接通过spring配置文件一步到位.一般需要具备如下几个基本配置. 1. ...

  7. 【转载】CSS3 文字溶解效果

    代码如下: <!DOCTYPE html> <html > <head> <meta charset="UTF-8"> <ti ...

  8. Prism框架研究(一)

    从今天起开始写一个Prism框架的学习博客,今天是第一篇,所以从最基本的一些概念开始学习这个基于MVVM的框架的学习,首先看一下Prism代表什么,这里引用一下比较官方的英文解释来看一下:Prism ...

  9. CodeForces 433C Ryouko&#39;s Memory Note (中位数定理)

    <题目链接> 题目大意:给你一堆数字,允许你修改所有相同的数字成为别的数字,不过只能修改一次,问你修改后序列相邻数字的距离和最小是多少. 解题分析: 首先,修改不是任意的,否则那样情况太多 ...

  10. JMeter—定时器(八)

    参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第三节定时器 JMeter中的定时器一般用来设置延迟与同步.定时器的执行优先级高于取样器,在同一作用域下有多个定 ...