如何从 CDN 提供 GWT 静态文件

Posted

技术标签:

【中文标题】如何从 CDN 提供 GWT 静态文件【英文标题】:How to serve GWT static files from a CDN 【发布时间】:2012-12-08 15:41:03 【问题描述】:

我试图弄清楚如何从 CDN 而不是从 tomcat 服务器提供我的 GWT 文件。

我从这段代码开始

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="robots" content="no-index, no-follow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Site</title>
<script type="text/javascript" src="/bcmjs/bcmjs.nocache.js"></script>
</head>

<body>
<div id="gwt_div">
</div>
</body>
</html>

并修改了 javascript 导入以使用 CDN url,来自:

<script type="text/javascript" src="/bcmjs/bcmjs.nocache.js"></script>

到这里:

<script type="text/javascript" src="https://uoo9w.cloudfront.net/bcmjs/bcmjs.nocache.js"></script>

万岁! js 下载,UIBinder 小部件可见,但 RPC 失败。

问题似乎是 GWT.getModuleBase 返回 Javascript 的 URL (uoo9w.cloudfront.net) 而不是主机页面 (mysite.example.com),这会破坏诸如用于 RPC 请求的 URL 之类的东西。

GWT.getModuleBaseForStaticFiles 似乎是一种允许使用 CDN 的方法,但我找不到有关它的文档。 (参见 cmets)

有谁知道设置 GWT 以从 CDN 提供服务并将 RPC 请求发送到主机页面的域的正确方法?

旁注:

由于 CDN 具有不同的域名和路径,我担心会出现涉及同源策略的问题,但由于 GWT 主机页面与所有 RPC 请求在同一个域上提供服务,所以这不是一个问题。 (即 Window.Location 与 RPC 是同一个域)

【问题讨论】:

仅供参考 getModuleBaseForStaticFiles 已针对 Super Dev Mode 引入:静态文件由 SuperDevMode CodeServer 提供服务,但 getModuleBaseURL 是您自己的服务器,也为 getHostPageBaseURL 提供服务。 【参考方案1】:

GWT 设置 RPC 的 url 指向 modulename.nocache.js 脚本标签的 src 属性,而不是文档的 location

修复它的正常方法是更改​​ rpc 服务的基本 URL 以指向 html 文件的 location

GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
((ServiceDefTarget)greetingService)
   .setServiceEntryPoint("http://hostname_of_your_document/modulename/greet");

注意:在这种情况下,您没有进行 跨域,因为您的 .html 和您的 services 位于同一主机中。

可选地,如果services.html 文件不在同一主机中,则您正在执行跨域,因此您可以配置您的servlet 以支持CORS。最好的方法是在你的web.xml中配置一个过滤器

<filter>
  <filter-name>corsFilter</filter-name>
  <filter-class>com.example.server.CORSFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>corsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

对于过滤器类,您可以使用我为 gwtquery Ajax documentation 所做的示例

【讨论】:

谢谢,第一部分是正确的,但如果您仔细阅读我的问题,您会发现 CORS 不是必需的,因为 CDN 不提供“主机页面”。因此,Window.Location 属性中的域与 xmlhttprequest 的域匹配。无论如何都赞成,因为 CORS 部分可能对许多其他人有用。 明白了。因此,您必须手动设置 serviceEntryPoint,因为 afaik,gwt 根据与您的module_name.nocache.js 匹配的文档中script 标记的src 计算主机名。其他选项可能是重写 gwt 用于计算名称的算法,或者在文档中真正的 nocache 脚本之前放置一个具有相同名称和不同主机的空脚本。 我接受了你的回答(我认为你可以使用代表,而且我对 GWTQuery 很感兴趣)。您能否更新您的答案以表明 CORS 是可选的?【参考方案2】:

所以答案似乎是为每个 RPC 接口手动调用ServiceDefTarget.setServiceEntryPoint()

这是我用来将moduleBaseURL 替换为主机页面的网址的代码。它让我可以在所有RemoteService 接口上使用现有的@RemoteServiceRelativePath 注释。

public static native String getHostpageUrl()/*-
   return $wnd.location.protocol + "//" + $wnd.location.host + "/";
-*/;

GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

ServiceDefTarget serviceDefTarget= ((ServiceDefTarget)greetingService);
String oldUrl = serviceDefTarget.getServiceEntryPoint();
String newServiceEntryPoint =  oldUrl.startsWith(GWT.getModuleBaseURL()) ? 
        getBaseUrl() + "module/" + oldUrl.substring(GWT.getModuleBaseURL().length(), value.length()) 
       : oldUrl;
serviceDefTarget.setServiceEntryPoint(newServiceEntryPoint);

【讨论】:

【参考方案3】:

请参阅此详细说明,了解您需要更新才能通过 AWS CloudFront 等 CDN 运行 GWT 应用程序。

https://groups.google.com/forum/?fromgroups#!topic/google-web-toolkit/4eNY2RiLH1k

希望对您有所帮助。

【讨论】:

以上是关于如何从 CDN 提供 GWT 静态文件的主要内容,如果未能解决你的问题,请参考以下文章

nginx代理cdn静态文件不一致

如何在 nginx 中缓存静态文件

静态资源库CDN服务

vu静态资源打包放到cdn

CDN

如何从数据库获取/发送/提供/(使可访问)数据到静态 jquery 文件?从快速 EJS 到静态 Jquery?