博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Thrift使用教程(Java版本)
阅读量:6708 次
发布时间:2019-06-25

本文共 55808 字,大约阅读时间需要 186 分钟。

hot3.png

在之前的一篇博文【】中,给出了一个使用thrift完成rpc的示例。

在本篇博文,我们会给出一个使用Thrift的基本教程~

Thrift简介

Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现

Thrift协议栈

Thrift 客户端、服务端API架构如下图所示:

152941_UgxQ_2911530.png

图片来自

Thrift的网络栈如下所示:

151556_XR0f_2911530.png

Transport

Transport层提供了一个简单的网络读写抽象层。这使得thrift底层的transport从系统其它部分(如:序列化/反序列化)解耦。以下是一些Transport接口提供的方法:

openclosereadwriteflush

更加详细方法如,

153933_QVO7_2911530.png

Thrift支持如下几种Transport:

183136_NiTt_2911530.png

  • TIOStreamTransport和TSocket这两个类的结构对应着阻塞同步IO, TSocket封装了Socket接口
  • TNonblockingTrasnsort,TNonblockingSocket这两个类对应着非阻塞IO
  • TMemoryInputTransport封装了一个字节数组byte[]来做输入流的封装
  • TMemoryBuffer使用字节数组输出流ByteArrayOutputStream做输出流的封装
  • TFramedTransport则封装了TMemoryInputTransport做输入流,封装了TByteArryOutPutStream做输出流,作为内存读写缓冲区的一个封装。TFramedTransport的flush方法时,会先写4个字节的输出流的长度作为消息头,然后写消息体。和FrameBuffer的读消息对应起来。FrameBuffer对消息时,先读4个字节的长度,再读消息体
  • TFastFramedTransport是内存利用率更高的一个内存读写缓存区,它使用自动增长的byte[](不够长度才new),而不是每次都new一个byte[],提高了内存的使用率。其他和TFramedTransport一样,flush时也会写4个字节的消息头表示消息长度。

Protocol

Protocol抽象层定义了一种将内存中数据结构映射成可传输格式的机制。换句话说,Protocol定义了datatype怎样使用底层的Transport对自己进行编解码。因此,Protocol的实现要给出编码机制并负责对数据进行序列化。

Thrift支持如下几种protocols:

182701_4fLw_2911530.png

  • TBinaryProtocol : 二进制格式.
  • TCompactProtocol : 压缩格式
  • TJSONProtocol : JSON格式
  • TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析
  • 等等

主要的方法有:

writeMessageBegin(name, type, seq)writeMessageEnd()writeStructBegin(name)writeStructEnd()writeFieldBegin(name, type, id)writeFieldEnd()writeFieldStop()writeMapBegin(ktype, vtype, size)writeMapEnd()writeListBegin(etype, size)writeListEnd()writeSetBegin(etype, size)writeSetEnd()writeBool(bool)writeByte(byte)writeI16(i16)writeI32(i32)writeI64(i64)writeDouble(double)writeString(string)

读操作~

name, type, seq = readMessageBegin()                  readMessageEnd()name = readStructBegin()       readStructEnd()name, type, id = readFieldBegin()                 readFieldEnd()k, v, size = readMapBegin()             readMapEnd()etype, size = readListBegin()              readListEnd()etype, size = readSetBegin()              readSetEnd()bool = readBool()byte = readByte()i16 = readI16()i32 = readI32()i64 = readI64()double = readDouble()string = readString()

Processor

Processor封装了从输入数据流中读数据和向数据数据流中写数据的操作。读写数据流用Protocol对象表示。

Processor的结构体非常简单:

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * *   http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */package org.apache.thrift;import org.apache.thrift.protocol.TProtocol;/** * A processor is a generic object which operates upon an input stream and * writes to some output stream. * */public interface TProcessor {  public boolean process(TProtocol in, TProtocol out)    throws TException;}

与服务相关的processor实现由编译器产生。

Processor主要工作流程如下:

从连接中读取数据(使用输入protocol),将处理授权给handler(由用户实现),最后将结果写到连接上(使用输出protocol)。

Server

Server将以上所有特性集成在一起,Server实现的几个步骤如下~

(1)  创建一个transport对象

(2)  为transport对象创建输入输出protocol

(3)  基于输入输出protocol创建processor

(4)  等待连接请求并将之交给processor处理

示例:

package com.xxx.tutorial.thrift.server;import java.util.logging.Logger;import org.apache.thrift.TProcessor;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.server.TServer;import org.apache.thrift.server.TSimpleServer;import org.apache.thrift.transport.TServerSocket;import com.xxx.tutorial.thrift.service.UserService;import com.xxx.tutorial.thrift.service.impl.UserServiceImpl;/** * @author wangmengjun * */public class TSimpleServerExample {	private static final Logger logger = Logger.getLogger(TSimpleServerExample.class.getName());	private static final int SERVER_PORT = 9123;	public static void main(String[] args) {		try {						/**			 * 1. 创建Transport			 */			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);			TServer.Args tArgs = new TServer.Args(serverTransport);						/**			 * 2. 为Transport创建Protocol			 */			tArgs.protocolFactory(new TBinaryProtocol.Factory());			// tArgs.protocolFactory(new TCompactProtocol.Factory());			// tArgs.protocolFactory(new TJSONProtocol.Factory());						/**			 * 3. 为Protocol创建Processor			 */			TProcessor tprocessor = new UserService.Processor
(new UserServiceImpl()); tArgs.processor(tprocessor); /** * 4. 创建Server并启动 * * org.apache.thrift.server.TSimpleServer - 简单的单线程服务模型,一般用于测试 */ TServer server = new TSimpleServer(tArgs); logger.info("UserService TSimpleServer start ...."); server.serve(); } catch (Exception e) { logger.severe("Server start error!!!" + e.getLocalizedMessage()); e.printStackTrace(); } }}

 

Thrift类型系统

Thrift类型系统包括预定义的基本类型(如bool , byte, double, string)、特殊类型(如binary)、用户自定义结构体(看上去像C 语言的结构体)、容器类型(如list,set,map)以及异常和服务定义~

基本类型(Base Type)

bool    : 布尔类型(true or value),占一个字节 byte/i8 : 有符号字节 i16     :  16位有符号整型 i32     :  32位有符号整型 i64     :  64位有符号整型 double  : 64位浮点数 string  : 未知编码或者二进制的字符串

