如何使用 Apache Thrift 在单个 catch 语句中捕获所有自定义异常?
How to catch all custom exceptions in a single catch statement with Apache Thrift?
我在 exception.thrift
中定义了许多不同的异常:
exception InvalidArgumentsError {
1: string parameter
}
/**
* Server has an problem while executing a function.
* Execution aborted.
*/
exception ServerInternalError {
1: string parameter
}
/**
* Server answer is empty.
*/
exception NoDataError {
1: string parameter
}
这就是我在 C++ 代码中捕获它们的方式:
catch (InvalidArgumentsError & ex) {
std::cout << ex.parameter;
}
catch (ServerInternalError & ex) {
std::cout << ex.parameter;
}
catch (NoDataError & ex) {
std::cout << ex.parameter;
}
catch (apache::thrift::TException& ex) {
std::cout << "TException:\n" << ex.what();
} catch (const std::exception& ex) {
std::cout << ex.what();
return;
}
我想写这样的东西并捕获我所有的异常:
catch (SomeBasicException& ex) {
std::cout << ex.what();
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
如果我只是捕获 TException
并调用 what()
,我只会收到 'Default TException' 消息,因为派生类不会覆盖虚拟 what()
方法。
thrift 编译器生成的代码:
class InvalidArgumentsError : public ::apache::thrift::TException {
public:
static const char* ascii_fingerprint; //..
static const uint8_t binary_fingerprint[16]; //..
InvalidArgumentsError() : parameter() {
}
virtual ~InvalidArgumentsError() throw() {}
std::string parameter;
_InvalidArgumentsError__isset __isset;
void __set_parameter(const std::string& val) {
parameter = val;
}
//...
};
如果您想停止重复输入,那么这可能是一个解决方案。
当你想捕获你的异常时,你可以这样写:
catch (...) {
handle_exception(print_message);
}
print_message
是一个函数,可以对消息做任何你想做的事情(在这种情况下,打印它):
void print_message(char const* const msg)
{
std::cout << msg;
}
handle_exception
是这样写的:
template<typename F>
void handle_exception(F handler)
try {
throw;
}
catch (InvalidArgumentsError const& ex) {
handler(ex.parameter.c_str());
}
catch (ServerInternalError const& ex) {
handler(ex.parameter.c_str());
}
catch (NoDataError const& ex) {
handler(ex.parameter.c_str());
}
catch (apache::thrift::TException const& ex) {
handler(ex.what());
}
catch (std::exception const& ex) {
handler(ex.what());
}
要处理新异常,请将其添加到 handle_exception
函数的 catch
子句中。
尽管这并没有真正从字面上回答问题(@Simple 已经在这方面做得很好),但我想提出一种稍微不同的方法。
鉴于上面发布的代码:
exception InvalidArgumentsError {
1: string parameter
}
exception ServerInternalError {
1: string parameter
}
exception NoDataError {
1: string parameter
}
如果我们查看该模式,我们可以 - 在不丢失任何信息且不会产生更大的不兼容性的情况下 - 将其更改为:
enum ErrorCode
Success = 0, // always good to have some null value
ServerInternalError = 1
NoData = 2
InvalidArguments = 3
// add more errors here
}
exception MyServiceException {
1: string parameter
2: ErrorCode code
}
我完全知道这可能不适合您的特定问题(例如,如果异常数据多于 1:parameter
)。但在某些情况下,这种方法可能值得考虑。我自己用过好几次了。
我在 exception.thrift
中定义了许多不同的异常:
exception InvalidArgumentsError {
1: string parameter
}
/**
* Server has an problem while executing a function.
* Execution aborted.
*/
exception ServerInternalError {
1: string parameter
}
/**
* Server answer is empty.
*/
exception NoDataError {
1: string parameter
}
这就是我在 C++ 代码中捕获它们的方式:
catch (InvalidArgumentsError & ex) {
std::cout << ex.parameter;
}
catch (ServerInternalError & ex) {
std::cout << ex.parameter;
}
catch (NoDataError & ex) {
std::cout << ex.parameter;
}
catch (apache::thrift::TException& ex) {
std::cout << "TException:\n" << ex.what();
} catch (const std::exception& ex) {
std::cout << ex.what();
return;
}
我想写这样的东西并捕获我所有的异常:
catch (SomeBasicException& ex) {
std::cout << ex.what();
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
如果我只是捕获 TException
并调用 what()
,我只会收到 'Default TException' 消息,因为派生类不会覆盖虚拟 what()
方法。
thrift 编译器生成的代码:
class InvalidArgumentsError : public ::apache::thrift::TException {
public:
static const char* ascii_fingerprint; //..
static const uint8_t binary_fingerprint[16]; //..
InvalidArgumentsError() : parameter() {
}
virtual ~InvalidArgumentsError() throw() {}
std::string parameter;
_InvalidArgumentsError__isset __isset;
void __set_parameter(const std::string& val) {
parameter = val;
}
//...
};
如果您想停止重复输入,那么这可能是一个解决方案。
当你想捕获你的异常时,你可以这样写:
catch (...) {
handle_exception(print_message);
}
print_message
是一个函数,可以对消息做任何你想做的事情(在这种情况下,打印它):
void print_message(char const* const msg)
{
std::cout << msg;
}
handle_exception
是这样写的:
template<typename F>
void handle_exception(F handler)
try {
throw;
}
catch (InvalidArgumentsError const& ex) {
handler(ex.parameter.c_str());
}
catch (ServerInternalError const& ex) {
handler(ex.parameter.c_str());
}
catch (NoDataError const& ex) {
handler(ex.parameter.c_str());
}
catch (apache::thrift::TException const& ex) {
handler(ex.what());
}
catch (std::exception const& ex) {
handler(ex.what());
}
要处理新异常,请将其添加到 handle_exception
函数的 catch
子句中。
尽管这并没有真正从字面上回答问题(@Simple 已经在这方面做得很好),但我想提出一种稍微不同的方法。
鉴于上面发布的代码:
exception InvalidArgumentsError {
1: string parameter
}
exception ServerInternalError {
1: string parameter
}
exception NoDataError {
1: string parameter
}
如果我们查看该模式,我们可以 - 在不丢失任何信息且不会产生更大的不兼容性的情况下 - 将其更改为:
enum ErrorCode
Success = 0, // always good to have some null value
ServerInternalError = 1
NoData = 2
InvalidArguments = 3
// add more errors here
}
exception MyServiceException {
1: string parameter
2: ErrorCode code
}
我完全知道这可能不适合您的特定问题(例如,如果异常数据多于 1:parameter
)。但在某些情况下,这种方法可能值得考虑。我自己用过好几次了。