问题描述:
当方法返回值为thrift基本类型(i64,bool...)时,客户端无法捕捉异常。
ps.当方法返回值为用户定义的类型时,不会出现该问题。
注意 thrift 版本0.8
跟踪thrift代码发现,问题出现的原因:
step 1: 服务端,写数据
(基本类型) 不会先判断返回值是否为空,基本类型也无法判断是否为空
oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
(用户定义类型) 会先判断返回值是否为空
if (struct.success != null) {
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
{
oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
for (Province _iter3 : struct.success)
{
_iter3.write(oprot);
}
oprot.writeListEnd();
}
oprot.writeFieldEnd();
}
}
step 2: 客户端读数据
(基本类型) 服务端写数据时,一定会写入返回值的TField,所以读到的第一个TFIELD 一定会进入case0. 其中执行了 struct.setSuccessIsSet(true); 方法标示 返回值已写入
switch (schemeField.id) {
case 0: // SUCCESS
if (schemeField.type == TType.I64) {
struct.success = iprot.readI64();
struct.setSuccessIsSet(true);
}
else {
TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 1: // USER_EXCEPTION
//................
default:
TProtocolUtil.skip(iprot, schemeField.type);
}
(用户定义类型) 服务端写数据时,经过判断未写入返回值TField, 因此直接进入case 1
switch (schemeField.id) {
case 0: // SUCCESS
// ................
break;
case 1: // COMMON_EXCEPTION
// .................
}
step 3: 客户端处理返回结果 执行recv_****方法时
if (result.isSetSuccess()) {
return result.success;
}
if (result.commonException != null) {
throw result.commonException;
}
(基本类型) 由于基本类型在step2中执行了setSuccessIsSet(true);
因此第一个if总是为真,在这步方法已经返回。
不能够进入第二个if.捕捉异常
(用户定义类型) 用户类型。如果产生异常则跳过第一个if,能够在第二个if块中捕捉到异常
我想到的解决方法:
方法1. 更改step1
oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
更改为
oprot.writeStructBegin(STRUCT_DESC);
if (this.isSetSuccess()) {
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
}
方法2. 更改step3
将recv_****方法中
if (result.isSetSuccess()) {
return result.success;
}
if (result.commonException != null) {
throw result.commonException;
}
更改顺序变为
if (result.commonException != null) {
throw result.commonException;
}
if (result.isSetSuccess()) {
return result.success;
}
问题得到解决
但是由于 这样需要为每个生成的Iface修改代码,开发代价太大。所以想请教下大牛们是如何解决这个问题的。
分享到:
相关推荐
在Java环境中,Thrift提供了服务器和客户端的实现,使得Java应用能够方便地建立起高效的通信机制。下面我们将深入探讨Thrift在Java环境中的服务器和客户端通信过程。 首先,我们需要定义服务接口。这通常通过编写一...
通过Thrift,你可以用Java编写服务端,而用Python、C++或任何支持Thrift的其他语言编写客户端,实现无缝交互。Thrift还提供了许多优化功能,如多线程处理、异步调用和高级数据序列化选项,使得它成为构建分布式系统...
Thrift下java服务器与客户端开发指南【精选文档】.doc
生成代码后,Thrift会为每种目标语言(如Java、Python、C++等)创建相应的客户端和服务器端代码。客户端代码提供了调用远程服务的接口,服务器端代码则包含了处理这些调用的实际逻辑。例如,对于Java,客户端代码会...
4. 创建Java客户端 客户端代码同样基于Thrift生成的代码,创建一个`Client.java`文件,用于调用服务器上的服务: ```java import org.apache.thrift.TException; public class Client { public static void main...
本文将基于Thrift的Java实现,总结学习过程中的一些关键知识点,旨在帮助理解Thrift的工作原理以及如何在Java环境中应用。 一、Thrift简介 Thrift是一种远程过程调用(RPC)框架,它通过定义一种中间描述文件(....
`--gen java` 参数告诉 Thrift 编译器我们需要生成 Java 代码,`namespace java Test` 定义了生成代码的 Java 包名。 ```thrift namespace java Test service Something { i32 ping() } ``` 执行 `thrift --gen ...
《Thrift下Java服务器与客户端开发指南》 Thrift 是一个高效的跨语言服务开发框架,由Facebook开源,主要用于构建可扩展且跨平台的服务。它通过定义一种中间表示(IDL,Interface Description Language)来描述数据...
创建Java客户端相对简单,因为Thrift已经为我们生成了必要的客户端代码。主要步骤是建立一个连接到服务器的客户端实例,然后调用服务方法。 4. 编译及运行 4.1 使用Java编译器(javac)编译所有源文件,确保所有...
客户端则使用Thrift生成的Java客户端类,连接服务端,进行通信。 - 这个测试项目可能是为了演示如何使用Thrift进行RPC(Remote Procedure Call)调用,包括服务的定义、服务端的实现、客户端的调用流程等。 - 项目...
4. **创建Java客户端** - **建立客户端连接**:客户端使用生成的`Something$Client`类来创建到服务器的连接。 - **调用服务**:通过客户端对象,我们可以调用`ping`方法,就像调用本地Java方法一样。 5. **编译及...
在这个"thrift的java和python结合例子"中,我们将探讨如何使用Thrift在Java和Python之间建立通信。 首先,Thrift通过定义接口描述文件(.thrift)来规范服务的接口。这个文件使用Thrift IDL(Interface Description...
4. **创建Java客户端** 客户端使用生成的`SomethingClient`类来连接服务器并调用服务: ```java public class Client { public static void main(String[] args) throws Exception { TTransport transport = ...
**GO语言通过Thrift服务器和客户端通信(经典)** 在软件开发中,跨语言通信是一个常见的需求,Thrift就是一种高效、轻量级的跨语言服务框架,它由Facebook开发并开源,支持多种编程语言,包括Go语言。本文将详细...
创建Java客户端涉及创建一个连接到服务器的实例,并调用服务接口的方法。你可以创建一个`Client.java`文件,连接到服务器并调用`ping`方法。 4. 编译及运行 4.1 编译 使用Java编译器(`javac`)编译生成的和自定义...
本文将详细介绍如何使用 Thrift 在 Java 环境下构建 `.jar` 文件,以便在不同的 Java 应用中使用 Thrift 生成的服务。 1. **安装 Thrift** 首先,你需要在本地安装 Thrift 编译器。访问 Thrift 官方网站...
Thrift下java服务器与客户端开发指南.doc
通过Thrift的编译器,这个IDL文件会被转换成Java代码,生成服务接口类(如`Calculator.java`)和服务处理类(如`CalculatorHandler.java`)。服务处理类实现了服务接口,具体执行业务逻辑。然后,开发者可以通过...