1

大约 2 年前,我使用 GWT 开发了一个 Web 应用程序,从那时起,该应用程序不断发展。在当前状态下,它依赖于获取单个 XML 文件并从中解析信息。总的来说,这很好用。这个应用程序的一个要求是它需要能够从文件系统 (file:///..) 以及从网络服务器 ( http://.. )运行的传统模型运行

使用RequestBuilder对象从网络服务器获取此文件完全符合预期。从文件系统 Firefox、Opera、Safari 和 Chrome 运行应用程序时,它们的行为都符合预期。当使用 IE7 或 IE8 从文件系统运行应用程序时,RequestBuilder.send()调用失败,有关错误的信息表明由于违反同源策略而访问文件时出现问题。该应用程序在 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 group 上有一个帖子,其中有一个解决此问题的假设解决方案(链接)。看着它,我可以看出它是为旧版本的 GWT 创建的。我正在使用最新版本,并认为这或多或少是我想做的(使用GWT 延迟绑定来检测特定的浏览器类型并运行我自己的 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 吗?

有没有我没有提到的解决这个问题的不同方法?

欢迎所有回复。

4

2 回答 2

4

你错过了一件关键的事情——打电话给GWT.create

为了使延迟绑定起作用,必须有人在该类上调用 GWT.create com.google.gwt.xhr.client.XMLHttpRequest- 只有这样您才能获得特定于您需要的实现。如果查看 RequestBuilder.java,它会直接在 deSend() 方法的第一行实例化一个 XMLHttpRequest 对象。也就是说,没有调用GWT.create(),因此您的 IE 特定实现不会被拾取。

要解决问题,您必须替换此行

XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create();

XMLHttpRequest xmlHttpRequest = GWT.create(XMLHttpRequest.class);

所以,你要么修改 GWT 的源代码并重新编译(YUCK!),要么你做这样的事情 -

  1. 子类RequestBuilder并覆盖 sendRequest() 方法。
  2. 复制/粘贴doSend()方法中的所有内容,替换我上面提到的一行
  3. 在你的代码中做一个盲目的grep,并替换所有RequestBuilder实例MyRequestBuilder

我想这应该可以解决你的问题。

于 2010-04-17T15:37:00.810 回答
2

请注意,-不是Internet Explorer 6 和 Internet Explorer 7 的ie7有效值(请参阅UserAgent.gwt.xml以了解如何计算)。user.agentie6user.agent

也许这个无效值导致 GWT 完全避免使用您的代码?

于 2010-04-16T19:24:53.733 回答