注意,

thrift不支持无符号整型,因为很多目标语言不存在无符号整型(如java)。

特殊类型(Special type)

binary   : 未经过编码的字节流

Thrift基本类型、特殊类型和Java类型的对应关系如下表所示:

073149_S607_2911530.png

容器(container)

Thrift容器与类型密切相关,它与当前流行编程语言提供的容器类型相对应,Thrift提供了3种容器类型:

List
:一系列t1类型的元素组成的有序表,元素可以重复 Set
:一系列t1类型的元素组成的无序表,元素唯一Map
:key/value对(key的类型是t1且key唯一,value类型是t2)

注意:

容器中的元素类型可以是除了service之外的任何合法thrift类型(包括结构体和异常)。

Thrift容器类型和Java类型的对应关系如下表所示:

073207_hAJM_2911530.png

结构(struct)

Thrift结构体在概念上同C语言结构体类型—-一种将相关属性聚集(封装)在一起的方式。在面向对象语言中,thrift结构体被转换成类,在Java语言中,这等价于JavaBean的概念~

如,

struct  User {    1:i32 userId,  2:string name}

异常(Exception)

异常在语法和功能上类似于结构体,只不过异常使用关键字exception而不是struct关键字声明。

但它在语义上不同于结构体—当定义一个RPC服务时,开发者可能需要声明一个远程方法抛出一个异常。

如,

exception MyException {	1: string code;	2: string message;}

服务(Service)

一个服务包含一系列命名函数,每个函数包含一系列的参数以及一个返回类型。

在语法上,服务等价于定义一个接口或者纯虚抽象类~

格式如下,

service 
{
(
) [throws (
)]...}

如,

service  UserService {    string sayHello(1:string name);}

其它语法参考

Typedefs

Thrift支持C/C++风格的typedef, 如

typedef i32 MyInteger

说明:

a.  末尾没有逗号

b.   struct可以使用typedef

typedef i32 MyInteger  struct  User {    1:MyInteger userId,  2:string name}

枚举Enums

可以像C/C++那样定义枚举类型,如:

enum Gender {	MALE,	FEMALE,	UNKONWN}

注释Comments

Thrfit支持shell注释风格,C/C++语言中单行或者多行注释风格

# This is a valid comment. /* * This is a multi-line comment. * Just like in C. */ // C++/Java style single-line comments work just as well.

命名空间Namespace

Thrift中的命名空间同C++中的namespace和java中的package类似,它们均提供了一种组织(隔离)代码的方式。因为每种语言均有自己的命名空间定义方式(如python中有module),thrift允许开发者针对特定语言定义namespace:

namespace cpp com.example.project  // a namespace java com.example.project // b

Includes

Thrift允许thrift文件包含,用户需要使用thrift文件名作为前缀访问被包含的对象,如:

include "user.thrift"namespace java com.xxx.tutorial.thrift.service  service  UserService {    string sayHello(1:string name),    bool saveUser(1:user.User user)}

说明:

a.  thrift文件名要用双引号包含,末尾没有逗号或者分号

b.  注意user前缀

常量Constants

Thrift允许用户定义常量,复杂的类型和结构体可使用JSON形式表示。

const i32 INT_CONST = 1234;    // a const map
MAP_CONST = {"hello": "world", "goodnight": "moon"}

编写一个Thrift文件

有了上述Thrift IDL的语法参考之外,我们就可以来根据这些语法信息,编写thrift文件,并完成生成java代码,结合示例来体验一把~

基本类型和特殊类型

定义一个types.thrift文件,内容如下:

struct Types {		1: bool boolValue;	        2: i8   byteValue;        3: i16  shortValue;        4: i32  intValue;        5: i64  longValue;        6: double doubleValue;        7: string stringValue;        8: binary binaryValue;	}

根据types.thrift生成的Types.java文件,类型相关的部分代码如下:

