Java 调用Restful API接口的几种方式(HTTPS)
摘要:最近有一个需求,为客户提供一些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); } }
结果:
<?xml version="1.0" encoding="utf-8"?>
<token>rxitf9//7nxwxjs2cjijyhltvzunvmzxxeqtgn0u07sc9ysjeibpqte3hcjulskoxpeuyguveyi9jv7/wiklrzxykc3ospatsm0kcbckphu0tb2cn/nfzv9fmlueowfbdyz+n0seii9k+0gp7920dfencn17wujvmc0u2jwvm5fajqkmilwodxz6a0dq+d7dqdjwvcwxbvj2ilhyib3pr805vppmi9atxrvako0oda006wejfofcgyg5p70wpj5rrbl85vfy9wcvkd1r7j6nvjhxgh2gnimhkjejormjdxw2gkiusiwseli/xpswao7/ctwnwtnctgk8px2zub0zfa==</token>
二、httpurlconnection
三、spring的resttemplate
其它方式以后补充
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。