5

有没有一种简单的方法来获取现有的 Java/scala 数据类型和 API 接口并生成相应的 .thrift 文件?让 Thrift 生成服务器数据结构具有过分的侵入性,因为它会产生以下后果:

  • 我无法注释我的数据结构(例如,XML、JSON、休眠持久性,...)
  • 此模式与其他想要拥有或需要修改我的源文件的序列化框架冲突。

结果,thrift 似乎强迫自己成为我的服务器的专有持久性格式——除非,也就是说,我围绕 Thrift 或其他处理这些数据结构的持久性格式创建数据编组包装器(休眠,杰克逊,斯卡拉 BeanProperty,...)。然而,这违背了自动数据编组工具(如 thrift)的目的,并直接导致必须维护相同但独立的接口和数据结构(= 浪费有才华的工程师时间和精力)的容易出错的世界。

我对 Thrift 自动生成客户端代码非常满意。但是,我(强烈)觉得我需要自由编辑我的服务器在 API 中处理的数据结构。

4

3 回答 3

5

您可以使用Swift

使长话短说; 注释您的类和接口(Thrift 用语中的结构和服务)。然后,您可以运行 Swift 的客户端/服务器代码,也可以使用 swift2thrift 生成器生成等效的 IDL 并使用 Thrift 编译器生成客户端(我建议您使用后者)。

一旦完成创建一个 TProcessor,您可以在具有普通 TProtocol/TTransport 对象的 TServlet 中使用该 TProcessor,请在 servlet 的 init() 中执行以下操作:

protected void addProcessor(String name, Object svc) {
    ThriftCodecManager codecManager = new ThriftCodecManager(
        new CompilerThriftCodecFactory(false)
    );
    List<ThriftEventHandler> eventList = Collections.emptyList();
    ThriftServiceProcessor proc = new ThriftServiceProcessor(codecManager, eventList, svc);
    this.processors.put(name, proc);
    this.multiplex.registerProcessor(name, NiftyProcessorAdapters.processorToTProcessor(proc));
}

此示例中的多路复用实例变量是TMultiplexedProcessorfrom的一个实例libthrift.jar

然后在你的 doPost() 中执行此操作:

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    getServletContext().log("entering doPost()");
    TTransport inTransport = null;
    TTransport outTransport = null;
    try {

        InputStream in = request.getInputStream();
        OutputStream out = response.getOutputStream();

        TTransport transport = new TIOStreamTransport(in, out);
        inTransport = transport;
        outTransport = transport;

        TProtocol inProtocol = getInProtocolFactory().getProtocol(inTransport);
        TProtocol outProtocol = getOutProtocolFactory().getProtocol(outTransport);

        if (multiplex.process(inProtocol, outProtocol)) {
            out.flush();
        } else {
            throw new ServletException("multiplex.process() returned false");
        }
    } catch (TException te) {
        throw new ServletException(te);
    } finally {
        if (inTransport != null) {
            inTransport.close();
        }
        if (outTransport != null) {
            outTransport.close();
        }
    }
}

仅供参考 - TJSONProtocol 不适用于 0.14 版之前的 Swift 版本,因此此时如果需要使用它,您需要从源代码构建。

另外...... Swift 强制标记你的结构final...... JPA 规范说实体不能final......似乎无论如何都可以与 Eclipselink 一起使用,但 YMMV

于 2014-09-04T01:58:23.493 回答
3

既然你提到了 Java:对于我们的一些项目,我确实实现了一个基于 Xtext 的解决方案,它从项目特定的 DSL 生成源代码和 Thrift IDL 文件。由于 Xtext/Xtend 是基于 Java 的,如果该解决方案能够满足您的需求,至少值得一看。但是,我有一种轻微的感觉,在你的情况下它可能有点过分了。

结果,似乎节俭迫使自己成为我的服务器的专有持久性格式 [...]

这不是 Thrifts 的错,它可以是任何格式。

但是,我(强烈)觉得我需要自由编辑我的服务器在 API 中处理的数据结构。

我完全同意。特别是在这种情况下,建议将序列化与内部数据结构分开,并将序列化视为真正的序列化:只是操作数据的一种方法1)。如果你有不止一种序列化格式,你总是会以类似的方式多次实现很多东西。这种影响或多或少是不可避免的,为我们提供了以对项目最好的方式来实现它的机会。

简单的序列化策略适用于一种格式。使用二/三种格式变得繁琐,最终变成具有三种以上格式的真正的 PITA。2)与往常一样,可维护和可扩展的解决方案是以增加一些复杂性为代价的。3)

您会看到,尽管您可以选择其中一种格式作为“最喜欢的主数据格式”,但从技术上讲,您不必这样做。


(1) 惊人比例的编程初学者教程和书籍未能正确传达这一点。(2) 这正是我在开头提到的通过 DSL 解决的用例。(3) 是的,我知道 YAGNI 是什么意思。我知道如何估计风险的期望值。

于 2014-09-03T20:20:19.057 回答
0

不,Thrift 只应该用于客户端和服务器之间的消息,而不是用于服务器内部的持久性:例如,您将如何查询它?

于 2014-09-03T18:46:21.387 回答