/** * Autogenerated by Thrift Compiler (0.10.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING *  @generated */@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-06-08")public class Types implements org.apache.thrift.TBase
, java.io.Serializable, Cloneable, Comparable
{ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Types"); private static final org.apache.thrift.protocol.TField BOOL_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("boolValue", org.apache.thrift.protocol.TType.BOOL, (short)1); private static final org.apache.thrift.protocol.TField BYTE_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("byteValue", org.apache.thrift.protocol.TType.BYTE, (short)2); private static final org.apache.thrift.protocol.TField SHORT_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("shortValue", org.apache.thrift.protocol.TType.I16, (short)3); private static final org.apache.thrift.protocol.TField INT_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("intValue", org.apache.thrift.protocol.TType.I32, (short)4); private static final org.apache.thrift.protocol.TField LONG_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("longValue", org.apache.thrift.protocol.TType.I64, (short)5); private static final org.apache.thrift.protocol.TField DOUBLE_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("doubleValue", org.apache.thrift.protocol.TType.DOUBLE, (short)6); private static final org.apache.thrift.protocol.TField STRING_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("stringValue", org.apache.thrift.protocol.TType.STRING, (short)7); private static final org.apache.thrift.protocol.TField BINARY_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("binaryValue", org.apache.thrift.protocol.TType.STRING, (short)8); private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new TypesStandardSchemeFactory(); private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new TypesTupleSchemeFactory(); public boolean boolValue; // required public byte byteValue; // required public short shortValue; // required public int intValue; // required public long longValue; // required public double doubleValue; // required public java.lang.String stringValue; // required public java.nio.ByteBuffer binaryValue; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { BOOL_VALUE((short)1, "boolValue"), BYTE_VALUE((short)2, "byteValue"), SHORT_VALUE((short)3, "shortValue"), INT_VALUE((short)4, "intValue"), LONG_VALUE((short)5, "longValue"), DOUBLE_VALUE((short)6, "doubleValue"), STRING_VALUE((short)7, "stringValue"), BINARY_VALUE((short)8, "binaryValue"); private static final java.util.Map
byName = new java.util.HashMap
(); static { for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { byName.put(field.getFieldName(), field); } } /** * Find the _Fields constant that matches fieldId, or null if its not found. */ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { case 1: // BOOL_VALUE return BOOL_VALUE; case 2: // BYTE_VALUE return BYTE_VALUE; case 3: // SHORT_VALUE return SHORT_VALUE; case 4: // INT_VALUE return INT_VALUE; case 5: // LONG_VALUE return LONG_VALUE; case 6: // DOUBLE_VALUE return DOUBLE_VALUE; case 7: // STRING_VALUE return STRING_VALUE; case 8: // BINARY_VALUE return BINARY_VALUE; default: return null; } } /** * Find the _Fields constant that matches fieldId, throwing an exception * if it is not found. */ public static _Fields findByThriftIdOrThrow(int fieldId) { _Fields fields = findByThriftId(fieldId); if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); return fields; } /** * Find the _Fields constant that matches name, or null if its not found. */ public static _Fields findByName(java.lang.String name) { return byName.get(name); } private final short _thriftId; private final java.lang.String _fieldName; _Fields(short thriftId, java.lang.String fieldName) { _thriftId = thriftId; _fieldName = fieldName; } public short getThriftFieldId() { return _thriftId; } public java.lang.String getFieldName() { return _fieldName; } } // isset id assignments private static final int __BOOLVALUE_ISSET_ID = 0; private static final int __BYTEVALUE_ISSET_ID = 1; private static final int __SHORTVALUE_ISSET_ID = 2; private static final int __INTVALUE_ISSET_ID = 3; private static final int __LONGVALUE_ISSET_ID = 4; private static final int __DOUBLEVALUE_ISSET_ID = 5; private byte __isset_bitfield = 0; public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); tmpMap.put(_Fields.BOOL_VALUE, new org.apache.thrift.meta_data.FieldMetaData("boolValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL))); tmpMap.put(_Fields.BYTE_VALUE, new org.apache.thrift.meta_data.FieldMetaData("byteValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BYTE))); tmpMap.put(_Fields.SHORT_VALUE, new org.apache.thrift.meta_data.FieldMetaData("shortValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I16))); tmpMap.put(_Fields.INT_VALUE, new org.apache.thrift.meta_data.FieldMetaData("intValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); tmpMap.put(_Fields.LONG_VALUE, new org.apache.thrift.meta_data.FieldMetaData("longValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64))); tmpMap.put(_Fields.DOUBLE_VALUE, new org.apache.thrift.meta_data.FieldMetaData("doubleValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE))); tmpMap.put(_Fields.STRING_VALUE, new org.apache.thrift.meta_data.FieldMetaData("stringValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.BINARY_VALUE, new org.apache.thrift.meta_data.FieldMetaData("binaryValue", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true))); metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Types.class, metaDataMap); } public Types() { } public Types( boolean boolValue, byte byteValue, short shortValue, int intValue, long longValue, double doubleValue, java.lang.String stringValue, java.nio.ByteBuffer binaryValue) { this(); this.boolValue = boolValue; setBoolValueIsSet(true); this.byteValue = byteValue; setByteValueIsSet(true); this.shortValue = shortValue; setShortValueIsSet(true); this.intValue = intValue; setIntValueIsSet(true); this.longValue = longValue; setLongValueIsSet(true); this.doubleValue = doubleValue; setDoubleValueIsSet(true); this.stringValue = stringValue; this.binaryValue = org.apache.thrift.TBaseHelper.copyBinary(binaryValue); } /** * Performs a deep copy on
other. */ public Types(Types other) { __isset_bitfield = other.__isset_bitfield; this.boolValue = other.boolValue; this.byteValue = other.byteValue; this.shortValue = other.shortValue; this.intValue = other.intValue; this.longValue = other.longValue; this.doubleValue = other.doubleValue; if (other.isSetStringValue()) { this.stringValue = other.stringValue; } if (other.isSetBinaryValue()) { this.binaryValue = org.apache.thrift.TBaseHelper.copyBinary(other.binaryValue); } } public Types deepCopy() { return new Types(this); } @Override public void clear() { setBoolValueIsSet(false); this.boolValue = false; setByteValueIsSet(false); this.byteValue = 0; setShortValueIsSet(false); this.shortValue = 0; setIntValueIsSet(false); this.intValue = 0; setLongValueIsSet(false); this.longValue = 0; setDoubleValueIsSet(false); this.doubleValue = 0.0; this.stringValue = null; this.binaryValue = null; } public boolean isBoolValue() { return this.boolValue; } public Types setBoolValue(boolean boolValue) { this.boolValue = boolValue; setBoolValueIsSet(true); return this; } ... ...}

可以看出来,thrift文件中定义的类型,转换成java代码的类型,和下面表格展示的是一致的~

073149_S607_2911530.png

枚举类

定义一个枚举 gender.thrift

enum Gender {	MALE,	FEMALE,	UNKONWN}

根据gender.thrift生成的java代码如下:

/** * Autogenerated by Thrift Compiler (0.10.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING *  @generated */import java.util.Map;import java.util.HashMap;import org.apache.thrift.TEnum;public enum Gender implements org.apache.thrift.TEnum {  MALE(0),  FEMALE(1),  UNKONWN(2);  private final int value;  private Gender(int value) {    this.value = value;  }  /**   * Get the integer value of this enum value, as defined in the Thrift IDL.   */  public int getValue() {    return value;  }  /**   * Find a the enum type by its integer value, as defined in the Thrift IDL.   * @return null if the value is not found.   */  public static Gender findByValue(int value) {     switch (value) {      case 0:        return MALE;      case 1:        return FEMALE;      case 2:        return UNKONWN;      default:        return null;    }  }}

异常exception

创建一个exception.thrift文件,并写入如下几个属性~

exception MyException {	1: string code;	2: string message;}

根据exception.thrift生成java代码

/** * Autogenerated by Thrift Compiler (0.10.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING *  @generated */@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-06-08")public class MyException extends org.apache.thrift.TException implements org.apache.thrift.TBase
, java.io.Serializable, Cloneable, Comparable
{ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("MyException"); private static final org.apache.thrift.protocol.TField CODE_FIELD_DESC = new org.apache.thrift.protocol.TField("code", org.apache.thrift.protocol.TType.STRING, (short)1); private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)2); private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new MyExceptionStandardSchemeFactory(); private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new MyExceptionTupleSchemeFactory(); public java.lang.String code; // required public java.lang.String message; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { CODE((short)1, "code"), MESSAGE((short)2, "message"); private static final java.util.Map
byName = new java.util.HashMap
(); static { for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { byName.put(field.getFieldName(), field); } } /** * Find the _Fields constant that matches fieldId, or null if its not found. */ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { case 1: // CODE return CODE; case 2: // MESSAGE return MESSAGE; default: return null; } } /** * Find the _Fields constant that matches fieldId, throwing an exception * if it is not found. */ public static _Fields findByThriftIdOrThrow(int fieldId) { _Fields fields = findByThriftId(fieldId); if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); return fields; } /** * Find the _Fields constant that matches name, or null if its not found. */ public static _Fields findByName(java.lang.String name) { return byName.get(name); } private final short _thriftId; private final java.lang.String _fieldName; _Fields(short thriftId, java.lang.String fieldName) { _thriftId = thriftId; _fieldName = fieldName; } public short getThriftFieldId() { return _thriftId; } public java.lang.String getFieldName() { return _fieldName; } } // isset id assignments public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); tmpMap.put(_Fields.CODE, new org.apache.thrift.meta_data.FieldMetaData("code", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(MyException.class, metaDataMap); } public MyException() { } public MyException( java.lang.String code, java.lang.String message) { this(); this.code = code; this.message = message; } /** * Performs a deep copy on
other. */ public MyException(MyException other) { if (other.isSetCode()) { this.code = other.code; } if (other.isSetMessage()) { this.message = other.message; } } public MyException deepCopy() { return new MyException(this); } @Override public void clear() { this.code = null; this.message = null; } public java.lang.String getCode() { return this.code; } public MyException setCode(java.lang.String code) { this.code = code; return this; } public void unsetCode() { this.code = null; } /** Returns true if field code is set (has been assigned a value) and false otherwise */ public boolean isSetCode() { return this.code != null; } public void setCodeIsSet(boolean value) { if (!value) { this.code = null; } } public java.lang.String getMessage() { return this.message; } public MyException setMessage(java.lang.String message) { this.message = message; return this; } public void unsetMessage() { this.message = null; } /** Returns true if field message is set (has been assigned a value) and false otherwise */ public boolean isSetMessage() { return this.message != null; } public void setMessageIsSet(boolean value) { if (!value) { this.message = null; } } public void setFieldValue(_Fields field, java.lang.Object value) { switch (field) { case CODE: if (value == null) { unsetCode(); } else { setCode((java.lang.String)value); } break; case MESSAGE: if (value == null) { unsetMessage(); } else { setMessage((java.lang.String)value); } break; } } public java.lang.Object getFieldValue(_Fields field) { switch (field) { case CODE: return getCode(); case MESSAGE: return getMessage(); } throw new java.lang.IllegalStateException(); } /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ public boolean isSet(_Fields field) { if (field == null) { throw new java.lang.IllegalArgumentException(); } switch (field) { case CODE: return isSetCode(); case MESSAGE: return isSetMessage(); } throw new java.lang.IllegalStateException(); } @Override public boolean equals(java.lang.Object that) { if (that == null) return false; if (that instanceof MyException) return this.equals((MyException)that); return false; } public boolean equals(MyException that) { if (that == null) return false; if (this == that) return true; boolean this_present_code = true && this.isSetCode(); boolean that_present_code = true && that.isSetCode(); if (this_present_code || that_present_code) { if (!(this_present_code && that_present_code)) return false; if (!this.code.equals(that.code)) return false; } boolean this_present_message = true && this.isSetMessage(); boolean that_present_message = true && that.isSetMessage(); if (this_present_message || that_present_message) { if (!(this_present_message && that_present_message)) return false; if (!this.message.equals(that.message)) return false; } return true; } @Override public int hashCode() { int hashCode = 1; hashCode = hashCode * 8191 + ((isSetCode()) ? 131071 : 524287); if (isSetCode()) hashCode = hashCode * 8191 + code.hashCode(); hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287); if (isSetMessage()) hashCode = hashCode * 8191 + message.hashCode(); return hashCode; } @Override public int compareTo(MyException other) { if (!getClass().equals(other.getClass())) { return getClass().getName().compareTo(other.getClass().getName()); } int lastComparison = 0; lastComparison = java.lang.Boolean.valueOf(isSetCode()).compareTo(other.isSetCode()); if (lastComparison != 0) { return lastComparison; } if (isSetCode()) { lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.code, other.code); if (lastComparison != 0) { return lastComparison; } } lastComparison = java.lang.Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage()); if (lastComparison != 0) { return lastComparison; } if (isSetMessage()) { lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message); if (lastComparison != 0) { return lastComparison; } } return 0; } public _Fields fieldForId(int fieldId) { return _Fields.findByThriftId(fieldId); } public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { scheme(iprot).read(iprot, this); } public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { scheme(oprot).write(oprot, this); } @Override public java.lang.String toString() { java.lang.StringBuilder sb = new java.lang.StringBuilder("MyException("); boolean first = true; sb.append("code:"); if (this.code == null) { sb.append("null"); } else { sb.append(this.code); } first = false; if (!first) sb.append(", "); sb.append("message:"); if (this.message == null) { sb.append("null"); } else { sb.append(this.message); } first = false; sb.append(")"); return sb.toString(); } public void validate() throws org.apache.thrift.TException { // check for required fields // check for sub-struct validity } private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { try { write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); } catch (org.apache.thrift.TException te) { throw new java.io.IOException(te); } } private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { try { read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); } catch (org.apache.thrift.TException te) { throw new java.io.IOException(te); } } private static class MyExceptionStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory { public MyExceptionStandardScheme getScheme() { return new MyExceptionStandardScheme(); } } private static class MyExceptionStandardScheme extends org.apache.thrift.scheme.StandardScheme
{ public void read(org.apache.thrift.protocol.TProtocol iprot, MyException struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TField schemeField; iprot.readStructBegin(); while (true) { schemeField = iprot.readFieldBegin(); if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { break; } switch (schemeField.id) { case 1: // CODE if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.code = iprot.readString(); struct.setCodeIsSet(true); } else { org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; case 2: // MESSAGE if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.message = iprot.readString(); struct.setMessageIsSet(true); } else { org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; default: org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } iprot.readFieldEnd(); } iprot.readStructEnd(); // check for required fields of primitive type, which can't be checked in the validate method struct.validate(); } public void write(org.apache.thrift.protocol.TProtocol oprot, MyException struct) throws org.apache.thrift.TException { struct.validate(); oprot.writeStructBegin(STRUCT_DESC); if (struct.code != null) { oprot.writeFieldBegin(CODE_FIELD_DESC); oprot.writeString(struct.code); oprot.writeFieldEnd(); } if (struct.message != null) { oprot.writeFieldBegin(MESSAGE_FIELD_DESC); oprot.writeString(struct.message); oprot.writeFieldEnd(); } oprot.writeFieldStop(); oprot.writeStructEnd(); } } private static class MyExceptionTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory { public MyExceptionTupleScheme getScheme() { return new MyExceptionTupleScheme(); } } private static class MyExceptionTupleScheme extends org.apache.thrift.scheme.TupleScheme
{ @Override public void write(org.apache.thrift.protocol.TProtocol prot, MyException struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot; java.util.BitSet optionals = new java.util.BitSet(); if (struct.isSetCode()) { optionals.set(0); } if (struct.isSetMessage()) { optionals.set(1); } oprot.writeBitSet(optionals, 2); if (struct.isSetCode()) { oprot.writeString(struct.code); } if (struct.isSetMessage()) { oprot.writeString(struct.message); } } @Override public void read(org.apache.thrift.protocol.TProtocol prot, MyException struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot; java.util.BitSet incoming = iprot.readBitSet(2); if (incoming.get(0)) { struct.code = iprot.readString(); struct.setCodeIsSet(true); } if (incoming.get(1)) { struct.message = iprot.readString(); struct.setMessageIsSet(true); } } } private static
S scheme(org.apache.thrift.protocol.TProtocol proto) { return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); }}

容器

编写user.thrift,用于定义一个User类, 会在集合类中使用~

namespace java com.xxx.tutorial.thrift.entity  /** * 用户类 */struct  User {    1:i32 userId,  2:string name}

创建containerTypes.thrift,用于使用容器类型,包括list、map和set~

include "user.thrift"namespace java com.xxx.tutorial.rpc.entitystruct ContainerTypes {		1: list
stringValueList; 2: set
stringValueSet; 3: map
stringValueMap; 4: list
userList; }

根据thrift文件生成java代码~

/** * Autogenerated by Thrift Compiler (0.10.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING *  @generated */package com.xxx.tutorial.rpc.entity;@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-06-08")public class ContainerTypes implements org.apache.thrift.TBase
, java.io.Serializable, Cloneable, Comparable
{ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ContainerTypes"); private static final org.apache.thrift.protocol.TField STRING_VALUE_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("stringValueList", org.apache.thrift.protocol.TType.LIST, (short)1); private static final org.apache.thrift.protocol.TField STRING_VALUE_SET_FIELD_DESC = new org.apache.thrift.protocol.TField("stringValueSet", org.apache.thrift.protocol.TType.SET, (short)2); private static final org.apache.thrift.protocol.TField STRING_VALUE_MAP_FIELD_DESC = new org.apache.thrift.protocol.TField("stringValueMap", org.apache.thrift.protocol.TType.MAP, (short)3); private static final org.apache.thrift.protocol.TField USER_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("userList", org.apache.thrift.protocol.TType.LIST, (short)4); private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ContainerTypesStandardSchemeFactory(); private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ContainerTypesTupleSchemeFactory(); public java.util.List
stringValueList; // required public java.util.Set
stringValueSet; // required public java.util.Map
stringValueMap; // required public java.util.List
userList; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { STRING_VALUE_LIST((short)1, "stringValueList"), STRING_VALUE_SET((short)2, "stringValueSet"), STRING_VALUE_MAP((short)3, "stringValueMap"), USER_LIST((short)4, "userList"); private static final java.util.Map
byName = new java.util.HashMap
(); static { for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { byName.put(field.getFieldName(), field); } } /** * Find the _Fields constant that matches fieldId, or null if its not found. */ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { case 1: // STRING_VALUE_LIST return STRING_VALUE_LIST; case 2: // STRING_VALUE_SET return STRING_VALUE_SET; case 3: // STRING_VALUE_MAP return STRING_VALUE_MAP; case 4: // USER_LIST return USER_LIST; default: return null; } }... ... }

从上述生成的代码可以看出,thrift文件中定义的容器类型转换成Java类型之后,与下图展示的内容一致~

073207_hAJM_2911530.png

服务Service

编写一个exception.thrift, 用于自定义异常类~

namespace java com.xxx.tutorial.rpc.exceptionexception UserNotFoundException {	1: string code;	2: string message;}

编写userService.thrift, 用于服务接口定义~ 

include "user.thrift"include "exception.thrift"namespace java com.xxx.tutorial.thrift.service  /** * 用户服务 */service  UserService {     /**保存用户*/   bool save(1:user.User user),    /**根据name获取用户列表*/   list
findUsersByName(1:string name), /**删除用户*/ void deleteByUserId(1:i32 userId) throws (1: exception.UserNotFoundException e)}

生成的UserService代码

package com.xxx.tutorial.thrift.service;@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-06-08")public class UserService {  /**   * 用户服务   */  public interface Iface {    /**     * 保存用户     *      * @param user     */    public boolean save(com.xxx.tutorial.thrift.entity.User user) throws org.apache.thrift.TException;    /**     * 根据name获取用户列表     *      * @param name     */    public java.util.List
findUsersByName(java.lang.String name) throws org.apache.thrift.TException; /** * 删除用户 * * @param userId */ public void deleteByUserId(int userId) throws com.xxx.tutorial.rpc.exception.UserNotFoundException, org.apache.thrift.TException; } public interface AsyncIface { public void save(com.xxx.tutorial.thrift.entity.User user, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException; public void findUsersByName(java.lang.String name, org.apache.thrift.async.AsyncMethodCallback
> resultHandler) throws org.apache.thrift.TException; public void deleteByUserId(int userId, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException; } public static class Client extends org.apache.thrift.TServiceClient implements Iface { public static class Factory implements org.apache.thrift.TServiceClientFactory
{ public Factory() {} public Client getClient(org.apache.thrift.protocol.TProtocol prot) { return new Client(prot); } public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) { return new Client(iprot, oprot); } } public Client(org.apache.thrift.protocol.TProtocol prot) { super(prot, prot); } public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) { super(iprot, oprot); } public boolean save(com.xxx.tutorial.thrift.entity.User user) throws org.apache.thrift.TException { send_save(user); return recv_save(); } public void send_save(com.xxx.tutorial.thrift.entity.User user) throws org.apache.thrift.TException { save_args args = new save_args(); args.setUser(user); sendBase("save", args); } public boolean recv_save() throws org.apache.thrift.TException { save_result result = new save_result(); receiveBase(result, "save"); if (result.isSetSuccess()) { return result.success; } throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "save failed: unknown result"); } public java.util.List
findUsersByName(java.lang.String name) throws org.apache.thrift.TException { send_findUsersByName(name); return recv_findUsersByName(); } public void send_findUsersByName(java.lang.String name) throws org.apache.thrift.TException { findUsersByName_args args = new findUsersByName_args(); args.setName(name); sendBase("findUsersByName", args); } public java.util.List
recv_findUsersByName() throws org.apache.thrift.TException { findUsersByName_result result = new findUsersByName_result(); receiveBase(result, "findUsersByName"); if (result.isSetSuccess()) { return result.success; } throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "findUsersByName failed: unknown result"); } public void deleteByUserId(int userId) throws com.xxx.tutorial.rpc.exception.UserNotFoundException, org.apache.thrift.TException { send_deleteByUserId(userId); recv_deleteByUserId(); } public void send_deleteByUserId(int userId) throws org.apache.thrift.TException { deleteByUserId_args args = new deleteByUserId_args(); args.setUserId(userId); sendBase("deleteByUserId", args); } public void recv_deleteByUserId() throws com.xxx.tutorial.rpc.exception.UserNotFoundException, org.apache.thrift.TException { deleteByUserId_result result = new deleteByUserId_result(); receiveBase(result, "deleteByUserId"); if (result.e != null) { throw result.e; } return; } }... ... }

示例

说明

在这个示例中,我们主要在用户接口中定义三个接口:保存用户,根据name获取用户列表以及删除用户,如:

/**     * 保存用户     *      * @param user     */    public boolean save(com.xxx.tutorial.thrift.entity.User user) throws org.apache.thrift.TException;    /**     * 根据name获取用户列表     *      * @param name     */    public java.util.List
findUsersByName(java.lang.String name) throws org.apache.thrift.TException; /** * 删除用户 * * @param userId */ public void deleteByUserId(int userId) throws com.xxx.tutorial.thrift.exception.UserNotFoundException, org.apache.thrift.TException;

然后使用多种Server创建方法,Thrift支持的Serer有多种,如TSimpleServer、TThreadPoolServer等~

185909_UATb_2911530.png

产生代码

根据thrift文件生成Java代码,这里就不再描述,请参考以前的博文【】

接口代码

将生成的Java代码放入thrift-demo-interface模块~ 如,

185849_hOap_2911530.png

实现代码

在thrift-demo-service模块增加UserService的实现类~

185948_rMlK_2911530.png

UserServiceImpl.java的内容如下:

/** *  */package com.xxx.tutorial.thrift.service.impl;import java.util.Arrays;import java.util.List;import java.util.logging.Logger;import org.apache.thrift.TException;import com.xxx.tutorial.thrift.entity.User;import com.xxx.tutorial.thrift.exception.UserNotFoundException;import com.xxx.tutorial.thrift.service.UserService;/** * @author wangmengjun * */public class UserServiceImpl implements UserService.Iface {	private static final Logger logger = Logger.getLogger(UserServiceImpl.class.getName());	public boolean save(User user) throws TException {		logger.info("方法save的参数user的内容==>" + user.toString());		return true;	}	public List
findUsersByName(String name) throws TException { logger.info("方法findUsersByName的参数name的内容==>" + name); return Arrays.asList(new User(1, "Wang"), new User(2, "Mengjun")); } public void deleteByUserId(int userId) throws UserNotFoundException, TException { /** * 直接模拟抛出异常,用于测试 */ logger.info("方法deleteByUserId的参数userId的内容==>" + userId); throw new UserNotFoundException("1001", String.format("userId=%d的用户不存在", userId)); }}

有了实现之后,就可以编写Server端的代码和Client端调用的代码~

TSimpleServer(阻塞IO)

在thrift-demo-server模块编写服务端代码~

四个步骤创建Server,如:

package com.xxx.tutorial.thrift.server;import java.util.logging.Logger;import org.apache.thrift.TProcessor;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.server.TServer;import org.apache.thrift.server.TSimpleServer;import org.apache.thrift.transport.TServerSocket;import com.xxx.tutorial.thrift.service.UserService;import com.xxx.tutorial.thrift.service.impl.UserServiceImpl;/** * @author wangmengjun * */public class TSimpleServerExample {	private static final Logger logger = Logger.getLogger(TSimpleServerExample.class.getName());	private static final int SERVER_PORT = 9123;	public static void main(String[] args) {		try {						/**			 * 1. 创建Transport			 */			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);			TServer.Args tArgs = new TServer.Args(serverTransport);						/**			 * 2. 为Transport创建Protocol			 */			tArgs.protocolFactory(new TBinaryProtocol.Factory());			// tArgs.protocolFactory(new TCompactProtocol.Factory());			// tArgs.protocolFactory(new TJSONProtocol.Factory());						/**			 * 3. 为Protocol创建Processor			 */			TProcessor tprocessor = new UserService.Processor
(new UserServiceImpl()); tArgs.processor(tprocessor); /** * 4. 创建Server并启动 * * org.apache.thrift.server.TSimpleServer - 简单的单线程服务模型,一般用于测试 */ TServer server = new TSimpleServer(tArgs); logger.info("UserService TSimpleServer start ...."); server.serve(); } catch (Exception e) { logger.severe("Server start error!!!" + e.getLocalizedMessage()); e.printStackTrace(); } }}

启动Server,

190405_RJwg_2911530.png

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.六月 08, 2017 7:03:46 下午 com.xxx.tutorial.thrift.server.TSimpleServerExample main信息: UserService TSimpleServer start ....

在thrift-demo-client模块编写客户端代码~

如:

package com.xxx.tutorial.thrift.client;import java.util.List;import java.util.logging.Logger;import org.apache.thrift.TException;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.transport.TSocket;import org.apache.thrift.transport.TTransport;import org.apache.thrift.transport.TTransportException;import com.xxx.tutorial.thrift.entity.User;import com.xxx.tutorial.thrift.exception.UserNotFoundException;import com.xxx.tutorial.thrift.service.UserService;public class UserClient {	private static final Logger logger = Logger.getLogger(UserClient.class.getName());	public static void main(String[] args) {				try {			TTransport transport = new TSocket("127.0.0.1", 9123);			TProtocol protocol = new TBinaryProtocol(transport);			UserService.Client client = new UserService.Client(protocol);			transport.open();			/**			 * 查询User列表			 */			List
users = client.findUsersByName("wang"); logger.info("client.findUsersByName()方法結果 == >" + users); /** * 保存User */ boolean isUserSaved = client.save(new User(101, "WMJ")); logger.info("user saved result == > " + isUserSaved); /** * 删除用户 */ client.deleteByUserId(1002); transport.close(); } catch (TTransportException e) { logger.severe("TTransportException==>" + e.getLocalizedMessage()); } catch (UserNotFoundException e) { logger.severe("UserNotFoundException==>" + e.getLocalizedMessage()); } catch (TException e) { logger.severe("TException==>" + e.getLocalizedMessage()); } }}

190703_B115_2911530.png

三个方法的结果都有了~

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.Received 1六月 08, 2017 7:06:21 下午 com.xxx.tutorial.thrift.client.UserClient main信息: client.findUsersByName()方法結果 == >[User(userId:1, name:Wang), User(userId:2, name:Mengjun)]Received 2六月 08, 2017 7:06:21 下午 com.xxx.tutorial.thrift.client.UserClient main信息: user saved result == > trueReceived 3六月 08, 2017 7:06:21 下午 com.xxx.tutorial.thrift.client.UserClient main严重: UserNotFoundException==>userId=1002的用户不存在

就这样,阻塞IO的示例就完成了~

TThreadPoolServer(多线程阻塞IO)

服务端代码示例:

package com.xxx.tutorial.thrift.server;import java.util.logging.Logger;import org.apache.thrift.TProcessor;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.server.TServer;import org.apache.thrift.server.TThreadPoolServer;import org.apache.thrift.transport.TServerSocket;import com.xxx.tutorial.thrift.service.UserService;import com.xxx.tutorial.thrift.service.impl.UserServiceImpl;/** *  * @author wangmengjun * */public class TThreadPoolServerExample {	private static final Logger logger = Logger.getLogger(TThreadPoolServerExample.class.getName());	private static final int SERVER_PORT = 9125;	public static void main(String[] args) {		try {						/**			 * 1. 创建Transport			 */			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);			TThreadPoolServer.Args tArgs = new TThreadPoolServer.Args(serverTransport);						/**			 * 2. 为Transport创建Protocol			 */			tArgs.protocolFactory(new TBinaryProtocol.Factory());			// tArgs.protocolFactory(new TCompactProtocol.Factory());			// tArgs.protocolFactory(new TJSONProtocol.Factory());						/**			 * 3. 为Protocol创建Processor			 */			TProcessor tprocessor = new UserService.Processor
(new UserServiceImpl()); tArgs.processor(tprocessor); /** * 4. 创建Server并启动 * * org.apache.thrift.server.TThreadPoolServer - 简单的单线程服务模型,一般用于测试 */ TServer server = new TThreadPoolServer(tArgs); logger.info("UserService TSimpleServer start ...."); server.serve(); } catch (Exception e) { logger.severe("Server start error!!!" + e.getLocalizedMessage()); e.printStackTrace(); } }}

