2010-04-16 64 views
1

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

将文件从网络服务器的工作原理与使用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实现,它似乎只支持与Web服务器上的文件进行交互。

我在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时,我捕捉失败的情况呢?

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

欢迎各位回复。

回答

2

注意ie7不是user.agent有效值 - ie6是双方的Internet Explorer 6和Internet Explorer 7(见UserAgent.gwt.xmluser.agent如何计算)的值。

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

+0

感谢您的建议。我已更新我的代码和问题与这些信息,但不幸的是,问题仍然存在 – snctln 2010-04-16 19:45:33

4

你缺少一个关键的事情 - 要GWT.create

建立一个呼叫的deferred binding工作,总要有人打电话GWT.create在类com.google.gwt.xhr.client.XMLHttpRequest - 只有这样,你得到您的具体需要的实现。如果您查看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! ),或者你这样做 -

  1. 子类RequestBuilder并覆盖sendRequest()方法。从doSend()方法
  2. 复制/粘贴一切更换一条线上面我
  3. 提到不要在你的代码盲grep和与MyRequestBuilder

取代的RequestBuilder所有实例我想这应该解决你的问题。

+0

伟大..它适用于我:) – sunnychayen 2013-02-22 10:54:05