GWT如何减少RPC调用的代码序列化程序的大小 [英] GWT how can I reduce the size of code serializers for RPC calls

查看:79
本文介绍了GWT如何减少RPC调用的代码序列化程序的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现在我的应用程序中由GWT生成的超过60%的javaScript代码用于RPC序列化器。
另外我发现序列化程序不在服务接口之间共享,我的意思是如果我有例如在2个rpc服务接口上引用的AccountDTO类型,我将得到2个序列化程序类而不是1个相同类型。
为了减少编译代码的大小,我在想,也许我可以使用延迟绑定来替换我为一个大界面所用的所有服务接口。如果可能的话,那么GWTCompiler可能只会生成一个AccountDTO序列化器,而不是2个。



我不确定这是个好主意还是更好解决方案为我的问题。



我试图实现的是这样的:

  //定义扩展所有服务接口的新接口
public interface GenericService扩展RemoteService,
AccountingService,
FinancialService,...,{}

公共接口GenericServiceAsync扩展了AccountingServiceAsync,
FinancialServiceAsync,...,{}

//在Application.gwt.xml中:

< module>
...
...
< replace-with class =com.arballon.gwt.core.client.GenericService>
< when-this-is class =com.arballon.gwt.core.client.AccountingService>
< / replace-with>
< replace-with class =com .arballon.gwt.core.client.GenericService>
< when-this-is class =com.arballon.gwt.core.client.FinancialService>
< / replace-with>
...
...

但目前我收到错误:
$ b

[错误]'file:/ C:/ Users / Daniel / EclipseWorkspace / ADK / src / com / arballon / gwt / core / client / FinancialService.java'
[错误]第31行:无法找到重新绑定结果'com.arballon.gwt.core.client.GenericService'

任何想法关于这个问题将不胜感激。
Regards



Daniel

解决方案

GWT的RPC生成代码建立几个类来完成它的工作,正如你已经注意到的那样:对于每一种类型的 * _ FieldSerializer ,以及 * _ Proxy 类用于RemoteService异步类型。这个代理类型需要一个 * _ TypeSerializer ,这是你问题的根源 - 出于某种原因,GWT在string-> js函数中连接了所有的序列化/反序列化方法地图,可能有助于快速查找 - 但此设置代码的代价是需要在最终版本中生成的代码行。一个更优化的方法可以让每个 FieldSerializer 都有一个注册方法,它将它的方法添加到代理所拥有的静态映射中 - 然而这受到了困扰,但是,GWT的尝试优化不引用 instantiate() deserialize() serialize()

你的问题源于许多类型可以被序列化,并且你试图构建<$> c $ c> RemoteService 类型,每个类型描述特定的功能单元,但重用多种模型类型。令人钦佩的目标,尤其是它可能会让你的服务器端代码看起来更漂亮,但很显然,GWT会咬你的。



我尝试在freenode上提供的解决方案作为niloc132)将构建一个名为 GeneralService 的单个大 RemoteService 类型,并匹配 GeneralServiceAsync ,每个扩展所有现有的rpc服务类型。我的第一个想法是使用< replace-with> 来告诉生成器系统,当您希望每个RemoteService类型用 GeneralService ,但正如Tahir指出的那样,这没有任何意义 - GWT不会将重新绑定的结果返回给自己,以继续查找。相反,我会建议,当你想要一个服务异步类型,请执行以下操作:

  AccountingServiceAsync服务=(AccountingServiceAsync)GWT。 create(GeneralService.class)

来自 GeneralService 将实现 GeneralServiceAsync ,它本身可分配给 AccountingServiceAsync 。如果内存提供服务,则表示您有提供这些服务的静态方法/字段 - 更改这些站点以始终创建 GeneralServiceAsync 实例。只要您不在任何 RemoteService 子类型上调用 GWT.create ,但是 GeneralService code>,你会将 TypeSerializers 的数目限制为一个。