同样客户端的代码还可以是:

package com.xxx.tutorial.thrift.client;import java.util.List;import java.util.logging.Logger;import org.apache.thrift.TException;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.transport.TSocket;import org.apache.thrift.transport.TTransport;import org.apache.thrift.transport.TTransportException;import com.xxx.tutorial.thrift.entity.User;import com.xxx.tutorial.thrift.exception.UserNotFoundException;import com.xxx.tutorial.thrift.service.UserService;public class UserClient {	private static final Logger logger = Logger.getLogger(UserClient.class.getName());	public static void main(String[] args) {				try {			TTransport transport = new TSocket("127.0.0.1", 9123);			TProtocol protocol = new TBinaryProtocol(transport);			UserService.Client client = new UserService.Client(protocol);			transport.open();			/**			 * 查询User列表			 */			List
users = client.findUsersByName("wang"); logger.info("client.findUsersByName()方法結果 == >" + users); /** * 保存User */ boolean isUserSaved = client.save(new User(101, "WMJ")); logger.info("user saved result == > " + isUserSaved); /** * 删除用户 */ client.deleteByUserId(1002); transport.close(); } catch (TTransportException e) { logger.severe("TTransportException==>" + e.getLocalizedMessage()); } catch (UserNotFoundException e) { logger.severe("UserNotFoundException==>" + e.getLocalizedMessage()); } catch (TException e) { logger.severe("TException==>" + e.getLocalizedMessage()); } }}

