在实际开发过程中,经常需要调用对方提供的接口或测试自己写的接口是否合适;而很多项目都会封装规定好本身项目的接口规范,所以大多数情况需要去调用对方提供的接口或第三方接口(短信、天气,支付,第三方登录等)。
测试自己写的接口可以使用postman(一个接口测试工具)或Advanced REST client(谷歌浏览器插件)
调用对方提供的接口或第三方接口方法:
......
一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序。
JDK自带的HTTP客户端,无需导入其它jar包。
步骤:
创建一个URL对象:
URL url = new URL(https://www.baidu.com);
调用URL对象的openConnection( )来获取HttpURLConnection对象实例:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
设置HTTP请求使用的方法:GET或者POST,或者其他请求方式比如:PUT ,DELETE
conn.setRequestMethod("GET");
设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头 conn.setConnectTimeout(6*1000); conn.setReadTimeout(6 * 1000);
调用getInputStream()方法获得服务器返回的输入流,然后对输入流进行读取
InputStream in = conn.getInputStream();
最后调用disconnect()方法将HTTP连接关掉
conn.disconnect();
注:除了上面这些外,有时还可能需要对响应码进行判断,比如if(conn.getResponseCode() != 200),然后判断结果是否成功和失败并做出对应的业务处理。
完整使用:
package com.xsh.HttpClient;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
/**
* @author : xsh
* @create : 2020-04-07 - 19:32
* @describe:
*/
public class test1 {
public static void main(String[] args) {
/*淘宝手机号查询接口,Get请求;使用时将xxx替换为正确的手机号*/
interfaceTest1("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=xxxxxxxxx", "");
}
/**
* 调用对方接口方法
* @param path 对方或第三方提供的路径
* @param data 如果是get请求则可以为空;post请求下向对方或第三方发送的数据,大多数情况下给对方发送JSON数据让对方解析
*/
public static void interfaceTest1(String path,String data) {
try {
//创建一个URL对象
URL url = new URL(path);
//打开和url之间的连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//创建一个字节流,用于打印接口返回信息
PrintWriter out = null;
//请求方式
conn.setRequestMethod("GET");
//设置通用的请求属性(模拟浏览器)
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//最常用的Http请求无非是get和post,get请求可以获取静态页面,也可以把参数放在URL字串后面
//post与get的 不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
/**
* 设置是否向httpUrlConnection输出
* 设置是否从httpUrlConnection读入
* 发送post请求必须设置这两个
*/
conn.setDoOutput(true);
conn.setDoInput(true);
//设置连接超时,读取超时的毫秒数
conn.setConnectTimeout(6*1000);
conn.setReadTimeout(6*1000);
out = new PrintWriter(conn.getOutputStream());
//发送请求参数即数据
out.print(data);
//缓冲数据
out.flush();
// 判断请求Url是否成功
int code = conn.getResponseCode();
if (code != 200) {
throw new RuntimeException("请求url失败");
}
InputStream is = conn.getInputStream();
//构造一个字符流缓存
BufferedReader br = new BufferedReader(new InputStreamReader(is,"GBK"));
String str = "";
while ((str = br.readLine()) != null) {
System.out.println(str);
}
//关闭流
is.close();
conn.disconnect();//固定多线程场景下,如果不disconnect,链接会增多,直到收发不出信息。
System.out.println(new Date()+",请求完整结束");
} catch (Exception e) {
e.printStackTrace();
}
}
}
返回结果:
HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性;简化了很多操作。
简单而言HttpClient就是加强版的HttpURLConnection,但是HttpClient能够维护客户端和服务端的Session。
使用:
新建一个maven工程,pom.xml导入jar包:
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
HttpClientUtil工具类:
package com.xsh.HttpClient;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class HttpClientUtil {
private CloseableHttpClient httpClient;
public HttpClientUtil() {
// 1 创建HttpClinet,相当于打开浏览器
httpClient = HttpClients.createDefault();
}
/* *
* get请求
* @param [url, map]
*/
public HttpResult doGet(String url, Map<String, Object> map) throws Exception {
// 声明URIBuilder
URIBuilder uriBuilder = new URIBuilder(url);
// 判断参数map是否为非空
if (map != null) {
// 遍历参数
for (Map.Entry<String, Object> entry : map.entrySet()) {
// 设置参数
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 2 创建httpGet对象,相当于设置url请求地址
HttpGet httpGet = new HttpGet(uriBuilder.build());
// 3 使用HttpClient执行httpGet,相当于按回车,发起请求
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
} catch (IOException e) {
HttpResult httpResult = new HttpResult();
httpResult.setCode(404);
httpResult.setBody("请求失败");
return httpResult;
}
// 4 解析结果,封装返回对象httpResult,相当于显示相应的结果
// 状态码
// response.getStatusLine().getStatusCode();
// 响应体,字符串,如果response.getEntity()为空,下面这个代码会报错,所以解析之前要做非空的判断
// EntityUtils.toString(response.getEntity(), "UTF-8");
HttpResult httpResult = new HttpResult();
// 解析数据封装HttpResult
if (response.getEntity() != null) {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(),"UTF-8"));
httpResult.setCode(response.getStatusLine().getStatusCode());
httpResult.setBody(EntityUtils.toString(response.getEntity(),"UTF-8"));
} else {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(), "");
httpResult.setCode(response.getStatusLine().getStatusCode());
//httpResult.setBody("");
}
// 返回
return httpResult;
}
/* *
* post请求
* @param [url, map]
*/
public HttpResult doPost(String url, Map<String, Object> map) throws Exception {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 判断map不为空
if (map != null) {
// 声明存放参数的List集合
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 遍历map,设置参数到list中
for (Map.Entry<String, Object> entry : map.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
// 创建form表单对象
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, "UTF-8");
// 把表单对象设置到httpPost中
httpPost.setEntity(formEntity);
}
// 使用HttpClient发起请求,返回response
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (IOException e) {
HttpResult httpResult = new HttpResult();
httpResult.setCode(404);
httpResult.setBody("请求失败");
return httpResult;
}
// 解析response封装返回对象httpResult
HttpResult httpResult = new HttpResult();
// 解析数据封装HttpResult
if (response.getEntity() != null) {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(),"UTF-8"));
httpResult.setCode(response.getStatusLine().getStatusCode());
httpResult.setBody(EntityUtils.toString(response.getEntity(),"UTF-8"));
} else {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(), "");
httpResult.setCode(response.getStatusLine().getStatusCode());
//httpResult.setBody("");
}
// 返回结果
return httpResult;
}
/* *
* Put请求
* @param [url, map]
*/
public HttpResult doPut(String url, Map<String, Object> map) throws Exception {
// 声明httpPost请求
HttpPut httpPut = new HttpPut(url);
// 判断map不为空
if (map != null) {
// 声明存放参数的List集合
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 遍历map,设置参数到list中
for (Map.Entry<String, Object> entry : map.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
// 创建form表单对象
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, "UTF-8");
// 把表单对象设置到httpPost中
httpPut.setEntity(formEntity);
}
// 使用HttpClient发起请求,返回response
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPut);
} catch (IOException e) {
HttpResult httpResult = new HttpResult();
httpResult.setCode(404);
httpResult.setBody("请求失败");
return httpResult;
}
// 解析response封装返回对象httpResult
HttpResult httpResult = new HttpResult();
// 解析数据封装HttpResult
if (response.getEntity() != null) {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(),"UTF-8"));
httpResult.setCode(response.getStatusLine().getStatusCode());
httpResult.setBody(EntityUtils.toString(response.getEntity(),"UTF-8"));
} else {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(), "");
httpResult.setCode(response.getStatusLine().getStatusCode());
//httpResult.setBody("");
}
// 返回结果
return httpResult;
}
/* *
* Delete请求
* @param [url, map]
*/
public HttpResult doDelete(String url, Map<String, Object> map) throws Exception {
// 声明URIBuilder
URIBuilder uriBuilder = new URIBuilder(url);
// 判断参数map是否为非空
if (map != null) {
// 遍历参数
for (Map.Entry<String, Object> entry : map.entrySet()) {
// 设置参数
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 2 创建httpGet对象,相当于设置url请求地址
HttpDelete httpDelete = new HttpDelete(uriBuilder.build());
// 3 使用HttpClient执行httpGet,相当于按回车,发起请求
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpDelete);
} catch (IOException e) {
HttpResult httpResult = new HttpResult();
httpResult.setCode(404);
httpResult.setBody("请求失败");
return httpResult;
}
// 4 解析结果,封装返回对象httpResult,相当于显示相应的结果
// 状态码
// response.getStatusLine().getStatusCode();
// 响应体,字符串,如果response.getEntity()为空,下面这个代码会报错,所以解析之前要做非空的判断
// EntityUtils.toString(response.getEntity(), "UTF-8");
HttpResult httpResult = new HttpResult();
// 解析数据封装HttpResult
if (response.getEntity() != null) {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(),"UTF-8"));
httpResult.setCode(response.getStatusLine().getStatusCode());
httpResult.setBody(EntityUtils.toString(response.getEntity(),"UTF-8"));
} else {
//httpResult = new HttpResult(response.getStatusLine().getStatusCode(), "");
httpResult.setCode(response.getStatusLine().getStatusCode());
//httpResult.setBody("");
}
// 返回
return httpResult;
}
}
HttpResult,封装返回结果
package com.xsh.HttpClient;
import java.io.Serializable;
public class HttpResult implements Serializable {
// 响应的状态码
private int code;
// 响应的响应体
private String body;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public String toString() {
return "HttpResult{" +
"code=" + code +
", body='" + body + '\'' +
'}';
}
}
使用:
import com.xsh.HttpClient.HttpClientUtil;
import com.xsh.HttpClient.HttpResult;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @author : xsh
* @create : 2020-04-07 - 21:55
* @describe:
*/
public class APITest {
private HttpClientUtil apiService;
@Before
public void init() {
this.apiService = new HttpClientUtil();
}
// 查询手机号是否已注册网易云音乐
@Test
public void test1() throws Exception {
String url = "http://neteasymusic.xiongsihao.com/cellphone/existence/check";
Map<String, Object> map = new HashMap<String, Object>();
map.put("phone",11111111111L);//int类型最多不能超过11位,所以需手机号后面加L
HttpResult httpResult = apiService.doGet(url,map);
if(httpResult.getCode()==200){
System.out.println("SUCCESS");
}
System.out.println(httpResult.getBody());
}
//查询本机ip地址
@Test
public void test2() throws Exception {
String url = "http://pv.sohu.com/cityjson";
HttpResult httpResult = apiService.doGet(url,null);
if(httpResult.getCode()==200){
System.out.println("SUCCESS");
}
System.out.println(httpResult.getBody());
}
//根据ip地址查询具体位置
@Test
public void test3() throws Exception {
String url = "http://whois.pconline.com.cn/ipJson.jsp";
Map<String, Object> map = new HashMap<String, Object>();
map.put("ip","101.244.63.242");//传入ip地址
map.put("json","true");
HttpResult httpResult = apiService.doGet(url,map);
if(httpResult.getCode()==200){
System.out.println("SUCCESS");
}
System.out.println(httpResult.getBody());
}
}
运行结果:
test1:
test2:
test3:
OkHttpClient官网: http://square.github.io/okhttp/ OkHttp GitHub地址:https://github.com/square/okhttp
导入依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.6.0</version>
</dependency>
<!--JSON解析工具-->
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-parent</artifactId>
<version>2.8</version>
</dependency>
使用:
package com.xsh.HttpClient;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
/**
* @author : xsh
* @create : 2020-04-07 - 20:39
* @describe: GTE接口调用
*/
public class testOkHttpClient {
public static void main(String[] args) {
try {
/*向指定手机号发送短信*/
String result=run("http://neteasymusic.xiongsihao.com/captcha/sent?phone=178xxxxxxxx");
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
}
private static String run(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
Request是OkHttp中访问的请求,Builder是辅助类。Response即OkHttp中的响应。
是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。
当然也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp。
RestTemplate包含以下几个部分:
导入依赖:
<!--RestTemplate依赖在spring-web这个包下-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
使用:
package com.xsh.HttpClient.Method1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
/**
* @author : xsh
* @create : 2020-04-07 - 21:06
* @describe:
*/
public class testRestTemplate {
public static void main(String[] args) {
RestTemplate restTemplate=new RestTemplate();
//获取网易云热评
String result = restTemplate.getForObject("http://neteasymusic.xiongsihao.com/comment/hotwall/list",String.class);//调用的ul与返回类型
System.out.println(result);
}
}
例子:http://neteasymusic.xiongsihao.com/
说明 : 调用此接口 ,传入手机号码, 可发送验证码
原网址:https://music.163.com/weapi/sms/captcha/sent
必选参数 : phone
: 手机号码
可选参数 : ctcode
: 国家区号,默认86即中国
接口地址 : /captcha/sent
直接调用例子 : http://neteasymusic.xiongsihao.com/captcha/sent?phone=13xxx
说明 : 调用此接口 ,可检测手机号码是否已注册
原网址:http://music.163.com/eapi/cellphone/existence/check
必选参数 : phone
: 手机号码
可选参数 : countrycode
: 国家码,用于国外手机号,例如美国传入:1
接口地址 : /cellphone/existence/check
直接调用例子 : http://neteasymusic.xiongsihao.com/cellphone/existence/check?phone=13xxx
说明 : 调用此接口 , 传入搜索关键词可以搜索该音乐 / 专辑 / 歌手 / 歌单 / 用户 , 关键词可以多个 , 以空格隔开
原网址:https://music.163.com/weapi/search/get
必选参数 : keywords
: 关键词
可选参数 : limit
: 返回数量 , 默认为 30 offset
: 偏移数量,用于分页数据
接口地址 : /search
直接调用例子 : http://neteasymusic.xiongsihao.com/search?keywords=冬眠
说明 : 传入的音乐 id( 可多个 , 用逗号隔开 ), 可以获取对应的音乐的 url;可先通过搜索获取音乐id,再传入此处获取url
必选参数 : id
: 音乐 id
接口地址 : /song/url
调用例子 :
http://neteasymusic.xiongsihao.com/song/url?id=1398663411
http://neteasymusic.xiongsihao.com/song/url?id=1398663411,33894312
说明 : 调用此接口 , 传入音乐 id 可获得对应音乐的歌词
原网址:https://music.163.com/api/song/lyric
必选参数 : id
: 音乐 id
接口地址 : /lyric
直接调用例子 : http://neteasymusic.xiongsihao.com/lyric?id=1398663411
说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该音乐的所有评论
原网址:https://music.163.com/api/comment/music
必选参数 : id
: 音乐 id
可选参数 : limit
: 取出评论数量 , 默认为 20
offset
: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值
before
: 分页参数,取上一页最后一项的 time
获取下一页数据(获取超过5000条评论的时候需要用到)
接口地址 : /comment/music
调用例子 : http://neteasymusic.xiongsihao.com/comment/music?id=1398663411&limit=1
对应冬眠评论
导入解析json的依赖:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20140107</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
以获取歌曲url为例(此处使用HttpClient方法调用接口):
首先需要获取歌曲的id(以冬眠为例)
@Test
public void test4() throws Exception {
String url = "http://neteasymusic.xiongsihao.com/search?keywords=";
Map<String, Object> map = new HashMap<String, Object>();
map.put("keywords","冬眠");
HttpResult httpResult = apiService.doGet(url,map);
if(httpResult.getCode()==200){
System.out.println("SUCCESS");
}
System.out.println(httpResult.getBody());
//解析json数据
String result=httpResult.getBody();
JSONObject jsonObject = new JSONObject(result);//将Stirng转化为JSON对象
System.out.println("返回状态码为:"+jsonObject.getInt("code"));//获取json数据指定key(code)的值
}
通过debug运行可以看到,歌曲id在songs(JSON数组类型)——>myArrayList(ArrayList类型)——>map(HashMap类型)——>id对应的value内
完整使用:
使用jsonObject取出此处的值,并获取歌曲URL(以冬眠为例):
//搜索歌曲,获取歌曲id,再通过id获取歌曲url
@Test
public void test4() throws Exception {
String url1 = "http://neteasymusic.xiongsihao.com/search";//搜索,获取歌曲id
String url2 = "http://neteasymusic.xiongsihao.com/song/url";//根据歌曲id获取歌曲url
Map<String, Object> map = new HashMap<String, Object>();
map.put("keywords","冬眠");
HttpResult httpResult1 = apiService.doGet(url1,map);
if(httpResult1.getCode()==200){
System.out.println("SUCCESS");
}
System.out.println(httpResult1.getBody());
//解析json数据
String result=httpResult1.getBody();
JSONObject jsonObject = new JSONObject(result);//将Stirng转化为JSON对象
System.out.println("返回状态码为:"+jsonObject.getInt("code"));//获取指定key(code)的值
JSONArray jsonArray = jsonObject.getJSONObject("result").getJSONArray("songs");//获取歌曲数组
for(int i=0; i< 3; i++){//此处只取前3,获取全部可将3替换为jsonArray.length();
JSONObject song = (JSONObject)jsonArray.get(i);
int songId = song.getInt("id");
System.out.println("歌曲【"+(i+1)+"】id:"+songId);//打印搜索结果中,前3的歌曲
//通过歌曲id获取歌曲url
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("id",songId);
HttpResult httpResult2 = apiService.doGet(url2,map2);
if(httpResult2.getCode()==200){
System.out.println("SUCCESS");
String result2=httpResult2.getBody();
//解析歌曲url信息
JSONObject jsonObject2 = new JSONObject(result2);
JSONArray jsonArray2 = jsonObject2.getJSONArray("data");
for(int j=0; j< jsonArray2.length(); j++){
JSONObject data = (JSONObject)jsonArray2.get(j);
String url = data.getString("url");
System.out.println("歌曲url:"+url);
}
}
}
}
运行结果:
jsonObject内获取各种数据类型的方法:
评论