浅谈java调用Restful API接口的方式
摘要:最近有一个需求,为客户提供一些restfulapi接口,qa使用postman进行测试,但是postman的测试接口与java调用的相似但并不相同,于是想自己写一个程序去测试restfulapi接口,由于使用的是https,所以还要考虑到对于https的处理。由于我也是首次使用java调用restful接口,所以还要研究一番,自然也是查阅了一些资料。
分析:这个问题与模块之间的调用不同,比如我有两个模块frontend和backend,frontend提供前台展示,backend提供数据支持。之前使用过hession去把backend提供的服务注册成远程服务,在frontend端可以通过这种远程服务直接调到backend的接口。但这对于一个公司自己的一个项目耦合性比较高的情况下使用,没有问题。但是如果给客户注册这种远程服务,似乎不太好,耦合性太高。所以就考虑用一下方式进行处理。
基本介绍
restful接口的调用,前端一般使用ajax调用,后端可以使用的方法比较多,
本次介绍三种:
1.httpurlconnection实现
2.httpclient实现
3.spring的resttemplate
一、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
@controller public class restfulaction { @autowired private userservice userservice; // 修改 @requestmapping(value = "put/{param}", method = requestmethod.put) public @responsebody string put(@pathvariable string param) { return "put:" + param; } // 新增 @requestmapping(value = "post/{param}", method = requestmethod.post) public @responsebody string post(@pathvariable string param,string id,string name) { system.out.println("id:"+id); system.out.println("name:"+name); return "post:" + param; } // 删除 @requestmapping(value = "delete/{param}", method = requestmethod.delete) public @responsebody string delete(@pathvariable string param) { return "delete:" + param; } // 查找 @requestmapping(value = "get/{param}", method = requestmethod.get) public @responsebody string get(@pathvariable string param) { return "get:" + param; } // httpurlconnection 方式调用restful接口 // 调用接口 @requestmapping(value = "dealcon/{param}") public @responsebody string dealcon(@pathvariable string param) { try { string url = "http://localhost:8080/tao-manager-web/"; url+=(param+"/xxx"); url restserviceurl = new url(url); httpurlconnection httpconnection = (httpurlconnection) restserviceurl .openconnection(); //param 输入小写,转换成 get post delete put httpconnection.setrequestmethod(param.touppercase()); // httpconnection.setrequestproperty("accept", "application/json"); if("post".equals(param)){ //打开输出开关 httpconnection.setdooutput(true); // httpconnection.setdoinput(true); //传递参数 string input = "&id="+ urlencoder.encode("abc", "utf-8"); input+="&name="+ urlencoder.encode("啊啊啊", "utf-8"); outputstream outputstream = httpconnection.getoutputstream(); outputstream.write(input.getbytes()); outputstream.flush(); } if (httpconnection.getresponsecode() != 200) { throw new runtimeexception( "http get request failed with error code : " + httpconnection.getresponsecode()); } bufferedreader responsebuffer = new bufferedreader( new inputstreamreader((httpconnection.getinputstream()))); string output; system.out.println("output from server: \n"); while ((output = responsebuffer.readline()) != null) { system.out.println(output); } httpconnection.disconnect(); } catch (malformedurlexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } return "success"; } }
三、spring的resttemplate
springmvc.xml增加
<!-- 配置resttemplate --> <!--http client factory --> <bean id="httpclientfactory" class="org.springframework.http.client.simpleclienthttprequestfactory"> <property name="connecttimeout" value="10000" /> <property name="readtimeout" value="10000" /> </bean> <!--resttemplate --> <bean id="resttemplate" class="org.springframework.web.client.resttemplate"> <constructor-arg ref="httpclientfactory" /> </bean>
controller
@controller public class resttemplateaction { @autowired private resttemplate template; @requestmapping("resttem") public @responsebody user resttem(string method) { user user = null; //查找 if ("get".equals(method)) { user = template.getforobject( "http://localhost:8080/tao-manager-web/get/{id}", user.class, "呜呜呜呜"); //getforentity与getforobject的区别是可以获取返回值和状态、头等信息 responseentity<user> re = template. getforentity("http://localhost:8080/tao-manager-web/get/{id}", user.class, "呜呜呜呜"); system.out.println(re.getstatuscode()); system.out.println(re.getbody().getusername()); //新增 } else if ("post".equals(method)) { httpheaders headers = new httpheaders(); headers.add("x-auth-token", uuid.randomuuid().tostring()); multivaluemap<string, string> postparameters = new linkedmultivaluemap<string, string>(); postparameters.add("id", "啊啊啊"); postparameters.add("name", "部版本"); httpentity<multivaluemap<string, string>> requestentity = new httpentity<multivaluemap<string, string>>( postparameters, headers); user = template.postforobject( "http://localhost:8080/tao-manager-web/post/aaa", requestentity, user.class); //删除 } else if ("delete".equals(method)) { template.delete("http://localhost:8080/tao-manager-web/delete/{id}","aaa"); //修改 } else if ("put".equals(method)) { template.put("http://localhost:8080/tao-manager-web/put/{id}",null,"bbb"); } return user; } }
以上就是本文关于浅谈java调用restful api接口的方式的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他java相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!