RemoteServiceProxy 子类型是无状态的,所以确保只创建一个实例可以使构建一致性更容易,但不会节省运行时内存或时间,因为它们几乎可以编译为静态方法。然而, * _ TypeSerializer 类具有状态,但每个类只有一个实例,因此将所有 RemoteService s可能会节省很少的工作记忆。


I found that the more than 60% of the javaScript code generated by GWT on my application is for RPC serializers. Also I found that serializers are not shared between service interfaces, I mean if I have for example AccountDTO type referenced on 2 rpc service interfaces, I will get 2 serializer classes instead of 1 for the same type. In Order to reduce the size of the compiled code I was thinking that maybe I could use Deferred Binding in order to do a replacement of all the services interfaces I have for one big interface. If that could be possible, maybe then GWTCompiler will produce only one AccountDTO serializer instead of 2.

I'm not sure this is a good idea or if there is a better solution for my problem.

What I was trying to implement was something like this:

// Define new interface that extends all service interfaces
public interface GenericService extends RemoteService,
                    AccountingService,
                    FinancialService,..., { }

public interface GenericServiceAsync extends AccountingServiceAsync,
                         FinancialServiceAsync, ..., { }

// At Application.gwt.xml do:

<module>
...
...
    <replace-with class="com.arballon.gwt.core.client.GenericService">
        <when-this-is class="com.arballon.gwt.core.client.AccountingService>
    </replace-with>
    <replace-with class="com.arballon.gwt.core.client.GenericService">
        <when-this-is class="com.arballon.gwt.core.client.FinancialService>
    </replace-with>
    ...
    ...

But at the moment I was receiving the error:

[ERROR] Errors in 'file:/C:/Users/Daniel/EclipseWorkspace/ADK/src/com/arballon/gwt/core/client/FinancialService.java' [ERROR] Line 31: Rebind result 'com.arballon.gwt.core.client.GenericService' could not be found

Any thoughts about the issue will be appreciated. Regards

Daniel

解决方案

GWT's RPC generation code builds several classes to do its work as you've noted: a *_FieldSerializer for each type that goes over the wire, and a *_Proxy class for the RemoteService async type. That proxy type requires a *_TypeSerializer, which is the root of your problem - for some reason, GWT wires up all of the serialization/deserialization methods in a string->js function map, probably to facilitate fast lookups - but this setup code comes at the cost of lines of code that need to be in the final build. A more optimized approach could have each FieldSerializer have a registration method where it adds its methods to the static map owned by the Proxy - this is plagued, however, but GWT's optimization of attempting to not reference instantiate(), deserialize() and serialize() methods if it doesnt appear they will be called.

Your issue stems from having many types that can be serialized, and from your having attempted to build out RemoteService types that each describe specific units of functionality, but re-use many model types. Admirable goal, especially as it will probably make your server-side code look nicer, but apparently GWT bites you for it.

The solution I attempted to offer you on freenode (as niloc132) was to build a single large RemoteService type, which you named GeneralService, and a matching GeneralServiceAsync, each extending all of the existing rpc service types. My first thought was to use a <replace-with> to tell the generator system that when you want each RemoteService type to replace it with GeneralService, but as Tahir points out, this doesn't make sense - GWT doesn't pass rebind results back into itself to keep doing lookups. Instead, I would suggest that when you want a service async type, do the following:

AccountingServiceAsync service = (AccountingServiceAsync) GWT.create(GeneralService.class)

The rebind result from GeneralService will implement GeneralServiceAsync, which is itself assignable to AccountingServiceAsync. If memory serves, you said that you have static methods/fields that provide these services - change those sites to always create a GeneralServiceAsync instance. As long as you do not invoke GWT.create on any RemoteService subtype but GeneralService, you will limit the number of TypeSerializers to one.

As a side note, the RemoteServiceProxy subtypes are stateless, so ensuring that you create only one instance might make it easier to build consistently, but saves no runtime memory or time, as they are almost certainly compiled out to static methods. The *_TypeSerializer classes do have state however, but there is only one instance of each, so combining all of your RemoteServices might save a very small amount of working memory.

这篇关于GWT如何减少RPC调用的代码序列化程序的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