GWT如何减少RPC调用的代码序列化程序的大小
我发现GWT在我的应用程序上生成的javaScript代码中有60%以上是用于RPC序列化程序的。 我还发现服务接口之间不共享序列化程序,我的意思是,如果我在2个rpc服务接口上引用了AccountDTO类型,那么对于同一类型,我将得到2个序列化程序类,而不是1个。 为了减少编译代码的大小,我在想,也许我可以使用延迟绑定来替换一个大接口中的所有服务接口。如果这是可能的,那么GWTCompiler将只生成一个AccountDTO序列化程序,而不是2个 我不确定这是否是一个好主意,也不确定是否有更好的方法解决我的问题 我试图实现的是这样的:GWT如何减少RPC调用的代码序列化程序的大小,gwt,gwt-rpc,Gwt,Gwt Rpc,我发现GWT在我的应用程序上生成的javaScript代码中有60%以上是用于RPC序列化程序的。 我还发现服务接口之间不共享序列化程序,我的意思是,如果我在2个rpc服务接口上引用了AccountDTO类型,那么对于同一类型,我将得到2个序列化程序类,而不是1个。 为了减少编译代码的大小,我在想,也许我可以使用延迟绑定来替换一个大接口中的所有服务接口。如果这是可能的,那么GWTCompiler将只生成一个AccountDTO序列化程序,而不是2个 我不确定这是否是一个好主意,也不确定是否有更好
// 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>
...
...
package com.arballon.gwt.core.client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface GenericBigService extends RemoteService,
AccountingService,
ActionClassifierService,
AFIPWebService,
AnalyticalService,
AuthorizationService,
BudgetService,
BusinessUnitService,
CatalogPartService,
CategoryService,
ClientDepositService,
.....
.....
{ }
public interface FinancialPeriodBalanceCategoryService extends RemoteService {
/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static FinancialPeriodBalanceCategoryServiceAsync instance;
public static FinancialPeriodBalanceCategoryServiceAsync getInstance() {
if (instance == null) {
instance = GWT.create(GenericBigService.class);
((ServiceDefTarget)instance).setServiceEntryPoint(GWT.getModuleBaseURL()+"FinancialPeriodBalanceCategoryService");
}
return instance;
}
}
//定义扩展所有服务接口的新接口
公共接口GenericService扩展了RemoteService,
会计服务,
金融服务,{}
公共接口GenericServiceAsync扩展AccountingServiceAsync,
金融服务同步,{}
//在Application.gwt.xml上执行以下操作:
...
...
...
...
但在我收到错误的那一刻:
“文件:/C:/Users/Daniel/EclipseWorkspace/ADK/src/com/arballon/gwt/core/client/FinancialService.java”中的[ERROR]错误
[错误]第31行:找不到重新绑定结果'com.arballon.gwt.core.client.GenericService'
如果您对这个问题有任何想法,我们将不胜感激。
问候
Daniel据我所知,GWT代码生成应该提供接口的具体实现。然后将此实现转换为javascript以进行特定排列 另一方面,您的示例正在用另一个接口替换一个接口。如果从GWT编译器的角度来看,您可能会看到此配置的问题 假设您是GWT编译器,您将在客户端代码中看到下面一行代码,并将其转换为JavaScript
AccountingServiceAsync accountingServiceAsync = (AccountingServiceAsync) GWT.create(AccountingService.class);
accountingServiceAsync.recordTransaction(transaction,callback);
因此,您需要在第2行了解应该发生什么。具体来说,您需要知道在哪里可以找到accountingServiceAsync.recordTransaction()的实现。因此,您需要查看所有配置,以确定是否有规则指定AccountingService(非异步)应使用哪个实现类。但遗憾的是你找不到。但是您注意到AccountingService也是一个远程服务。因此,您需要再次深入了解您的配置。而且,啊哈,这是一条规则,规定你可以。您很高兴地将提供AccountingService实现的任务移交给ServiceInterfaceProxyGenerator
但是,假设您的配置告诉您AccountingService可以是GenericService,而不是这个圆满的结局,您会说,“嘿,酷,开始吧”。但就在这时,您发现GenericService也是一个接口。显然,你会被关闭,说“现在,我要用另一个接口做什么,我所需要的只是AccountingService的实现”。在这一点上,你想通过向程序员抛出一个神秘的错误来报复他
到目前为止,所有这些都解释了为什么你的解决方案(理论上)不起作用。至于您对臃肿javascript的实际关注,我很惊讶,考虑到GWT人员在优化已编译javascript方面付出的努力,这个问题竟然存在。您是如何测试编译的输出的重复性的?对于任何GWT-RPC服务,GWT都将生成一个代理和一个TypeSerializer。对于可能通过GWT传递的每个对象,您将有一个FieldSerializer类。每个类只能有一个FieldSerializer。因此,一个AccountDTO不能有两个FieldSerializer 您尝试使用的延迟绑定规则将不起作用。例如,您有如下内容: MyServiceAsync sync=GWT.create(MyService.class) 延迟绑定规则将其更改为: MyServiceAsync sync=new myServiceAsyncu Proxy() 您的规则实际上会执行以下操作:
// 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>
...
...
package com.arballon.gwt.core.client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface GenericBigService extends RemoteService,
AccountingService,
ActionClassifierService,
AFIPWebService,
AnalyticalService,
AuthorizationService,
BudgetService,
BusinessUnitService,
CatalogPartService,
CategoryService,
ClientDepositService,
.....
.....
{ }
public interface FinancialPeriodBalanceCategoryService extends RemoteService {
/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static FinancialPeriodBalanceCategoryServiceAsync instance;
public static FinancialPeriodBalanceCategoryServiceAsync getInstance() {
if (instance == null) {
instance = GWT.create(GenericBigService.class);
((ServiceDefTarget)instance).setServiceEntryPoint(GWT.getModuleBaseURL()+"FinancialPeriodBalanceCategoryService");
}
return instance;
}
}
MyServiceAsync sync=新建MyGenericService()//无效,因为MyGenericService是一个接口
因此,您的解决方案将不起作用
既然您说应用程序生成的代码中有60%是与RPC相关的东西,我怀疑您有RPC类型爆炸的问题
检查GWT在编译过程中是否没有抛出任何警告,或者是否为RPC类型序列化程序生成存根,很可能您在服务中有一些非常常见的接口。GWT的RPC生成代码构建了几个类来完成它的工作,正如您所指出的那样:一个
*\u FieldSerializer
用于连接的每种类型,以及用于RemoteService异步类型的*\u代理
类。该代理类型需要一个*\u TypeSerializer
,这是问题的根源-出于某种原因,GWT将所有序列化/反序列化方法连接在一个string->js函数映射中,可能是为了方便快速查找-但此设置代码以需要在最终构建中的代码行为代价。更优化的方法可以让每个FieldSerializer
都有一个注册方法,将其方法添加到代理所拥有的静态映射中-然而,这是一个难题,但是GWT优化了尝试不引用实例化()
,反序列化()
和序列化()
方法如果不出现,将调用它们
您的问题源于具有许多可以序列化的类型,以及您试图构建每个描述特定功能单元的RemoteService
类型,但重复使用了许多模型类型。这是一个令人钦佩的目标,特别是因为它可能会使您的服务器端代码看起来更好,但显然GWT为此咬了您一口
我试图在freenode上为您提供的解决方案