使用Vue和thrift建立前后端交互的demo
初识thrift
thrift 是 facebook 于2007年开发的一款跨平台 RPC(Remote Procedure Call) 软件框架,
它可以在多种平台上进行无缝交互,数据传输使用二进制的方式,比XML和JSON体积更小,适合于内网的之间的数据进行交互。
thrift 结构
(参见https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/)

thrift 是由传输层、协议层和业务组成。用户选定的传输层类型、协议层类型之后,只需要关注业务代码即可,无需关注底层实现。
当生成了一套协议后,由客户端和和服务端根据协议文件生成 thrift 的接口库,
接口库会提供定义的service方法,直接调用方法,远程服务端会返回数据。
thrift类型
接口定义地址;
http://thrift.apache.org/docs/types
基本类型:
- bool 对应js中boolean
- byte 8位无符号整数
- i16 16位无符号整数
- i32 32位无符号整数
- i64 64位无符号整数
- double 64位符点型数字
- string utf-8类型的字符串
- binary 一系列基于string类型的编码的字符串
与Js对应的对象类型,
- struct 结构体,可使用基本类型,强类型,需要定义不同的名称
示例:
struct ListItem {
1: i32 id,
2: string content = '',
3: Status status = 1,
4: string author,
5: i32 textLength
}
容器类型,是不能直接在外层定义的,需要在 struct 中定义或者在 service 中定义,
主要包括:
与Js的数组对应的类型:
- list 一系列的数组元素
与Js中set对应的类型:
- set 相当于不重复的数组
与Js中Map对应的类型
- map 类似于字典模式
其他类型;
异常类型
- exception
可调用接口
- service
示例:
service Todo {
list<ListItem> getTodoList(),
i32 getTotalLength(1: string author),
i8 postTodo(1: PostItem item)
ListItem doneArtical(1: i32 id)
ListItem deleteArtical(1: i32 id)
}
使用thrift实现网页和nodejs服务端进行交互的实践
安装环境
为方便操作,使用vue进行html的开发。首先,需要安装thrift环境(在mac环境下,其他环境请参考http://thrift.apache.org/tutorial/):
brew install thrift
同时安装vue开发的环境,vue/cli,用于直接对单个文件进行开发(其实是为了省事,不想搭webpack环境)。
npm install -g @vue/cli
npm install -g @vue/cli-service-global
新建接口文件
接口文件是我们根据 thrift 定义的类型进行书写。其中除service类型外,其他定义都相当于定义成全局的类型,要注意名字的唯一性,service 是供我们调用的类型,就是接口。
创建的thrift文件如下:
enum Status {
NORMAL = 1,
DONE = 2,
DELETED = 3
}
struct PostItem {
1: string content = '',
2: string author,
}
exception CodeError {
1: i32 code = 0,
2: string message = ''
}
struct ListItem {
1: i32 id,
2: string content = '',
3: Status status = 1,
4: string author,
5: i32 textLength
}
service Todo {
list<ListItem> getTodoList(),
i32 getTotalLength(1: string author),
i8 postTodo(1: PostItem item)
ListItem doneArtical(1: i32 id)
ListItem deleteArtical(1: i32 id)
}
Todo就是我们需要使用的类。
生成接口库文件
thrift -r --gen js:node todo.thrift && thrift -r --gen js todo.thrift
js:node 是供 Nodejs 调用的库文件,js 是浏览器环境的文件(貌似是需要使用grunt进行打包,反正我是用不习惯,只是个示例,直接中在html通过脚本引入了)。生成的文件保存在gen-js 和 gen/nodejs 两个文件夹下,一个是类型文件,一个是接口文件。
建立 server 端代码
由于浏览器和后台交互目前只支持 ajax 的方式,所以我们的服务端是需要搭建http服务器的。
使用 thrift 的 createWebServer即可(注意不要使用示例中的createServer,那个创建的是socket服务,不是Http服务)。同时设置好传输协议为json格式,传输层类型为buffer模式。为接口中的每个 service 添加实现方式。
const thrift = require('thrift')
const Todo = require('./gen-nodejs/Todo')
const tTypes = require('./gen-nodejs/todo_types')
const data = []
let gid = 0
const actions = {
getTodoList () {
return data
},
getTotalLength () {
return data.length
},
postTodo (item) {
const result = new tTypes.ListItem({
content: item.content,
author: item.author,
status: tTypes.Status.NORMAL,
textLength: item.content.length,
id: ++gid
})
data.push(result)
return 0
},
doneArtical (id) {
const result = data.find(item => item.id === id)
if (!result) {
throw new tTypes.CodeError({code: 1, message: '请选择条目!'})
}
result.status = tTypes.Status.DONE
return result
},
deleteArtical (id) {
const index = data.findIndex(item => item.id === id)
const result = data[index]
if (!~result) {
throw new tTypes.CodeError({code: 1, message: '请选择条目!'})
}
data.splice(index, 1)
return result
}
}
const serverOptions = {
// 静态文件服务器路径
files: '.',
// 设置跨域请求
cors: {
'*': true
},
services: {
// 设置service
'/': {
// 传输层类型为buffer模式
transport: thrift.TBufferedTransport,
// 协议类型为json格式
protocol: thrift.TJSONProtocol,
processor: Todo,
handler: actions,
}
}
}
const server = thrift.createWebServer(serverOptions)
server.listen(7878, () => {
console.log(`监听端口:${7878}`)
})
创建浏览器端代码
浏览器代码就是写网页了。为了使用 vue 的 serve 功能,网页的名称需要设置为 App.vue,同时添加个自定义的 html 文件,添加引入 thrift 库脚本:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>新增文章</title>
<meta name="viewport" id="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
</head>
<body>
<div id="app"></div>
<script type='text/javascript' src='http://localhost:7878/thrift-bundle.js'></script>
</body>
</html>
vue文件内容为:
<template>
<div>
<section class="artical-list">
<ul>
<li
v-for="(item, index) in list"
:key="index">
<p>{{item.content}}</p>
<p>作者: {{item.author}}, 当前状态:{{item.status | status}}</p>
<button @click="doneArtical(item)">设置为已阅</button>
<button @click="deleteArtical(item)">删除</button>
</li>
</ul>
</section>
<section class="form-data">
<textarea name="artical" v-model="artical" cols="30" rows="10"></textarea>
<input type="text" name="author" v-model="author"/>
<button @click="postArtical">提交</button>
</section>
</div>
</template>
<script>
/* eslint-disable */
export default {
data () {
return {
list: [],
artical: '',
author: '',
}
},
created () {
this.init()
},
filters: {
status (value) {
const status = ['无', '正常', '已阅', '删除']
return status[value]
},
},
methods: {
init () {
const transport = new Thrift.Transport('http://localhost:7878')
const protocol = new Thrift.Protocol(transport)
const client = new TodoClient(protocol)
this.client = client
this.getList()
},
getList () {
this.client.getTodoList((result) => {
this.list = result
})
},
postArtical () {
const result = new PostItem()
result.content = this.artical
result.author = this.author
this.client.postTodo(result, (result) => {
this.getList()
})
},
doneArtical (item) {
this.client.doneArtical(item.id, (result) => {
if (result instanceof Thrift.TApplicationException) {
alert(result.message)
return
}
this.getList()
})
},
deleteArtical (item) {
this.client.deleteArtical(item.id, (result) => {
if (result instanceof Thrift.TApplicationException) {
alert(result.message)
return
}
this.getList()
})
},
},
}
</script>
主要思路是在初始化先创建接口的实例,设置 transport 的请求地址,然后使用我们定义的 service,
绑定实例在this上。每次要操作时直接调用实例的方法即可。看起来是不是和我们写普通封装好的axios一样?
运行
为方便使用,我们使用 nodemon 进行服务器开发自动重启,我们在 npm 包中添加以下脚本:
"scripts": {
"start": "vue serve & node server.js",
"dev": "vue serve & npm run compile && nodemon server.js",
"compile": "npm run gen && npm run concat",
"gen": "thrift -r --gen js:node todo.thrift && thrift -r --gen js todo.thrift",
"concat": "concat -o thrift-bundle.js ./thrift.js ./gen-js/*.js"
},
这样,我们使用 npm start 启动已经构建好的服务,使用 npm run dev 进行开发,
使用 npm run compile 在改动了 thrift 接口文件后进行重新编译。
这样我们的网页就做好了:

总结
搭建一个简单的 thrift 项目还是很容易的,所有的代码已经放在我的github上https://github.com/wenlonghuo/code-test/tree/master/004_thrift。
其他原理和总结有待后续挖掘。
使用Vue和thrift建立前后端交互的demo的更多相关文章
- 三、vue前后端交互(轻松入门vue)
轻松入门vue系列 Vue前后端交互 六.Vue前后端交互 1. 前后端交互模式 2. Promise的相关概念和用法 Promise基本用法 then参数中的函数返回值 基于Promise处理多个A ...
- .Net Core+Vue.js+ElementUI 实现前后端分离
.Net Core+Vue.js+ElementUI 实现前后端分离 Tags: Vue 架构 前端采用:Vue.js.Element-UI.axios 后端采用:.Net Core Mvc 本项目是 ...
- Servlet实现前后端交互的原理及过程解析
在日常调试项目时,总是利用tomcat去启动项目,并进行前后端联调,但对于前后端的请求响应的交互原理及过程并不是特别清晰. 为什么在前端发出相应请求,就能跳转到后端通过程序得到结果再响应到前端页面呢? ...
- nodejs实现前后端交互
本人nodejs入门级选手,站在巨人(文殊)的肩膀上学习了一些相关知识,有幸在项目中使用nodejs实现了前后端交互,因此,将整个交互过程记录下来,方便以后学习. 本文从宏观讲述nodejs实现前后端 ...
- Vue-CLI项目-axios模块前后端交互(类似ajax提交)
08.31自我总结 Vue-CLI项目-axios前后端交互 一.模块的安装 npm install axios --save #--save可以不用写 二.配置main.js import axio ...
- Node之简单的前后端交互
node是前端必学的一门技能,我们都知道node是用的js做后端,在学习node之前我们有必要明白node是如何实现前后端交互的. 这里写了一个简单的通过原生ajax与node实现的一个交互,刚刚学n ...
- Django之META与前后端交互
Django之META与前后端交互 1 提交表单之GET 前端提交数据与发送 1)提交表单数据 2)提交JSON数据 后端的数据接收与响应 1)接收GET请求数据 2)接收POST请求数据 3)响应请 ...
- 前后端交互实现(nginx,json,以及datatable的问题相关)
1.同源问题解决 首先,在同一个域下搭建网络域名访问,需要nginx软件,下载之后修改部分配置 然后再终端下cmd nginx.exe命令,或者打开nginx.exe文件,会运行nginx一闪而过, ...
- springboot+mybatis+thymeleaf项目搭建及前后端交互
前言 spring boot简化了spring的开发, 开发人员在开发过程中省去了大量的配置, 方便开发人员后期维护. 使用spring boot可以快速的开发出restful风格微服务架构. 本文将 ...
随机推荐
- 2017-07-02(free uptime cat /proc/cpuinfo uname lsb_release)
free -b 字节为单位显示 -k KB为单位显示,默认显示就是KB -m 以MB为单位显示 -g 以GB为单位显示 free -m free 显示说明 uptime 跟top命令第一行内容相同 c ...
- 洛谷P1233 [木棍加工]
主要思路: 这道题一眼看过去就可以贪心.. 首先可以按L排序.. 显然排序之后我们就可以抛开L不管了.. 然后就可以愉快的贪心了.. 细节: 这道题可以看成用 最少的合法序列(详见原题) 装下所有木棍 ...
- impala集成sentry
1.安装配置sentry 详细步骤见上一篇安装配置sentry. 2.配置impala 注:以下配置未集成kerberos安全认证 在/etc/imapla/conf目录下创建sentry-site. ...
- linux ngix安装
因为我完全按照第一篇参考文章从上到下一步步安装导致有些安装失败最后重装的,过程有点乱,就没自己总结please read the follow articles Linux 安装Nginx详细图解教程 ...
- Linux磁盘热插拔命令
对于支持热插拔SCSI技术的服务器,SCSI硬盘和磁带机可以在Linux下实现在线添加和移除,有两种方法实现,先说麻烦的 具体方法如下: 一. 添加或者删除硬盘/磁带机: # echo "s ...
- Jetson TX2刷机教程(原创)
Jetson TX2刷机教程 一,硬件准备 1台host主机(linux系统,最好是ubuntu64位) 1台Jetson TX2的平台 二,软件包 JetPack(Jetson SDK) 下载地址: ...
- 监控mysql主从同步状态
在高并发网站架构中,MySQL数据库主从同步是不可或缺的,不过经常会发生由于网络原因或者操作错误,MySQL主从经常会出现不同步的情况,那么如何监控MySQL主从同步,也变成网站正常运行的重要环节. ...
- 这可能是我觉得最折腾的C++环境配置(编码+调试)--mac+eclipse
本着造福大众的心态,万一可能有人喜欢这种环境开发呢对吧~~折腾了一天,又是谷歌又是百度,讲真遇到报错问题搜出的资料挺少的,看来用这类环境开发C++的人不多,毕竟谁没事干放着xcode,vscode不用 ...
- linux makefile字符串操作函数 替换subst、模式替换patsubst、去首尾空格strip、查找字符串findstring、过滤filter、反过滤filter-out、排序函数sort、取单词word、取单词串wordlist、个数统计words
1.1 字符操作函数使用 在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能.make所支持的函数也不算很多,不过已经足够我们的操作了.函数调用后,函 ...
- Springboot security cas源码陶冶-CasAuthenticationFilter
Springboot security cas整合方案中不可或缺的校验Filter类或者称为认证Filter类,其内部包含校验器.权限获取等,特开辟新地啃啃 继承结构 - AbstractAuthen ...