同样调用成功

194457_xs6i_2911530.png

服务端也打印了方法调用的信息:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.六月 08, 2017 7:43:35 下午 com.xxx.tutorial.thrift.server.TThreadPoolServerExample main信息: UserService TSimpleServer start ....六月 08, 2017 7:43:39 下午 com.xxx.tutorial.thrift.service.impl.UserServiceImpl findUsersByName信息: 方法findUsersByName的参数name的内容==>wang六月 08, 2017 7:43:39 下午 com.xxx.tutorial.thrift.service.impl.UserServiceImpl save信息: 方法save的参数user的内容==>User(userId:101, name:WMJ)六月 08, 2017 7:43:39 下午 com.xxx.tutorial.thrift.service.impl.UserServiceImpl deleteByUserId信息: 方法deleteByUserId的参数userId的内容==>1002

THsHaServer(多线程 NIO)

THsHaServer的描述如下:

/** * An extension of the TNonblockingServer to a Half-Sync/Half-Async server. * Like TNonblockingServer, it relies on the use of TFramedTransport. */public class THsHaServer extends TNonblockingServer {... ...}

 

THsHaServer使用了Java NIO channel~ 在这种Server类型下,一定要使用TFrameTransport~

服务端代码示例如下:

package com.xxx.tutorial.thrift.server;import java.util.logging.Logger;import org.apache.thrift.TProcessor;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.server.THsHaServer;import org.apache.thrift.server.TServer;import org.apache.thrift.transport.TFramedTransport;import org.apache.thrift.transport.TNonblockingServerSocket;import com.xxx.tutorial.thrift.service.UserService;import com.xxx.tutorial.thrift.service.impl.UserServiceImpl;/** * @author wangmengjun * */public class THsHaServerExample {	private static final Logger logger = Logger.getLogger(THsHaServerExample.class.getName());	private static final int SERVER_PORT = 9123;	public static void main(String[] args) {		try {						/**			 * 1. 创建Transport			 */			//TServerSocket serverTransport = new TServerSocket(SERVER_PORT);			TNonblockingServerSocket serverTransport = new TNonblockingServerSocket(SERVER_PORT);			THsHaServer.Args tArgs = new THsHaServer.Args(serverTransport);						/**			 * 2. 为Transport创建Protocol			 */			tArgs.transportFactory(new TFramedTransport.Factory());			tArgs.protocolFactory(new TBinaryProtocol.Factory());			// tArgs.protocolFactory(new TCompactProtocol.Factory());			// tArgs.protocolFactory(new TJSONProtocol.Factory());						/**			 * 3. 为Protocol创建Processor			 */			TProcessor tprocessor = new UserService.Processor
(new UserServiceImpl()); tArgs.processor(tprocessor); /** * 4. 创建Server并启动 * * org.apache.thrift.server.TSimpleServer - 简单的单线程服务模型,一般用于测试 */ //TServer server = new TSimpleServer(tArgs); //半同步半异步的服务模型 TServer server = new THsHaServer(tArgs); logger.info("UserService TSimpleServer start ...."); server.serve(); } catch (Exception e) { logger.severe("Server start error!!!" + e.getLocalizedMessage()); e.printStackTrace(); } }}

客户端代码如下:

package com.xxx.tutorial.thrift.client;import java.util.List;import java.util.logging.Logger;import org.apache.thrift.TException;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.transport.TFramedTransport;import org.apache.thrift.transport.TSocket;import org.apache.thrift.transport.TTransport;import org.apache.thrift.transport.TTransportException;import com.xxx.tutorial.thrift.entity.User;import com.xxx.tutorial.thrift.exception.UserNotFoundException;import com.xxx.tutorial.thrift.service.UserService;public class UserClient2 {	private static final Logger logger = Logger.getLogger(UserClient.class.getName());	public static void main(String[] args) {		try {			TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 9123, 3000));			TProtocol protocol = new TBinaryProtocol(transport);			UserService.Client client = new UserService.Client(protocol);			transport.open();			/**			 * 查询User列表			 */			List
users = client.findUsersByName("wang"); logger.info("client.findUsersByName()方法結果 == >" + users); /** * 保存User */ boolean isUserSaved = client.save(new User(101, "WMJ")); logger.info("user saved result == > " + isUserSaved); /** * 删除用户 */ client.deleteByUserId(1002); transport.close(); } catch (TTransportException e) { logger.severe("TTransportException==>" + e.getLocalizedMessage()); } catch (UserNotFoundException e) { logger.severe("UserNotFoundException==>" + e.getLocalizedMessage()); } catch (TException e) { logger.severe("TException==>" + e.getLocalizedMessage()); } }}

同样,执行结果成功~

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to no-operation (NOP) logger implementationSLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.Received 1六月 08, 2017 7:51:12 下午 com.xxx.tutorial.thrift.client.UserClient2 main信息: client.findUsersByName()方法結果 == >[User(userId:1, name:Wang), User(userId:2, name:Mengjun)]Received 2六月 08, 2017 7:51:12 下午 com.xxx.tutorial.thrift.client.UserClient2 main信息: user saved result == > trueReceived 3六月 08, 2017 7:51:12 下午 com.xxx.tutorial.thrift.client.UserClient2 main严重: UserNotFoundException==>userId=1002的用户不存在

小结

本教程主要帮助开发人员熟悉Thrift的IDL语法,并给出Java对应的示例,并给出几种不同的Server和Client端调用实现~

限于篇幅,AsyncIface和AsyncClient等会在后续的博文中补充上去~

另外,FaceBook也开源了Nifty

Nifty是facebook公司开源的,基于netty的thrift服务端和客户端实现。

详细资料可以参考Nifty官网【】

后续,也可以给出Nifty相关的示例~

代码下载

【】

200832_0rtW_2911530.png

参考文献

【1】https://media.readthedocs.org/pdf/thrift-tutorial/latest/thrift-tutorial.pdf

【2】https://diwakergupta.github.io/thrift-missing-guide/thrift.pdf

【3】http://dongxicheng.org/search-engine/thrift-guide/

【4】http://www.micmiu.com/soa/rpc/thrift-sample/

【5】http://blog.csdn.net/ITer_ZC/article/details/39695187

转载于:https://my.oschina.net/wangmengjun/blog/917456

你可能感兴趣的文章
poj 3040 Allowance 贪心
查看>>
分享27款最佳的复古风格 WordPress 主题
查看>>
ASP.NET 打包多CSS或JS文件以加快页面加载速度的Handler
查看>>
让“是男人就下到100层”在Android平台上跑起来
查看>>
hdu 1010:Tempter of the Bone(DFS + 奇偶剪枝)
查看>>
文件和目录之umask函数
查看>>
ecmall的物流配送体系改造
查看>>
[Python]网络爬虫(九):百度贴吧的网络爬虫(v0.4)源码及解析(转)
查看>>
hdu4292Food(最大流Dinic算法)
查看>>
手机网站判断及跳转
查看>>
[LeetCode] Text Justification
查看>>
webdriver API study
查看>>
QoS令牌桶工作原理
查看>>
android工程gen目录中R.java包名是怎么确定
查看>>
【Machine Learning in Action --4】朴素贝叶斯过滤网站的恶意留言
查看>>
Java基础之类Class使用
查看>>
Ubuntu+Eclipse+ADT+Genymotion+VirtualBox开发环境搭建
查看>>
Android 学习之 开源项目PullToRefresh的使用
查看>>
Matplot中文乱码完美解决方式
查看>>
stm32学习笔记----双串口同时打开时的printf()问题
查看>>