使用OkHttp3进行简单的API调用
OKHttp是一个当前主流的网络请求的开源框架,
1.get方法(同步)
引入依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.1.0</version>
</dependency>
get提交数据:
大致分3大步
1.实例化OkHttpClient。
2.执行调用。
i. 在执行调用之前,需要实例化一个Request 对象,作用是定义请求的各种参数,然后构建调用对象Call;
ii.最后执行调用,如果调用失败可能抛异常,所以必须抓取异常。
iii.开始执行调用。call.execute()就是执行调用的代码。
3. call. execute()返回的其实是一个执行的结果对象,调用对象的方法即可获取返回的字符串内容: call.execute(). body() .string();
扩展: 如果获得返回的二进制字节数组,则调用call.execute(). body().bytes(),如果想拿到返回的inputStream,则调call.execute(). body().byteStream().有inputStream就可以通过IO的方式写文件。
具体实现:
import java.io.IOException;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class GetPage {
/**
* 根据输入的url,读取页面内容并返回
*/
public String getContent(String url) {
// okHttpClient 实例
OkHttpClient okHttpClient = new OkHttpClient();
// 定义request组装请求头
Request request = new Request.Builder().url(url).build();
// 使用client去请求
Call call = okHttpClient.newCall(request);
// 返回结果字符串
String result = null;
try {
// 获得返回结果
result = call.execute().body().string();
//这里的call也经常写成response,其中response为Response response = okHttpClient.newCall(request).execute();
} catch (IOException e) {
// 抓取异常
System.out.println("request " + url + " error . ");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
GetPage getPage = new GetPage();
String url = "https://www.fastmock.site/mock/3d95acf3f26358ef032d8a23bfdead99/api/musicRankings";
String content = getPage.getContent(url);
System.out.println("API调用结果");
System.out.println(content);
}
}
2.post方法(同步)
post提交表单数据
大致步骤上只和get方法的new Request
对象的时候有差别,get提交数据是把数据放在了url中,而post则不同。
具体实现:
引入依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.1.0</version>
</dependency>
提交表单数据:
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import okhttp3.FormBody;
import okhttp3.FormBody.Builder;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class FormPoster {
public String postContent(String url, Map<String, String> formData) {
// okHttpClient 实例
OkHttpClient okHttpClient = new OkHttpClient();
//post方式提交的数据
Builder builder = new FormBody.Builder();
// 放入表单数据
for(String key:formData.keySet()){
builder.add(key,formData.get(key));
}
// 构建 FormBody 对象
FormBody formBody = builder.build();
// 指定 post 方式提交FormBody
Request request = new Request.Builder().url(url).post(formBody).build();
// 使用client去请求
Call call = okHttpClient.newCall(request);
// 返回结果字符串
String result = null;
try {
// 获得返回结果
result = call.execute().body().string();
} catch (IOException e) {
// 抓取异常
System.out.println("request " + url + " error . ");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String url = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm";
Map<String, String> formData = new HashMap();
formData.put("tel","13283714686");
FormPoster poster = new FormPoster();
String content = poster.postContent(url, formData);
System.out.println("API调用结果");
System.out.println(content);
}
}
post提交JSON数据
大致分3个步骤:
1.将数据转换成JSON 格式的字符串,调用JSON.toJSONString()
方法即可。
2.创建RequestBody 实例,注意需要指定提交的类型是application/json; charset=utf-8 。
3.构建Request 实例对象时,调用.post(requestBody)即表示使用JSON的方式提交数据。
具体实现:
先引入新的依赖:
<!-- JSON 操作库 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
提交JSON数据操作:
import com.alibaba.fastjson.JSON;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
public class JsonPoster {
// 定义提交数据的类型
public static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
/**
* 向指定的 url 提交数据,以 json 的方式
*/
public String postContent(String url, Map<String, String> datas) {
// okHttpClient 实例
OkHttpClient okHttpClient = new OkHttpClient();
// 数据对象转换成 json 格式字符串
String param = JSON.toJSONString(datas);
//post方式提交的数据
RequestBody requestBody = RequestBody.create(JSON_TYPE, param);
Request request = new Request.Builder().url(url).post(requestBody).build();
// 使用client去请求
Call call = okHttpClient.newCall(request);
// 返回结果字符串
String result = null;
try {
// 获得返回结果
result = call.execute().body().string();
} catch (IOException e) {
// 抓取异常
System.out.println("request " + url + " error . ");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String url = "https://www.fastmock.site/mock/3d95acf3f26358ef032d8a23bfdead99/api/posts";
Map<String, String> datas = new HashMap();
datas.put("name", "迪丽不热吧");
datas.put("secondName", "奥摩");
JsonPoster poster = new JsonPoster();
String content = poster.postContent(url, datas);
System.out.println("API调用结果");
System.out.println(content);
}
}
headers
1User-Agent:表示用户端的访问类型,是谷歌浏览器还是火狐还是手机,有时候一个url在浏览器里可以访问,但是在Java程序里就访问不到这里就是User-Agent
起的作用。User-Agent官方文档戳这里
2.Referer:在网站中有的图片使用了防盗链,在java程序里访问会被重定向到别的地址,只能他们自己的服务器才能访问该图片,如果不使用Referer用response.request().url().toString()
打印出最终响应的url是重定向过的,和原始代码里请求的url不一致,加了Refer之后会保证访问请求是在该服务器内的,即可最终访问到原始url。
3.Host表示当前请求的域名。虽然这个域名已经存在于URL中,但遇到复杂的场景,例如使用代理服器、或者URL中不写域名而是写|IP 地址进行请求等,设置Host 就非常有用了。Host一定不会带协议头(http/https),且一定是个域名。
代码举例:
// okHttpClient 实例
OkHttpClient okHttpClient = new OkHttpClient();
// 定义一个request
Request request = new Request.Builder()
.url(url)
.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1")
.addHeader("Referer","http://photo.yupoo.com/")
.addHeader("Host","photo.yupoo.com")
.build();
Web中为什么要设置Session和Cookie
一年一度的国庆小长假到来了,东方世纪欢乐园借此机会准备在举办夜晚欢乐派对,对一直支持游乐园的铁杆粉丝发出邀请。公司白领小贺本就计划好假期带女朋友一起来玩,所以一听到这个消息十分开心,当即给此次活动报了名。小胖是这家游乐园的工作人员,负责此次活动游客的进入进出
,每来一个人都需要他在花名册
里核对名单,查询
该游客是否报名了此次活动。
活动开始了,小贺和女友如期而至,走到游乐园门口的时候报了自己的名字,等待小胖从花名册里查询,大概过了2分钟,小胖扶了扶眼镜告诉他说终于找到了,可以进去,小贺心里默念:游乐园看着挺豪华为什么里面工作人员的工作效率这么低,幸好自己是提前来的,不然遇到高峰期恐怕要等工作人员查好久才能进去。不过一点不足无伤大雅,游乐园里面的服务特别优质,大家该吃吃该喝喝该玩玩,每个人都很开心。活动进行到一半,有人提出要上厕所的要求,可是游乐园里没有厕所,只能出园再进来,但是进来的时候又要请求小胖去查找很长的花名册,这不管对游客还是对工作人员小胖无疑都是个很不爽的槽点。随着排队等待的人越来越多,小贺看不下去了,决定走向前去为小胖支招:大家出园的时候给每个人手腕系个一次性标记绳
,要想解开这个绳结除非剪断它,这样你看到绳结就可以认为之前查询到有他的名字,不必再次查询
了。小胖一听,直拍大腿,跳了起来,我丢,这主意好啊,省去了二次查询的麻烦,还特别省时间,真是太方便了。于是当即实施这种辨别方式,赢得了广大游客的好评,当晚的派对活动最终圆满结束。
通过上面的小故事,不知道大家有没有领悟到cookie机制在web中使用的好处呢?上面故事里的花名册就对对应数据库,一次性标记绳就是cookie,小胖就是某个应用的登陆页面,小贺就是用户,想要去请求登陆。cookie优点就是当用户二次登陆网站的时候不必进行登陆操作去数据库查询该用户的信息是否正确,而是通过cookie确定数据库里有该用户,可以直接进入网站主页,省去了冗余查询操作。
那么既然有了cookie足够证明用户身份
,为什么还要有Session呢?其实Session存在于服务器端,主要储存用户的一些详细信息
(比如头像,性别,年龄,手机号),安全性比cookie高
,并且cookie的大小最多不能超过4k,而session理论上并没有限制
。
Cookie和Session的执行流程:
cookie执行流程
首先用户访问应用的时候,来到服务器。服务器设置一个cookie,在做响应的时候会通过set-cookie响应头将cookie带给浏览器。然后回到浏览器,浏览器会将此数据保存起来,接下来再次去访问服务器的时候,浏览器会根据cookie的path属性将这些数据带回去,来到服务器,服务器有对应的api获取这些值,有了值(一次性手腕绳)就知道用户是谁了。
session执行流程
客户浏览器发起一个请求到服务器,服务器先检查你是否携带了一个叫做JSESSIONID的cookie。
如果有携带,会将此cookie的值取出来(比如abc123),然后从服务器的session池中找到ID为aaa123的session(用户详细信息)返回给调用者。
如果没有携带这个JSESSIONID的cookie,那么服务器将会自动创建一个session对象并且生成一个随机字符串(比如abc123)作为此session的ID保存到session池中。在服务器为客户端浏览器作响应的时候自动创建一个键为“JSESSIONID” 值为“abc123”的cookie对象让浏览器储存起来以便下次再访问的时候带过来。
对JSON的理解
JSON字符串:只是一种特殊的字符串,没有换行格式,是前后端交互常采用的通信格式
“ { "firstName": "Bill", "lastName": "Gates"}”
JSON对象:用大括号包围的具体格式的对象
{
"firstName": "Bill",
"lastName": "Gates"
}
JSON数组:本质上就是数组,每一个数组元素是json对象,用[]包围起来
[
{
"firstName": "Bill",
"lastName": "Gates"
},
{
"firstName": "George",
"lastName": "Bush"
}
]
json的运用:
前端收到json字符串,可以转化成json对象,进行取值操作。直接操作json字符串麻烦。
前端发送json数据时,首先拼接json对象,然后把发送的json对象转化为json字符串的形式发送。
后台收到json字符串,转化成json对象,进行取值操作。
同样,后台发送json数据,首先拼接json对象,然后把发送的json对象转化为json字符串的形式发送。
JSON、JSONObject、JAVAObject之间的相互转换
直接上代码,说明:这里输出转换成功类型的特有方法是为了类型已经成功转换,Ip类只有以个属性ip。
public static void main( String[] args )
{
String jsonStr = "{\"ip\":\"61.158.152.209\"}";
//将json字符串强转为map
Map map= (Map)JSONObject.parse(jsonStr);
//将map强转为json字符串
String jsonStr1 = JSON.toJSONString(map);
//json强转为JsonObject
JSONObject jsonObject = JSON.parseObject(jsonStr1);
//json字符串强转为JavaObject类 先把JSON强转为JsonObject
Ip ip = JSON.toJavaObject(JSON.parseObject(jsonStr1),Ip.class);
//JAVAObject强转为JSON字符串
String jsonStr2 = JSON.toJSONString(ip);
//JAVAObject强转为Map 先把Objiect转换为JSonString
Map map1 = JSON.parseObject(JSON.toJSONString(ip));
//map强转为JavaObject 先把map转为JSON字符串然后转换为JSONOBject再转换为JavaObject
Ip ip1 = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(map1)),Ip.class);
//这是json字符串强转为map的输出:61.158.152.209
System.out.println("这是json字符串强转为map的输出:" + map.get("ip"));
//这是map强转为json字符串的输出:{"ip":"61.158.152.209"}
System.out.println("这是map强转为json字符串的输出:" + jsonStr1);
//这是Json字符串强转为JavaObject的输出:61.158.152.209
System.out.println("这是Json字符串强转为JavaObject的输出:" + ip.getIp());
//这是JAVAObject强转为JSON字符串:{"ip":"61.158.152.209"}
System.out.println("这是JAVAObject强转为JSON字符串:" + jsonStr2);
//这是JAVAObject强转为Map的输出:61.158.152.209
System.out.println("这是JAVAObject强转为Map的输出:" + map1.get("ip"));
//这是map强转为JavaObject的输出:61.158.152.209
System.out.println("这是map强转为JavaObject的输出:" + ip1.getIp());
}