REST API [一]

时间:2021-03-03 11:48:34   收藏:0   阅读:0

一. 概念

1.1 REST API概念

Representational State Transfer 的简称

rest api 是前后端分离最佳实践,是开发的一套标准或者说是一套规范,不是框架

用于Http服务器和客户端的数据交换,好处:

1、轻量,直接通过http,不需要额外的协议。
2、面向资源,一目了然,具有自解释性
3、数据描述简单,一般通过json或者xml做数据通讯

技术图片

1.2 六大原则

1. C-S架构
数据的存储在Server端,Client端只需使用就行。两端彻底分离的好处使client端代码的可移植性变强,Server端的拓展性变强。两端单独开发,互不干扰。

2. 无状态
http请求本身就是无状态的,基于C-S架构,客户端的每一次请求带有充分的信息能够让服务端识别。请求所需的一些信息都包含在URL的查询参数、header、body,服务端能够根据请求的各种参数,无需保存客户端的状态,将响应正确返回给客户端。无状态的特征大大提高的服务端的健壮性和可拓展性。

当然这总无状态性的约束也是有缺点的,客户端的每一次请求都必须带上相同重复的信息确定自己的身份和状态(这也是必须的),造成传输数据的冗余性,但这种确定对于性能和使用来说,几乎是忽略不计的。

3.统一的接口
这个才是REST架构的核心,统一的接口对于RESTful服务非常重要。客户端只需要关注实现接口就可以,接口的可读性加强,使用人员方便调用。

4.一致的数据格式
服务端返回的数据格式要么是XML,要么是Json(获取数据),或者直接返回状态码,有兴趣的可以看看博客园的开放平台的操作数据的api,post、put、patch都是返回的一个状态码 。

自我描述的信息,每项数据应该是可以自我描述的,方便代码去处理和解析其中的内容。比如通过HTTP返回的数据里面有 [MIME type ]信息,我们从MIME type里面可以知道数据的具体格式,是图片,视频还是JSON,客户端通过body内容、查询串参数、请求头和URI(资源名称)来传送状态。服务端通过body内容,响应码和响应头传送状态给客户端。这项技术被称为超媒体(或超文本链接)。

除了上述内容外,HATEOS也意味着,必要的时候链接也可被包含在返回的body(或头部)中,以提供URI来检索对象本身或关联对象。下文将对此进行更详细的阐述。

如请求一条微博信息,服务端响应信息应该包含这条微博相关的其他URL,客户端可以进一步利用这些URL发起请求获取感兴趣的信息,再如分页可以从第一页的返回数据中获取下一页的URT也是基于这个原理。

4.系统分层
客户端通常无法表明自己是直接还是间接与端服务器进行连接,分层时同样要考虑安全策略。

5.可缓存
在万维网上,客户端可以缓存页面的响应内容。因此响应都应隐式或显式的定义为可缓存的,若不可缓存则要避免客户端在多次请求后用旧数据或脏数据来响应。管理得当的缓存会部分地或完全地除去客户端和服务端之间的交互,进一步改善性能和延展性。

6.按需编码、可定制代码(可选)
服务端可选择临时给客户端下发一些功能代码让客户端来执行,从而定制和扩展客户端的某些功能。比如服务端可以返回一些 Javascript 代码让客户端执行,去实现某些特定的功能。提示:REST架构中的设计准则中,只有按需编码为可选项。如果某个服务违反了其他任意一项准则,严格意思上不能称之为RESTful风格。

技术图片

1.3 REST模式方法

1. POST  /url     创建  

    • 200(OK)- 如果现有资源已被更改
    • 201(created)- 如果新资源被创建
    • 202(accepted)- 已接受处理请求但尚未完成(异步处理)
    • 301(Moved Permanently)- 资源的URI被更新
    • 303(See Other)- 其他(如,负载均衡)
    • 400(bad request)- 指代坏请求
    • 404 (not found)- 资源不存在
    • 406 (not acceptable)- 服务端不支持所需表示
    • 409 (conflict)- 通用冲突
    • 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
    • 415 (unsupported media type)- 接受到的表示不受支持
    • 500 (internal server error)- 通用错误响应
    • 503 (Service Unavailable)- 服务当前无法处理请求

2. PUT    /url/xxx 更新或创建

3. GET    /url/xxx 查看

4. DELETE  /url 删除

二. Express JS实现

用ExpressJS实现用例

Server:

首先新建NodeJS项目作为Server,安装body-parser和express

1 "dependencies": {
2     "body-parser": "^1.19.0",
3     "express": "^4.17.1",
4   },

实现Controller:/controller/feed.js

 1 exports.getPosts = (req, res, next) => {
 2   res.status(200).json({
 3     posts: [{ title: ‘First Post‘, content: ‘This is the first post!‘ }]
 4   });
 5   // res.status(404).json({
 6   //   posts: [{ title: ‘First Post‘, content: ‘This is the first post!‘ }]
 7   // })
 8 };
 9 
10 exports.createPost = (req, res, next) => {
11   const title = req.body.title;
12   const content = req.body.content;
13   console.log(title, content);
14   // Create post in db
15   res.status(201).json({
16     message: ‘Post created successfully!‘,
17     post: { id: new Date().toISOString(), title: title, content: content }
18   });
19 };

新建一个Route:/route/feed.js

 1 const express = require(‘express‘);
 2 
 3 const feedController = require(‘../controller/feed‘);
 4 
 5 const router = express.Router();
 6 
 7 // GET /feed/posts
 8 router.get(‘/posts‘, feedController.getPosts);
 9 
10 // POST /feed/post
11 router.post(‘/posts‘, feedController.createPost);
12 
13 module.exports = router;

程序入口:

 1 const express = require(‘express‘);
 2 const bodyParser = require(‘body-parser‘);
 3 
 4 const feedRoutes = require(‘./routes/feed‘);
 5 
 6 const app = express();
 7 
 8 // app.use(bodyParser.urlencoded()); // x-www-form-urlencoded <form>
 9 app.use(bodyParser.json()); // application/json
10 
11 app.use((req, res, next) => {
12     res.setHeader(‘Access-Control-Allow-Origin‘, ‘*‘);
13     res.setHeader(‘Access-Control-Allow-Methods‘, ‘GET, POST, PUT, PATCH, DELETE‘);
14     res.setHeader(‘Access-Control-Allow-Headers‘, ‘Content-Type, Authorization‘);
15     next();
16 })
17 
18 app.use(‘/feed‘, feedRoutes);
19 
20 app.listen(8080);

npm start 启动server

Client:

新建2个按钮用于GET和POST

1 <button id="get">Get Posts</button>
2 <button id="post">Create a Post</button>

JS:

 1 const getButton = document.getElementById(‘get‘);
 2 const postButton = document.getElementById(‘post‘);
 3 
 4 getButton.addEventListener(‘click‘, ()=>{
 5   fetch(‘http://localhost:8080/feed/posts‘)
 6     .then(res => res.json())
 7     .then(resData => console.log(resData))
 8     .catch(err => console.log(err));
 9 });
10 
11 postButton.addEventListener(‘click‘, ()=>{
12   fetch(‘http://localhost:8080/feed/posts‘, {
13     method:‘POST‘,
14     body:JSON.stringify({
15       title:‘A Codepen Post‘,
16       content:‘Created via Codepen‘
17     }),
18     headers: {
19       ‘Content-Type‘:‘Application/json‘
20     }
21   })
22     .then(res => res.json())
23     .then(resData => console.log(resData))
24     .catch(err => console.log(err));
25 });

触发按钮,通过Chrome Console可看到已经Log:

技术图片

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!