Google Web Toolkit 延迟绑定问题
Posted
技术标签:
【中文标题】Google Web Toolkit 延迟绑定问题【英文标题】:Google Web Toolkit Deferred Binding Issue 【发布时间】:2011-02-08 23:12:19 【问题描述】:大约 2 年前,我使用 GWT 开发了一个 Web 应用程序,此后该应用程序不断发展。在当前状态下,它依赖于获取单个 XML 文件并从中解析信息。总的来说,这很好用。这个应用程序的一个要求是它需要能够从文件系统 (file:///..) 以及从网络服务器 (http://...) 运行的传统模型运行。
使用RequestBuilder 对象从网络服务器获取此文件完全符合预期。从文件系统 Firefox、Opera、Safari 和 Chrome 运行应用程序时,它们的行为都符合预期。当使用 IE7 或 IE8 从文件系统运行应用程序时,RequestBuilder.send() 调用失败,有关错误的信息表明由于违反 same origin policy 而访问文件时出现问题。 该应用在 IE6 中按预期运行,但在 IE7 或 IE8 中无法正常运行。
所以我查看了RequestBuilder.java 的源代码,发现实际请求是使用 XMLHttpRequest GWT 对象执行的。于是我查看了XMLHttpRequest.java的源代码,发现了一些信息。
这里是代码(从 XMLHttpRequest.java 的第 83 行开始)
public static native XMLHttpRequest create() /*-
if ($wnd.XMLHttpRequest)
return new XMLHttpRequest();
else
try
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
catch (e)
return new ActiveXObject("Microsoft.XMLHTTP");
-*/;
因此,基本上如果无法创建 XMLHttpRequest(例如在 IE6 中,因为它不可用),则使用 ActiveXObject 代替。
我阅读了更多关于 XMLHttpRequest 的 IE 实现的信息,似乎它只支持与网络服务器上的文件交互。
我在 IE8 中找到了一个设置(工具->Internet 选项->高级->安全->启用本机 XMLHTTP 支持),当我取消选中此框时,我的应用程序可以正常工作。我认为这是因为我很少告诉 IE 不要使用他们的 XmlHttpRequest 实现,所以 GWT 只使用 ActiveXObject,因为它认为本机 XmlHttpRequest 不可用。
这解决了问题,但不是一个长期的解决方案。
我目前可以捕获失败的发送请求并验证它是否正在尝试使用普通 GWT 从文件系统中获取 XML 文件。在这种情况下,我想做的是抓住 IE7 和 IE8 的情况,让它们使用 ActiveXObject 而不是本机 XmlHttpRequest 对象。
在 GWT google 组上有一个帖子,该帖子提供了解决此问题的假设方法 (link)。看着它,我可以看出它是为旧版本的 GWT 创建的。我正在使用最新版本,并认为这或多或少是我想做的(使用GWT deferred binding 来检测特定的浏览器类型并运行我自己的 XMLHttpRequest.java 实现来代替内置的 GWT 实现)。
这是我尝试使用的代码
package com.mycompany.myapp.client;
import com.google.gwt.xhr.client.XMLHttpRequest;
public class XMLHttpRequestIE7or8 extends XMLHttpRequest
// commented out the "override" so that eclipse and the ant build script don't throw errors
//@Override
public static native XMLHttpRequest create()
/*-
try
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
catch (e)
return new ActiveXObject("Microsoft.XMLHTTP");
-*/;
// have an empty protected constructor so the ant build script doesn't throw errors
// the actual XMLHttpRequest constructor is empty as well so this shouldn't cause any problems
protected XMLHttpRequestIE7or8()
;
这是我添加到我的模块 xml 中的行
<replace-with class="com.mycompany.myapp.client.XMLHttpRequestIE7or8">
<when-type-is class="com.google.gwt.xhr.client.XMLHttpRequest"/>
<any>
<when-property-is name="user.agent" value="ie6" />
<when-property-is name="user.agent" value="ie8" />
</any>
</replace-with>
据我所知,这应该可以,但我的代码永远不会运行。
有人知道我做错了什么吗?
我是否应该不通过延迟绑定来执行此操作,而在捕获失败案例时只使用本机 javascript?
有没有我没有提到的解决这个问题的不同方法?
欢迎所有回复。
【问题讨论】:
【参考方案1】:你错过了一件关键的事情——打电话给GWT.create
要使deferred binding 工作,必须有人在com.google.gwt.xhr.client.XMLHttpRequest
类上调用 GWT.create - 只有这样您才能获得特定于您需求的实现。如果查看 RequestBuilder.java,它直接实例化了一个 XMLHttpRequest 对象on the first line of deSend() method。也就是说,没有对 GWT.create()
的调用,因此您的 IE 特定实现不会被拾取。
要解决问题,你必须替换这一行
XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create();
与
XMLHttpRequest xmlHttpRequest = GWT.create(XMLHttpRequest.class);
因此,您要么修改 GWT 的源代码并重新编译(YUCK!),要么执行类似的操作 -
-
子类
RequestBuilder
并覆盖 sendRequest() 方法。
复制/粘贴 doSend()
方法中的所有内容但是替换我上面提到的一行
在您的代码中执行盲 grep,并将所有 RequestBuilder
实例替换为 MyRequestBuilder
我想这应该可以解决你的问题。
【讨论】:
【参考方案2】:请注意,ie7
不是 user.agent
的有效值 - ie6
是 Internet Explorer 6 和 Internet Explorer 7 的值(请参阅 UserAgent.gwt.xml,了解如何计算 user.agent
)。
也许这个无效值导致 GWT 完全避免使用您的代码?
【讨论】:
感谢您的建议。我已经用这些信息更新了我的代码和问题,但不幸的是问题仍然存在以上是关于Google Web Toolkit 延迟绑定问题的主要内容,如果未能解决你的问题,请参考以下文章