浅谈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,
MapparamBody)throwsException{
returndoPost(httpsClient,url,paramHeader,paramBody,DEFAULT_CHARSET);
}
publicstaticStringdoPost(HTTPSClienthttpsClient,Stringurl,MapparamHeader,
MapparamBody,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,MapparamHeader,
MapparamBody)throwsException{
returndoGet(httpsClient,url,paramHeader,paramBody,DEFAULT_CHARSET);
}
publicstaticStringdoGet(HTTPSClienthttpsClient,Stringurl,MapparamHeader,
MapparamBody,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,MapparamHeader){
//设置Header
if(paramHeader!=null){
SetkeySet=paramHeader.keySet();
for(Stringkey:keySet){
request.addHeader(key,paramHeader.get(key));
}
}
}
privatestaticvoidsetBody(HttpPosthttpPost,MapparamBody,Stringcharset)throwsException{
//设置参数
if(paramBody!=null){
Listlist=newArrayList();
SetkeySet=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");
MapparamBody=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,
MapparamBody)throwsException{
returndoPost(httpClient,url,paramHeader,paramBody,DEFAULT_CHARSET);
}
publicstaticStringdoPost(HttpClienthttpClient,Stringurl,MapparamHeader,
MapparamBody,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,MapparamHeader,
MapparamBody)throwsException{
returndoGet(httpClient,url,paramHeader,paramBody,DEFAULT_CHARSET);
}
publicstaticStringdoGet(HttpClienthttpClient,Stringurl,MapparamHeader,
MapparamBody,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,MapparamHeader){
//设置Header
if(paramHeader!=null){
SetkeySet=paramHeader.keySet();
for(Stringkey:keySet){
request.addHeader(key,paramHeader.get(key));
}
}
}
privatestaticvoidsetBody(HttpPosthttpPost,MapparamBody,Stringcharset)throwsException{
//设置参数
if(paramBody!=null){
Listlist=newArrayList();
SetkeySet=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");
MapparamBody=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());
MultiValueMappostParameters=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相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!