浅谈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
需要认证
在准备证书阶段选择的是使用证书认证
packagecom.darren.test.https.v42; importjava.io.File; importjava.io.FileInputStream; importjava.security.KeyStore; importorg.apache.http.conn.ssl.SSLSocketFactory; publicclassHTTPSCertifiedClientextendsHTTPSClient{ publicHTTPSCertifiedClient(){ } @Override publicvoidprepareCertificate()throwsException{ //获得密匙库 KeyStoretrustStore=KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStreaminstream=newFileInputStream( newFile("C:/Users/zhda6001/Downloads/software/xxx.keystore")); //FileInputStreaminstream=newFileInputStream(newFile("C:/Users/zhda6001/Downloads/xxx.keystore")); //密匙库的密码 trustStore.load(instream,"password".toCharArray()); //注册密匙库 this.socketFactory=newSSLSocketFactory(trustStore); //不校验域名 socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); } }
跳过认证
在准备证书阶段选择的是跳过认证
packagecom.darren.test.https.v42; importjava.security.cert.CertificateException; importjava.security.cert.X509Certificate; importjavax.net.ssl.SSLContext; importjavax.net.ssl.TrustManager; importjavax.net.ssl.X509TrustManager; importorg.apache.http.conn.ssl.SSLSocketFactory; publicclassHTTPSTrustClientextendsHTTPSClient{ publicHTTPSTrustClient(){ } @Override publicvoidprepareCertificate()throwsException{ //跳过证书验证 SSLContextctx=SSLContext.getInstance("TLS"); X509TrustManagertm=newX509TrustManager(){ @Override publicvoidcheckClientTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ } @Override publicvoidcheckServerTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ } @Override publicX509Certificate[]getAcceptedIssuers(){ returnnull; } } ; //设置成已信任的证书 ctx.init(null,newTrustManager[]{ tm } ,null); //穿件SSLsocket工厂,并且设置不检查host名称 this.socketFactory=newSSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); } }
总结
现在发现这两个类都继承了同一个类HTTPSClient,并且HTTPSClient继承了DefaultHttpClient类,可以发现,这里使用了模板方法模式。
packagecom.darren.test.https.v42; importorg.apache.http.conn.ClientConnectionManager; importorg.apache.http.conn.scheme.Scheme; importorg.apache.http.conn.scheme.SchemeRegistry; importorg.apache.http.conn.ssl.SSLSocketFactory; importorg.apache.http.impl.client.DefaultHttpClient; publicabstractclassHTTPSClientextendsDefaultHttpClient{ protectedSSLSocketFactorysocketFactory; /** *初始化HTTPSClient * *@return返回当前实例 *@throwsException */ publicHTTPSClientinit()throwsException{ this.prepareCertificate(); this.regist(); returnthis; } /** *准备证书验证 * *@throwsException */ publicabstractvoidprepareCertificate()throwsException; /** *注册协议和端口,此方法也可以被子类重写 */ protectedvoidregist(){ ClientConnectionManagerccm=this.getConnectionManager(); SchemeRegistrysr=ccm.getSchemeRegistry(); sr.register(newScheme("https",443,socketFactory)); } }
下边是工具类
packagecom.darren.test.https.v42; importjava.util.ArrayList; importjava.util.List; importjava.util.Map; importjava.util.Set; importorg.apache.http.HttpEntity; importorg.apache.http.HttpResponse; importorg.apache.http.NameValuePair; importorg.apache.http.client.entity.UrlEncodedFormEntity; importorg.apache.http.client.methods.HttpGet; importorg.apache.http.client.methods.HttpPost; importorg.apache.http.client.methods.HttpRequestBase; importorg.apache.http.message.BasicNameValuePair; importorg.apache.http.util.EntityUtils; publicclassHTTPSClientUtil{ privatestaticfinalStringDEFAULT_CHARSET="UTF-8"; publicstaticStringdoPost(HTTPSClienthttpsClient,Stringurl,MapparamHeader, Map paramBody)throwsException{ returndoPost(httpsClient,url,paramHeader,paramBody,DEFAULT_CHARSET); } publicstaticStringdoPost(HTTPSClienthttpsClient,Stringurl,Map paramHeader, Map paramBody,Stringcharset)throwsException{ Stringresult=null; HttpPosthttpPost=newHttpPost(url); setHeader(httpPost,paramHeader); setBody(httpPost,paramBody,charset); HttpResponseresponse=httpsClient.execute(httpPost); if(response!=null){ HttpEntityresEntity=response.getEntity(); if(resEntity!=null){ result=EntityUtils.toString(resEntity,charset); } } returnresult; } publicstaticStringdoGet(HTTPSClienthttpsClient,Stringurl,Map paramHeader, Map paramBody)throwsException{ returndoGet(httpsClient,url,paramHeader,paramBody,DEFAULT_CHARSET); } publicstaticStringdoGet(HTTPSClienthttpsClient,Stringurl,Map paramHeader, Map paramBody,Stringcharset)throwsException{ Stringresult=null; HttpGethttpGet=newHttpGet(url); setHeader(httpGet,paramHeader); HttpResponseresponse=httpsClient.execute(httpGet); if(response!=null){ HttpEntityresEntity=response.getEntity(); if(resEntity!=null){ result=EntityUtils.toString(resEntity,charset); } } returnresult; } privatestaticvoidsetHeader(HttpRequestBaserequest,Map paramHeader){ //设置Header if(paramHeader!=null){ Set keySet=paramHeader.keySet(); for(Stringkey:keySet){ request.addHeader(key,paramHeader.get(key)); } } } privatestaticvoidsetBody(HttpPosthttpPost,Map paramBody,Stringcharset)throwsException{ //设置参数 if(paramBody!=null){ List list=newArrayList (); Set keySet=paramBody.keySet(); for(Stringkey:keySet){ list.add(newBasicNameValuePair(key,paramBody.get(key))); } if(list.size()>0){ UrlEncodedFormEntityentity=newUrlEncodedFormEntity(list,charset); httpPost.setEntity(entity); } } } }
然后是测试类:
packagecom.darren.test.https.v42; importjava.util.HashMap; importjava.util.Map; publicclassHTTPSClientTest{ publicstaticvoidmain(String[]args)throwsException{ HTTPSClienthttpsClient=null; httpsClient=newHTTPSTrustClient().init(); //httpsClient=newHTTPSCertifiedClient().init(); Stringurl="https://1.2.6.2:8011/xxx/api/getToken"; //Stringurl="https://1.2.6.2:8011/xxx/api/getHealth"; MapparamHeader=newHashMap<>(); //paramHeader.put("Content-Type","application/json"); paramHeader.put("Accept","application/xml"); Map paramBody=newHashMap<>(); paramBody.put("client_id","ankur.tandon.ap@xxx.com"); paramBody.put("client_secret","P@ssword_1"); Stringresult=HTTPSClientUtil.doPost(httpsClient,url,paramHeader,paramBody); //Stringresult=HTTPSClientUtil.doGet(httpsClient,url,null,null); System.out.println(result); } }
返回信息:
jkf8RL0sw+Skkflj8RbKI5hP1bEQK8PrCuTZPpBINqMYKRMxY1kWCjmCfT191Zpp88VV1aGHW8oYNWjEYS0axpLuGAX89ejCoWNbikCc1UvfyesXHLktcJqyUFiVjevhrEQxJPHncLQYWP+Xse5oD9X8vKFKk7InNTMRzQK7YBTZ/e3U7gswM/5cvAHFl6o9rEq9cWPXavZNohyvnXsohSzDo+BXAtXxa1xpEDLy/8h/UaP4n4dlZDJJ3B8t1Xh+CRRIoMOPxf7c5wKhHtOkEOeXW+xoPQKKSx5CKWwJpPuGIIFWF/PaqWg+JUOsVT7QGdPv8PMWJ9DwEwjTdxguDg==
新版本4.5.3
需要认证
packagecom.darren.test.https.v45; importjava.io.File; importjava.io.FileInputStream; importjava.security.KeyStore; importjavax.net.ssl.SSLContext; importorg.apache.http.conn.ssl.SSLConnectionSocketFactory; importorg.apache.http.conn.ssl.TrustSelfSignedStrategy; importorg.apache.http.ssl.SSLContexts; publicclassHTTPSCertifiedClientextendsHTTPSClient{ publicHTTPSCertifiedClient(){ } @Override publicvoidprepareCertificate()throwsException{ //获得密匙库 KeyStoretrustStore=KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStreaminstream=newFileInputStream( newFile("C:/Users/zhda6001/Downloads/software/xxx.keystore")); //FileInputStreaminstream=newFileInputStream(newFile("C:/Users/zhda6001/Downloads/xxx.keystore")); try{ //密匙库的密码 trustStore.load(instream,"password".toCharArray()); } finally{ instream.close(); } SSLContextsslcontext=SSLContexts.custom().loadTrustMaterial(trustStore,TrustSelfSignedStrategy.INSTANCE) .build(); this.connectionSocketFactory=newSSLConnectionSocketFactory(sslcontext); } }
跳过认证
packagecom.darren.test.https.v45; importjava.security.cert.CertificateException; importjava.security.cert.X509Certificate; importjavax.net.ssl.SSLContext; importjavax.net.ssl.TrustManager; importjavax.net.ssl.X509TrustManager; importorg.apache.http.conn.ssl.SSLConnectionSocketFactory; publicclassHTTPSTrustClientextendsHTTPSClient{ publicHTTPSTrustClient(){ } @Override publicvoidprepareCertificate()throwsException{ //跳过证书验证 SSLContextctx=SSLContext.getInstance("TLS"); X509TrustManagertm=newX509TrustManager(){ @Override publicvoidcheckClientTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ } @Override publicvoidcheckServerTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ } @Override publicX509Certificate[]getAcceptedIssuers(){ returnnull; } } ; //设置成已信任的证书 ctx.init(null,newTrustManager[]{ tm } ,null); this.connectionSocketFactory=newSSLConnectionSocketFactory(ctx); } }
总结
packagecom.darren.test.https.v45; importorg.apache.http.config.Registry; importorg.apache.http.config.RegistryBuilder; importorg.apache.http.conn.socket.ConnectionSocketFactory; importorg.apache.http.conn.socket.PlainConnectionSocketFactory; importorg.apache.http.impl.client.CloseableHttpClient; importorg.apache.http.impl.client.HttpClientBuilder; importorg.apache.http.impl.client.HttpClients; importorg.apache.http.impl.conn.PoolingHttpClientConnectionManager; publicabstractclassHTTPSClientextendsHttpClientBuilder{ privateCloseableHttpClientclient; protectedConnectionSocketFactoryconnectionSocketFactory; /** *初始化HTTPSClient * *@return返回当前实例 *@throwsException */ publicCloseableHttpClientinit()throwsException{ this.prepareCertificate(); this.regist(); returnthis.client; } /** *准备证书验证 * *@throwsException */ publicabstractvoidprepareCertificate()throwsException; /** *注册协议和端口,此方法也可以被子类重写 */ protectedvoidregist(){ //设置协议http和https对应的处理socket链接工厂的对象 RegistrysocketFactoryRegistry=RegistryBuilder. create() .register("http",PlainConnectionSocketFactory.INSTANCE) .register("https",this.connectionSocketFactory) .build(); PoolingHttpClientConnectionManagerconnManager=newPoolingHttpClientConnectionManager(socketFactoryRegistry); HttpClients.custom().setConnectionManager(connManager); //创建自定义的httpclient对象 this.client=HttpClients.custom().setConnectionManager(connManager).build(); //CloseableHttpClientclient=HttpClients.createDefault(); } }
工具类:
packagecom.darren.test.https.v45; importjava.util.ArrayList; importjava.util.List; importjava.util.Map; importjava.util.Set; importorg.apache.http.HttpEntity; importorg.apache.http.HttpResponse; importorg.apache.http.NameValuePair; importorg.apache.http.client.HttpClient; importorg.apache.http.client.entity.UrlEncodedFormEntity; importorg.apache.http.client.methods.HttpGet; importorg.apache.http.client.methods.HttpPost; importorg.apache.http.client.methods.HttpRequestBase; importorg.apache.http.message.BasicNameValuePair; importorg.apache.http.util.EntityUtils; publicclassHTTPSClientUtil{ privatestaticfinalStringDEFAULT_CHARSET="UTF-8"; publicstaticStringdoPost(HttpClienthttpClient,Stringurl,MapparamHeader, Map paramBody)throwsException{ returndoPost(httpClient,url,paramHeader,paramBody,DEFAULT_CHARSET); } publicstaticStringdoPost(HttpClienthttpClient,Stringurl,Map paramHeader, Map paramBody,Stringcharset)throwsException{ Stringresult=null; HttpPosthttpPost=newHttpPost(url); setHeader(httpPost,paramHeader); setBody(httpPost,paramBody,charset); HttpResponseresponse=httpClient.execute(httpPost); if(response!=null){ HttpEntityresEntity=response.getEntity(); if(resEntity!=null){ result=EntityUtils.toString(resEntity,charset); } } returnresult; } publicstaticStringdoGet(HttpClienthttpClient,Stringurl,Map paramHeader, Map paramBody)throwsException{ returndoGet(httpClient,url,paramHeader,paramBody,DEFAULT_CHARSET); } publicstaticStringdoGet(HttpClienthttpClient,Stringurl,Map paramHeader, Map paramBody,Stringcharset)throwsException{ Stringresult=null; HttpGethttpGet=newHttpGet(url); setHeader(httpGet,paramHeader); HttpResponseresponse=httpClient.execute(httpGet); if(response!=null){ HttpEntityresEntity=response.getEntity(); if(resEntity!=null){ result=EntityUtils.toString(resEntity,charset); } } returnresult; } privatestaticvoidsetHeader(HttpRequestBaserequest,Map paramHeader){ //设置Header if(paramHeader!=null){ Set keySet=paramHeader.keySet(); for(Stringkey:keySet){ request.addHeader(key,paramHeader.get(key)); } } } privatestaticvoidsetBody(HttpPosthttpPost,Map paramBody,Stringcharset)throwsException{ //设置参数 if(paramBody!=null){ List list=newArrayList (); Set keySet=paramBody.keySet(); for(Stringkey:keySet){ list.add(newBasicNameValuePair(key,paramBody.get(key))); } if(list.size()>0){ UrlEncodedFormEntityentity=newUrlEncodedFormEntity(list,charset); httpPost.setEntity(entity); } } } }
测试类:
packagecom.darren.test.https.v45; importjava.util.HashMap; importjava.util.Map; importorg.apache.http.client.HttpClient; publicclassHTTPSClientTest{ publicstaticvoidmain(String[]args)throwsException{ HttpClienthttpClient=null; //httpClient=newHTTPSTrustClient().init(); httpClient=newHTTPSCertifiedClient().init(); Stringurl="https://1.2.6.2:8011/xxx/api/getToken"; //Stringurl="https://1.2.6.2:8011/xxx/api/getHealth"; MapparamHeader=newHashMap<>(); paramHeader.put("Accept","application/xml"); Map paramBody=newHashMap<>(); paramBody.put("client_id","ankur.tandon.ap@xxx.com"); paramBody.put("client_secret","P@ssword_1"); Stringresult=HTTPSClientUtil.doPost(httpClient,url,paramHeader,paramBody); //Stringresult=HTTPSClientUtil.doGet(httpsClient,url,null,null); System.out.println(result); } }
结果:
RxitF9//7NxwXJS2cjIjYhLtvzUNvMZxxEQtGN0u07sC9ysJeIbPqte3hCjULSkoXPEUYGUVeyI9jv7/WikLrzxYKc3OSpaTSM0kCbCKphu0TB2Cn/nfzv9fMLueOWFBdyz+N0sEiI9K+0Gp7920DFEncn17wUJVmC0u2jwvM5FAjQKmilwodXZ6a0Dq+D7dQDJwVcwxBvJ2ilhyIb3pr805Vppmi9atXrVAKO0ODa006wEJFOfcgyG5p70wpJ5rrBL85vfy9WCvkd1R7j6NVjhXgH2gNimHkjEJorMjdXW2gKiUsiWsELi/XPswao7/CTWNwTnctGK8PX2ZUB0ZfA==
二、HttpURLConnection
@Controller publicclassRestfulAction{ @Autowired privateUserServiceuserService; //修改 @RequestMapping(value="put/{param}",method=RequestMethod.PUT) public@ResponseBodyStringput(@PathVariableStringparam){ return"put:"+param; } //新增 @RequestMapping(value="post/{param}",method=RequestMethod.POST) public@ResponseBodyStringpost(@PathVariableStringparam,Stringid,Stringname){ System.out.println("id:"+id); System.out.println("name:"+name); return"post:"+param; } //删除 @RequestMapping(value="delete/{param}",method=RequestMethod.DELETE) public@ResponseBodyStringdelete(@PathVariableStringparam){ return"delete:"+param; } //查找 @RequestMapping(value="get/{param}",method=RequestMethod.GET) public@ResponseBodyStringget(@PathVariableStringparam){ return"get:"+param; } //HttpURLConnection方式调用Restful接口 //调用接口 @RequestMapping(value="dealCon/{param}") public@ResponseBodyStringdealCon(@PathVariableStringparam){ try{ Stringurl="http://localhost:8080/tao-manager-web/"; url+=(param+"/xxx"); URLrestServiceURL=newURL(url); HttpURLConnectionhttpConnection=(HttpURLConnection)restServiceURL .openConnection(); //param输入小写,转换成GETPOSTDELETEPUT httpConnection.setRequestMethod(param.toUpperCase()); //httpConnection.setRequestProperty("Accept","application/json"); if("post".equals(param)){ //打开输出开关 httpConnection.setDoOutput(true); //httpConnection.setDoInput(true); //传递参数 Stringinput="&id="+URLEncoder.encode("abc","UTF-8"); input+="&name="+URLEncoder.encode("啊啊啊","UTF-8"); OutputStreamoutputStream=httpConnection.getOutputStream(); outputStream.write(input.getBytes()); outputStream.flush(); } if(httpConnection.getResponseCode()!=200){ thrownewRuntimeException( "HTTPGETRequestFailedwithErrorcode:" +httpConnection.getResponseCode()); } BufferedReaderresponseBuffer=newBufferedReader( newInputStreamReader((httpConnection.getInputStream()))); Stringoutput; System.out.println("OutputfromServer:\n"); while((output=responseBuffer.readLine())!=null){ System.out.println(output); } httpConnection.disconnect(); } catch(MalformedURLExceptione){ e.printStackTrace(); } catch(IOExceptione){ e.printStackTrace(); } return"success"; } }
三、Spring的RestTemplate
springmvc.xml增加
controller
@Controller publicclassRestTemplateAction{ @Autowired privateRestTemplatetemplate; @RequestMapping("RestTem") public@ResponseBodyUserRestTem(Stringmethod){ Useruser=null; //查找 if("get".equals(method)){ user=template.getForObject( "http://localhost:8080/tao-manager-web/get/{id}", User.class,"呜呜呜呜"); //getForEntity与getForObject的区别是可以获取返回值和状态、头等信息 ResponseEntityre=template. getForEntity("http://localhost:8080/tao-manager-web/get/{id}", User.class,"呜呜呜呜"); System.out.println(re.getStatusCode()); System.out.println(re.getBody().getUsername()); //新增 }elseif("post".equals(method)){ HttpHeadersheaders=newHttpHeaders(); headers.add("X-Auth-Token",UUID.randomUUID().toString()); MultiValueMap postParameters=newLinkedMultiValueMap (); postParameters.add("id","啊啊啊"); postParameters.add("name","部版本"); HttpEntity >requestEntity=newHttpEntity >( postParameters,headers); user=template.postForObject( "http://localhost:8080/tao-manager-web/post/aaa",requestEntity, User.class); //删除 }elseif("delete".equals(method)){ template.delete("http://localhost:8080/tao-manager-web/delete/{id}","aaa"); //修改 }elseif("put".equals(method)){ template.put("http://localhost:8080/tao-manager-web/put/{id}",null,"bbb"); } returnuser; } }
以上就是本文关于浅谈java调用RestfulAPI接口的方式的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他Java相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!