内容:http请求、返回规范、Json、项目示例
一.网络请求的分类
网络请求主要有八种,如下表所示:
请求方式 | 描述 |
---|---|
GET | 发送请求来获得服务器上的资源【比如请求百度的页面】 |
POST | 向服务器提交资源让服务器处理【比如百度云盘上传资源】 |
HEAD | 主要用来检查资源或超链接的有效性或是否可以可达、检查网页是否被串改或更新 |
PUT | 向指定资源位置上上传其最新内容 |
DELETE | 请求服务器删除某资源 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 |
OPTIONS | 允许客户端查看服务器的性能 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
最常用的是GET和POST请求。
(1)GET请求:一般情况下,发送请求从服务器上获取资源,不会对服务器资源产生任何影响的时候使用GET请求。
(2)POST请求:向服务器发送数据(登录)、上传文件等让服务器处理,会对服务器资源产生影响的时候使用POST请求。
1.请求头常见参数
(1)User-Agent
指浏览器的名称。我们在向别人的服务器发送请求的时候,别人的服务器通过这个参数知道请求是从哪种浏览器发出的,这样就能返回正确的信息。但是如果不设置这个参数的话,我们如果使用Python发送去了请求,别人的服务器【大部分服务器】就知道这个请求时Python发出的,从而不给我们返回正确的数据。因此我们必须设定这个参数。
(2)Referer
表明这个网页是从哪个网站跳转过来的。有些网页只能从特定的链接跳转过来,如果不设置这个参数,有些网页就知道你是通过非浏览器方式试图获取他们的html页面,因此就不返回给你正确的数据。所以这个参数可以用来进行反爬虫设计,我们需要设定这个参数。
(3)Cookie
HTTP协议是无状态的。也就是同一个人在浏览器上发送了两次请求,服务器不知道这两个请求是否来自同一个人。因此这时候就用Cookie来做标识。一般登陆后才能访问的网页,这个时候就需要发送Cookie信息。
2.常见响应状态码
状态码 | 含义 |
---|---|
200 | 请求成功 |
301 | 永久重定向,资源(网页等)被永久转移到其它URL【www.jingdong.com —>>>www.jd.com】 |
404 | 请求的资源(网页等)不存在 |
500 | 内部服务器错误 |
二、返回规范
向前端返回详细的错误信息
当错误发生时,除了需要返回相应的状态码之外,还需要返回详情的错误信息。因为状态码只是通用的描述错误的类别,一般无法表示实际发生的具体错误信息。
比如说400
状态码,只是知道前端请求发生了错误,至于如何去修改,仅凭这个是没有办法找到bug
的。
通常来说:返回错误信息的方法有两种:
- 将信息放入
HTTP
响应头 - 将信息通过
HTTP
响应体返回
1、通过自定义头部,将详细的错误信息放入响应头中
X-ERROR-CODE: 2020
X-ERROR-MESSAGE: Bad authentication token
X-ERROR-INFO: http://api.example.com/v1/authentication
2、将错误信息放入响应体中
{
"error": {
"code": 2020,
"message": "Bad authentication token",
"info": "http://api.example.com/v1/authentication"
}
}
从前端的角度来考虑,通过响应体返回会更加容易处理。
这里的错误代码的命名方式,按照后端自己的要求编写即可。
通常情况下,会要求接口的错误信息越详细越好,但这也不是一定的,也会有特殊情况。
一般而言,前端会将后端接口的错误信息原封不动的显示出来,因为前端很难去判断是否有涉密信息或者让用户难堪的信息。比如说A用户屏蔽了B用户,当B用户想看A用户的详情时,如果正确的返回:“A用户已屏蔽B用户,无法获取”的话,会让双方都难堪。这时就需要返回模棱两可的信息。这个就需要后端开发们自己去领悟。
针对默认返回与API
维护
某些接口在发生错误时会将HTML
返回。特别是发生404、503等错误时,这种情况就比较常见。当发生这些错误时,用于构建API
的Web
服务器或者app
框架会直接返回出错信息,默认情况下大都是HTML
。
但虽说是发生了错误,前端依然在访问中,所以仍然期待服务器返回约定好的格式,比如JSON
。尤其在通过Accept
请求头部或扩展名等指定了接收格式时。当然可以让前端去检查Content_Type
头部,进行相应的处理。但如果前端处理的不好或者没有处理,可能会导致app
崩溃。
尤其是公共api
,不能期望所有的使用者都严格遵循规范来处理好,这种api
算不上了好的api
。
关于API
的维护,正常来说,要避免不得不停止API
的发生。但特殊的时候也会不得不停止API
进行维护工作,这种情况需要返回503
状态码来告知前端当前API
已经停止工作。另外,因为这种停止操作不是意外而是有计划进行的,所以要有API
何时重启的时间信息,将其发送给前端。
不仅要预备好用于定期维护的状态码和出错信息的返回,还要使用Retry-After
头部来告诉前端维护结束的时间。从SEO
的角度来看,这个方式对普通的web
站点的维护也同样适用,也是Google
推荐的方法。
Retry-After
的值可以是某个具体的日期或从当前时刻算起至可正常访问为止所需的秒数。
503 Service Temporarily Unavailable
Retry-After: Mon, 9 Sep 2020 20:00:00 GMT
从前端实现的角度来看,在返回503错误时,是期待前端能识别出API
地方Retry-After
值指定的时间等待,然后在API
重启的时候再次访问。
虽然这些处理都取决于前端的具体实现,后端无法对此进行控制,但依然要尽可能地返回详细的信息,方便前端处理并提升用户体验。
总结
主要是三个痛点:
- 必须选择合适的
HTTP
状态码 - 向前端返回详细的错误信息
- 针对默认返回与
API
维护
三、Json
1.什么是json
JSON:(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。目前,Json处于数据交换语言的王者地位.
1.1 json的特点
(1)json是一种轻量级的数据交换格式
(2)json采用完全独立于计算机语言和操作系统的平台,不同的编程语言和操作系统json数据是一致的
(3)json易于阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输效率)
1.2 xml和json的区别
(1)xml:
1.json与js对象的转换
<script type="text/javascript">
// js对象
var obj = { name: "亚瑟", age: 23, address: "上海" };
document.write(obj.name + "<br/>");
var obj2 = {
users: [{ name: "鲁班", age: 21, address: "北京" },
{ name: "后裔", age: 26, address: "广州" }]
};
document.write(obj2.users[0].address + "<br/>");
// json转换为js对象(方式一)
var test1 = '{"name":"后裔","age":25}';
var obj3 = eval("(" + test1 + ")"); //必须带圆括号
document.write("name=" + obj3.name + ",age=" + obj3.age + "<br/>");
// json转换为js对象(方式二)
var obj4 = JSON.parse('{ "name":"李白", "age":18, "address":"北京" }');
document.write(obj4.name + "<br/>");
</script>
注意:
(1)有些浏览器不支持JSON.parse这个方法,可以到官网下载json2.js添加到你的hlml中就可以了。
(2)为什么要 eval这里要添加 eval(“(” + test1 + “)”)//”呢?
原因在于:eval本身的问题。 由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理,所以必须强制性
的将它转换成一种表达式。
加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将 括号内的表达式(expression)转化为对象,而不是作为语(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始
和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:
alert(eval(“{}”); // return undefined
alert(eval(“({})”);// return object[Object]
2.Json与Java对象的转换
(1)使用 alibaba 的 fastJson
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
(2)实例
public class MyJson {
public static String jsonmap = "{\"001\":{\"name\":\"xiaohong\",\"password\":\"654321\"},\"002\":[{\"$ref\":\"$.001\"},{\"name\":\"xixi\",\"password\":\"789\"}]}";
public static String jsonuser = "{\"name\":\"xiaohong\",\"password\":\"654321\"}";
public static String jsonlist = "[{\"name\":\"xiaohong\",\"password\":\"654321\"},{\"name\":\"xixi\",\"password\":\"789\"}]";
public static void main(String[] args) {
User user = new User();
user.setName("xiaohong");
user.setPassword("654321");
List<User> list = new ArrayList<User>();
list.add(user);
list.add(new User("xixi","789"));
Map map = new HashMap();
map.put("001",user);
map.put("002",list);
// 1. json字符串 转换为 java 对象
// toJsonString - java对象转换为json字符串
System.out.println(JSONObject.toJSONString(user));
System.out.println(JSONObject.toJSONString(list));
System.out.println(JSONObject.toJSONString(map));
// toJavaObject - json字符串转换为java对象
System.out.println(JSONObject.parseObject(jsonuser,User.class));
List list1 = JSONObject.parseObject(jsonlist, List.class);
for(int i=0;i<list1.size();i++) {
System.out.println(JSONObject.parseObject(JSONObject.toJSONString(list1.get(i)),User.class));
}
Map map1 = JSONObject.parseObject(jsonmap, Map.class);
Iterator iterator = map1.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry= (Map.Entry) iterator.next();
System.out.println("key :"+entry.getKey()+" value: " + entry.getValue());
}
// Json -- 实体类转换为json字符串
System.out.println(JSON.toJSONString(user));
System.out.println(JSON.toJSONString(list));
System.out.println(JSON.toJSONString(map));
// json -- json 转 java对象
System.out.println(JSON.parseObject(jsonuser,User.class));
List list2 = JSON.parseObject(jsonlist, List.class);
for(int i=0;i<list2.size();i++) {
System.out.println(JSON.parseObject(JSON.toJSONString(list1.get(i)),User.class));
}
Map map2 = JSON.parseObject(jsonmap, Map.class);
Iterator iterator2 = map1.entrySet().iterator();
while (iterator2.hasNext()) {
Map.Entry entry= (Map.Entry) iterator2.next();
System.out.println("key :"+entry.getKey()+" value: " + entry.getValue());
} } }
3.使用Java修改json字符串(JSON解析库使用Jackson)
(1)替换json字符串,指定的值
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class Main {
public static void main(String[] args) {
String jsonStr = "{\"code\":0,\"msg\":\"\",\"count\":3042,\"data\":[{\"UPN\":\"WR1.04.046.0166300023032100120230316104\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-1\",\"CreateTime\":\"2023-10-23 08:49:00\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316512\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-2\",\"CreateTime\":\"2023-10-23 08:49:12\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316434\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-3\",\"CreateTime\":\"2023-10-23 08:49:24\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316999\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-5\",\"CreateTime\":\"2023-10-23 09:05:02\"},{\"UPN\":\"WR1.04.042.0074273022120800120221205927\",\"PN\":\"1.04.042.0074\",\"Lot\":null,\"DC\":\"20221205\",\"Qty\":2730,\"PositionCode\":\"1-1-1-3\",\"CreateTime\":\"2023-10-25 12:51:21\"}]}";
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
jsonObject.put("msg", "替换后的值");
System.out.println(jsonObject.toJSONString());
}
}
(2)替换json字符串的key的值
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class Main {
public static void main(String[] args) {
String jsonStr = "{\"code\":0,\"msg\":\"\",\"count\":3042,\"data\":[{\"UPN\":\"WR1.04.046.0166300023032100120230316104\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-1\",\"CreateTime\":\"2023-10-23 08:49:00\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316512\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-2\",\"CreateTime\":\"2023-10-23 08:49:12\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316434\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-3\",\"CreateTime\":\"2023-10-23 08:49:24\"},{\"UPN\":\"WR1.04.046.0166300023032100120230316999\",\"PN\":\"1.04.046.0166\",\"Lot\":null,\"DC\":\"20230316\",\"Qty\":3000,\"PositionCode\":\"1-1-27-5\",\"CreateTime\":\"2023-10-23 09:05:02\"},{\"UPN\":\"WR1.04.042.0074273022120800120221205927\",\"PN\":\"1.04.042.0074\",\"Lot\":null,\"DC\":\"20221205\",\"Qty\":2730,\"PositionCode\":\"1-1-1-3\",\"CreateTime\":\"2023-10-25 12:51:21\"}]}";
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
int count = jsonObject.getIntValue("count");
jsonObject.put("total", count);
jsonObject.remove("count");
System.out.println(jsonObject.toJSONString());
}
}