1.thrift的數(shù)據(jù)類(lèi)型。(這里主要為翻譯官方文檔)
a. 基本數(shù)據(jù)類(lèi)型
1) boolean型,值為true或false
2) byte型,值為單字節(jié)字母
3) i16型,值長(zhǎng)度為16位的integer帶符號(hào)數(shù)字.
4) i32型,值長(zhǎng)度為32位的integer帶符號(hào)數(shù)字.
5) i64型,值長(zhǎng)度為64位的integer帶符號(hào)數(shù)字.
6) double型,值長(zhǎng)度為64的浮點(diǎn)數(shù).
7) string型,字符串或者binary數(shù)據(jù)。
b. 結(jié)構(gòu)體
有點(diǎn)類(lèi)似c的結(jié)構(gòu)體。不怎么懂c的同學(xué)可以理解為不帶方法的類(lèi),只有屬性而已。
型如:
struct
Work {
1
: i32 num1 =
0
,
2
: i32 num2,
3
: Operation op,
4
: optional
string
comment,
}
?
c. 容器
1) list類(lèi)型。
指一組有序元素的集合,類(lèi)似于java的ArrayList類(lèi)。
typedef i32 MyInteger
MyInteger a;
struct
hello{
list
<MyInteger>
d; }
指hello結(jié)構(gòu)體中含有一個(gè)list類(lèi)型的數(shù)據(jù),且里面的元素都必須是a數(shù)據(jù)類(lèi)型的MyInteger數(shù)據(jù)類(lèi)型的數(shù)據(jù),主要這里的typedef起一個(gè)別名的作用。
2) set類(lèi)型
一個(gè)不可重復(fù)的排序元素的集合,類(lèi)似java的hashset,python的set.使用同list
3)?map<type1,type2>類(lèi)型。
使用如:
map<
string
,
string
> MAPCONSTANT = {
'
hello
'
:
'
world
'
,
'
goodnight
'
:
'
moon
'
}
4) 枚舉類(lèi)型
?
2. 服務(wù)
有了數(shù)據(jù)結(jié)構(gòu),那么就該對(duì)數(shù)據(jù)進(jìn)行操作。thrift這里所說(shuō)的服務(wù),不可能針對(duì)我們自己的業(yè)務(wù)邏輯,而是指的是服務(wù)端從端口讀取數(shù)據(jù),客戶(hù)端傳入數(shù)據(jù)的一套方法。
service <服務(wù)名>{
<返回類(lèi)型> <方法名>(參數(shù)) throws <異常>
}
3. 實(shí)踐:
根據(jù)前面所說(shuō)數(shù)據(jù)類(lèi)型和結(jié)構(gòu)體,編寫(xiě)如下thrift文件,名為 test.thrift
i32 a;
i32 b;
string
c;
list
<
string
>
d;
map
<
string
,
string
> e = {
"
hello
"
:
"
world
"
,
"
dd
"
:
"
ee
"
};
struct
f{
1
:a,
2
:b,
3
:c=
2
,
4
:d=
"
ceshi
"
,
5
:e,
}
service Hello{
f get_f(
1
:f gg) throws (Exception, e)
}
以上代碼使用thrift的標(biāo)準(zhǔn)命令(thrift.exe -gen py test.thrift)是不成功,因?yàn)檎Z(yǔ)法還是不正確!
修改
1.常量量如a,b,c,d, e要使用const修飾。
2. 如果都使用了const修飾,但有;號(hào),還是不成功,盡管有的人說(shuō)thrift對(duì);不敏感,那還是估計(jì)看版本的,這里我使用的是最新的0.8版本。也就是說(shuō),如果你是一個(gè)java或者php程序員,請(qǐng)注意沒(méi)有";"
3. 靜態(tài)變量請(qǐng)賦值,如const i32 a = "helloworld"
4. 結(jié)構(gòu)體內(nèi)部的屬性請(qǐng)指定參數(shù)類(lèi)型,因?yàn)榻Y(jié)構(gòu)體內(nèi)部屬性和外部的靜態(tài)屬性沒(méi)有任何關(guān)系。
5. 異常之間沒(méi)有“,”分割,以空格代替
6. Exception類(lèi)型請(qǐng)定義。
7. throws參數(shù)也要指定是第幾個(gè)參數(shù)
好了,修改后的thrift腳本變?yōu)?
const
i32 a =
1
const
i32 b =
2
const
string
c =
"
helloworld
"
const
list<
string
> d =
"
test
"
const
map<
string
,
string
> e = {
"
hello
"
:
"
world
"
,
"
dd
"
:
"
ee
"
}
struct
f{
1
:i32 a,
2
:i32 b,
3
:
string
c,
4
:list<
string
> d=[
"
ceshi
"
],
5
:map<
string
,
string
> e = {
"
hello
"
:
"
world
"
},
}
exception Exception{
1
:i32 what;
2
:
string
where
;
}
service Hello{
f get_f(
1
:f gg) throws (
1
:Exception e)
}
稍微有那么一點(diǎn)像生產(chǎn)環(huán)境了,生成代碼結(jié)構(gòu):
我們可以讓這個(gè)隨便編寫(xiě)的腳本為我們完成一點(diǎn)點(diǎn)功能,比如get_f讓他對(duì)結(jié)構(gòu)體f的對(duì)象gg的各種值計(jì)算,當(dāng)然生成環(huán)境也可以集成數(shù)據(jù)庫(kù)了。
?
那么現(xiàn)在需要幾個(gè)數(shù)據(jù)通信接口了。
1.?讀取數(shù)據(jù):readMessageBegin()
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
從端口讀取請(qǐng)求流,獲取3個(gè)值。
readMessageEnd() 讀取數(shù)據(jù)結(jié)束。
2.?readStructBegin() 開(kāi)始讀取結(jié)構(gòu)體
readStructEnd() 讀取結(jié)構(gòu)體結(jié)束
3.?readFieldBegin() 讀取屬性開(kāi)始
readFieldEnd()
4.?readMapBegin()讀取map開(kāi)始
readMapEnd()讀取map結(jié)束。
這里的數(shù)據(jù)接口還有很多,不一一列舉,因?yàn)槲覀冊(cè)趯?shí)際使用thrift的時(shí)候,只要不類(lèi)似于修改thrift源碼的操作,都不需要關(guān)心這些具體的數(shù)據(jù)操作。
?
接下來(lái)我們做客戶(hù)端和服務(wù)端的操作,同時(shí)在服務(wù)端進(jìn)行具體業(yè)務(wù)的處理。
?
1. 編寫(xiě)借口類(lèi).
import sys
sys.path.append(
"
../gen-py
"
)
from
cc import Hello
from
cc import ttypes
class
My_Handler(Hello.Iface):
def get_f(self, gg):
#對(duì)對(duì)象gg進(jìn)行梳理
gg.a
= gg.a +
gg.b
gg.b
= gg.a -
gg.b
return
gg
官方事例的CalculatorHandler是不繼承Iface的,而我這里采用繼承Hello.Iface,并沒(méi)有別的深意,是表示一定要有我們定義thrift文件的get_f方法。假如我們的邏輯更加復(fù)雜,handler處理里有數(shù)據(jù)庫(kù)操作等等,繼承不繼承Iface都是可以的。
官方的handler(部分):
class
CalculatorHandler:
def __init__(self):
self.log
=
{}
def ping(self):
print
'
ping()
'
def add(self, n1, n2):
print
'
add(%d,%d)
'
%
(n1, n2)
return
n1+n2
接下來(lái)要對(duì)這個(gè)handler要對(duì)這個(gè)hander進(jìn)行處理:
import sys
sys.path.append(
"
../gen-py
"
)
from
cc import Hello
from
cc import ttypes
class
My_Handler(Hello.Iface):
def get_f(self, gg):
#對(duì)對(duì)象gg進(jìn)行梳理
gg.a
= gg.a +
gg.b
gg.b
= gg.a -
gg.b
return
gg
handler
=
My_Handler()
process
=
Hello.Processor(handler)
from
thrift.transport.TSocket import TServerSocket
server
= TServerSocket(host=
"
localhost
"
, port =
9090
)
from
thrift.transport.TTransport import TBufferedTransportFactory
tfactory
=
TBufferedTransportFactory()
from
thrift.protocol.TBinaryProtocol import TBinaryProtocolFactory
bfactory
=
TBinaryProtocolFactory()
from
thrift.server.TServer import TSimpleServer
servers
=
TSimpleServer(process, server, tfactory, bfactory)
print
"
starting the server...
"
servers.serve()
print
"
done...
"
直接上代碼了。注意,這里的TServerSocket一定要指定,因?yàn)楣俜降念?lèi)初始化時(shí)host賦初值居然寫(xiě)的none,等于沒(méi)有寫(xiě)麼。
class
TServerSocket(TSocketBase, TServerTransportBase):
"""
Socket implementation of TServerTransport base.
"""
def __init__(self, host
=None, port=
9090
, unix_socket=None):
一個(gè)沒(méi)有host的服務(wù),可以想象會(huì)是什么樣子,使用netstat -na查看端口:
TCP [::]:9090 [::]:0 LISTENING
就是沒(méi)有host導(dǎo)致的情況。
一個(gè)host定義為localhost的服務(wù),使用netstat -na查看端口:
TCP 127.0.0.1:9090 0.0.0.0:0 LISTENING
?
接下來(lái)編寫(xiě)客戶(hù)端,客戶(hù)端的編寫(xiě)主要是是實(shí)例化Hello.Client對(duì)象
__author__ =
'
CLTANG
'
#
! -*- encoding:utf-
8
-*-
'''
客戶(hù)端
'''
import sys
sys.path.append(
"
../gen-py
"
)
from
cc import Hello
from
cc import ttypes
from
thrift.transport import TSocket
from
thrift.transport import TTransport
from
thrift.protocol.TBinaryProtocol import TBinaryProtocol
transport
= TSocket.TSocket(
'
localhost
'
,
9090
)
# Buffering
is
critical. Raw sockets are very slow
transport
=
TTransport.TBufferedTransport(transport)
# Wrap
in
a protocol
protocol
=
TBinaryProtocol(transport)
client
=
Hello.Client(protocol)
transport.open()
ff
= ttypes.f(a=
1
,b=
2
)
results
=
client.get_f(ff)
print results
transport.close()
執(zhí)行客戶(hù)端程序,最終將輸出:
f(a=3, c='helloworld', b=1, e={'cc': 'dd', 'ee': 'ff'}, d=['hello', 'world'])
達(dá)到了我們最早定義在test.thrift中的service的內(nèi)容,即傳入f類(lèi)型的實(shí)例化對(duì)象,調(diào)用get_f方法,返回一個(gè)經(jīng)過(guò)處理的f類(lèi)型的實(shí)例化對(duì)象。
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

