内容简介:RESTful API的前后端分离实现
在配合后端进行页面开发时,在非MVC时代,页面配合后端数据通常采用的是后端模板(如smarty、jinja等)+前端html进行开发,例如以下代码
也就是采用的是前后端耦合的方式将后端数据渲染出来,这样的方式使得前端页面代码可读性差,在后端数据发生结构变化时,前端还得配合后端数据模板进行修改。使得页面的可维护性大大下降、开发效率下降,个人不是很喜欢这样的开发模式,相比之下,使用RESTful服务器为前端提供API进行页面开发是当前较为推荐的前后端分离模式。
什么是REST?
REST (REpresentational State Transfer) 是Web服务实现方案之一,近年来因其简介的 设计模式 而被广泛采用,如今REST已经变成了web services 和 web APIs 的标配。
REST系统有如下特点:
- 客户端-服务器:客户端与服务器隔离,服务器提供服务,客户端进行消费;
- 无状态:从客户端到服务器的每个请求都必须包含理解请求所必需的信息。也就是说,服务器不会存储客户端上一次请求的信息用来给下一次使用。
- 可缓存:服务器必须明示客户端请求能否缓存。
- 分层系统: 客户端和服务器之间的通信应该以一种标准的方式,就是中间层代替服务器做出响应的时候,客户端不需要做任何变动。
- 统一的接口: 服务器和客户端的通信方法必须是统一的。
- 按需编码: 服务器可以提供可执行代码或脚本,为客户端在它们的环境中执行。这个约束是唯一一个是可选的。
建立一个web service服务器
了解了REST系统,接下来就是通过REST 客户端-服务器
的特点建立一个web service服务器,为前端工作提供API接口。
本文使用的是 Python 的Flask框架进行REST服务器搭建。这个服务器实现了页面端通过API接口以GET、POST等HTTP标准方法进行请求、响应,并将结果以JSON数据的形式返回,从而实现页面应用的开发。
1.设置页面根路径
开发之前需要在服务器端设置页面的根路由,以便在打开指定页面地址时能打开对应的页面,本文以 static
目录下的 index.html
文件作为根路由显示文件:
#设置根路由 @app.route('/') def root(): return app.send_static_file('index.html')
运行服务器,打开 http://127.0.0.1:5000/
即可看到index.html的页面内容。
2.GET API访问数据
根路由创建并且可以访问到 index.html
文件后,接下来就可以利用前端AJAX请求来获取服务器的数据了,因为本文不涉及数据库的使用和操作,所以我将服务器数据内容静态的写在 app.py
中,数据是一个tasks任务的json数据:
#模拟json数据 tasks = [ { 'id': 1, 'title': u'Buy groceries', 'description': u'Milk, Cheese, Pizza, Fruit, Tylenol', 'done': False }, { 'id': 2, 'title': u'Learn Python', 'description': u'Need to find a good Python tutorial on the web', 'done': False } ]
该tasks数据有几个字段,分别是: id
作为每个task的唯一标识符,在后续的修改操作尤其重要; title
是task的标题; description
是task的具体内容; done
表示task是否已完成。
前端页面为了获取数据,可直接采用 GET
方式请求内容,这里将接口命名为 /todo/api/tasks
,请求方式为 GET
:
#GET方法api @app.route('/todo/api/tasks', methods=['GET']) def getTasks(): return jsonify({'tasks': tasks})
为了验证刚才模拟的tasks数据可以访问,在前端页面还没开发时,可以直接访问 /todo/api/tasks
查看数据:运行服务器,访问 http://127.0.0.1:5000/todo/api/tasks
可以直接查看json数据。
3.POST API数据修改数据
用户在进行页面访问时,有可能需要对当前数据库内容进行新增或者删除,此时需要开发一个POST请求的API,可接受前端AJAX参数进行进一步的数据库读取操作。首先是新增tasks任务,API接口名字为 /todo/api/addTask
,方法为 POST
:
#POST方法API,添加数据项 @app.route('/todo/api/addTask', methods=['POST']) def add_task(): pass
结合tasks的数据结构,为了新增task任务,需要有以下参数进行标识:
task = { 'id' : tasks[-1]['id'] + 1, 'title': request.json['title'], 'description' : request.json.get('description', ""), 'done' : False }
其中 request
就是页面AJAX的请求信息。
整合了AJAX的请求信息就可以直接插入现有的数据库中了,完整的POST新增task的代码如下:
#POST方法API,添加数据项 @app.route('/todo/api/addTask', methods=['POST']) def add_task(): if request.json['title'] == "": abort(400) task = { 'id' : tasks[-1]['id'] + 1, 'title': request.json['title'], 'description' : request.json.get('description', ""), 'done' : False } tasks.append(task) #tasks变动后返回新数据到页面,状态码201 return jsonify({'tasks': tasks}), 201
同理,如果需要删除tasks中的某一项,需要以task的id作为标识符,请求方式同样为 POST
:
#POST方法API,删除数据项 @app.route('/todo/api/deleteTask', methods=['POST']) def delete_task(): task_id = request.json['id'] for task in tasks: if task['id'] == task_id: tasks.remove(task) return jsonify({'tasks': tasks}), 201
4.404错误
如果前端访问一个不存在的接口,需要抛出404错误提示:
#404 @app.errorhandler(404) def not_found(error): return make_response(jsonify({'error': 'Not found'}), 404)
API在前端的调用与渲染
前端调用无非就是使用AJAX进行数据请求,AJAX可以使用 XMLHttpRequest
、 $ajax()
等多种方式进行请求。本文使用的是MVVM框架vue.js进行接口调用并渲染页面,接口调用使用 vue-resource
的 $http()
方法。
首先在页面加载时访问接口,并将接口返回的数据渲染到页面上:
data: { tasks: [] }, compiled: function() { var self = this; //在编译后即调用API接口取得服务器端数据 self.$http.get('/todo/api/tasks').then(function(res) { self.tasks = res.data.tasks; }); }
视图模型如下:
<div v-for="task in tasks"> <div> <button @click="deleteTask(task.id)">x</button> </div> <div> </div> </div> <div class="box"> <input type="text" v-model="new_task.title"><br> <textarea cols="30" rows="10" v-model="new_task.description"> </textarea> <button @click="addTask">add</button> </div>
在视图模型中我还加入了可以添加、删除数据的操作 addTask
、 deleteTask
,对应的接口调用方法如下:
methods: { addTask: function() { var self = this; self.$http.post('/todo/api/addTask', { title: self.new_task.title, description: self.new_task.description }).then(function(res) { self.tasks = res.data.tasks; }); }, deleteTask: function(id) { var self = this; self.$http.post('/todo/api/deleteTask', { id: id }).then(function(res) { self.tasks = res.data.tasks; }); } }
此时再打开 http://127.0.0.1:5000/
就可以看到数据渲染、添加、删除等一系列前端效果,至此一个简单的前后端分离的实践已经结束。
路由
有了API接口,在多页面的情况下可以直接使用前端路由进行页面切换,将路由命名、规则完全交给前端。
总结
本文通过Python的Flask框架搭建了一个可以响应GET、POST请求的RESTful服务器,为前端页面提供了相应的操作API接口,同时使用vue.js进行数据请求和渲染,展现了前端页面如何调用API接口,可以看到使用RESTful API进行前后端分离有以下优点:
- 不再使用后端模板语言,前端页面代码可读性大大提高,维护性也大大提高;
- 通过前后端分离,具有数据交互的页面当做SPA开发,前端工程师可以更加专注的开发高性能、用户体验良好的页面;后端工程师只需为前端提供API接口,可以将更多的精力专注与后端的工作,前后端的业务专注度也有很大的提高;
- 如果使用MVVM框架进行页面开发,通过API数据响应可以自动更新dom,不需要开发者直接操作dom,也提高了页面的可维护性。
本文完整代码可直接到 RESRful-API-with-vuejs 进行查看,由于本人对部分知识了解不深,在文章里也写的比较肤浅,还请各位批评指正。
(完)
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。