3

我已经用 Java 后端的 GWT + GAE 建立了一个简单的 Web 应用程序(很像教程中的 stockwatcher 示例:http: //www.gwtproject.org/doc/latest/tutorial/clientserver.html)。从 .appspot.com 域提供服务时,它运行良好。

我希望能够从不同的服务器(现在我的 PC 中的本地 Web 服务器)为客户端(GWT)部分提供服务,并且仍然使用 GAE 作为后端。如何才能做到这一点?

尝试的解决方案

我认为这加起来就是做跨服务器 Ajax,我没有找到太多关于如何做到这一点的信息,所以我通过反复试验进行;这是我所做的:

客户端应用程序称为myapp_web,服务器端称为myapp

我将 GWT 部分复制到本地服务器的目录/webapps/myapp_web 中;它加载得很好。我在/webapps/myapp_web/myapp上遇到 404 错误,所以我推断这是应用程序尝试查找后端的 url。

我在http://developer.yahoo.com/javascript/howto-proxy.html中找到了一个示例 PHP 脚本,它应该用作代理以允许跨服务器调用:

<?php

// PHP Proxy example for Yahoo! Web services. 
// Responds to both HTTP GET and POST requests
//
// Author: Jason Levitt
// December 7th, 2005
//

// Allowed hostname (api.local and api.travel are also possible here)
define ('HOSTNAME', 'http://search.yahooapis.com/');

// Get the REST call path from the AJAX application
// Is it a POST or a GET?
$path = ($_POST['yws_path']) ? $_POST['yws_path'] : $_GET['yws_path'];
$url = HOSTNAME.$path;

// Open the Curl session
$session = curl_init($url);

// If it's a POST, put the POST data in the body
if ($_POST['yws_path']) {
    $postvars = '';
    while ($element = current($_POST)) {
        $postvars .= urlencode(key($_POST)).'='.urlencode($element).'&';
        next($_POST);
    }
    curl_setopt ($session, CURLOPT_POST, true);
    curl_setopt ($session, CURLOPT_POSTFIELDS, $postvars);
}

// Don't return HTTP headers. Do return the contents of the call
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

// Make the call
$xml = curl_exec($session);

// The web service returns XML. Set the Content-Type appropriately
header("Content-Type: text/xml");

echo $xml;
curl_close($session);

?>

我将此脚本复制到/webapps/myapp_web/myapp,文件myapp,没有扩展名,我让 Apache 将其作为 php 处理。我将变量HOSTNAMEhttp://search.yahooapis.com/更改为http://myapp_url.appspot.com/myapp_web/myapp

现在我收到 500 服务器错误,我被卡住了,不知道如何调试它。感谢您的任何帮助,您可以提供。

4

2 回答 2

0

正如您在问题中所说,有两种选择可以解决此问题:

  • 第一个选项是正确设置您的服务器端(GAE 应用程序)以正确处理跨域资源共享(CORS)。这仅适用于支持它的浏览器。现在大多数浏览器都包含 IE10。IE8/9 需要不同的方法XDomainRequest
  • 第二个是在服务器端使用代理,就像您尝试过的那样。但是您必须编写请求服务器,添加X-GWT-Permutation来自您的客户端的请求。否则 gwt servlet 将引发SecurityException500 响应。

话虽如此,我会继续使用 CORS 选项,因为它简单、轻巧,并且将成为标准方式。

要配置 CORS,您只需在 Web 应用程序中设置一个过滤器。

将这些行添加到您的web.xml文件中:

<filter>
 <filter-name>CORSFilter</filter-name>
 <filter-class>my.namespace.CORSFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>CORSFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

并编写一个 servlet 过滤器来处理请求,并使用适当的标头进行响应。

这里有一个我前段时间为gwt-query ajax wiki编写的示例。

 public class CORSFilter implements Filter {
   // For security reasons set this regex to an appropriate value
   // example: ".*example\\.com"
   private static final String ALLOWED_DOMAINS_REGEXP = ".*";

   public void doFilter(ServletRequest servletRequest,
       ServletResponse servletResponse, FilterChain filterChain)
       throws IOException, ServletException {

     HttpServletRequest req = (HttpServletRequest) servletRequest;
     HttpServletResponse resp = (HttpServletResponse) servletResponse;

     String origin = req.getHeader("Origin");
     if (origin != null && origin.matches(ALLOWED_DOMAINS_REGEXP)) {
       resp.addHeader("Access-Control-Allow-Origin", origin);
       if ("options".equalsIgnoreCase(req.getMethod())) {
         resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
         if (origin != null) {
           String headers = req.getHeader("Access-Control-Request-Headers");
           String method = req.getHeader("Access-Control-Request-Method");
           resp.addHeader("Access-Control-Allow-Methods", method);
           resp.addHeader("Access-Control-Allow-Headers", headers);
           resp.setContentType("text/plain");
         }
         resp.getWriter().flush();
         return;
       }
     }

    // Fix ios6 caching post requests
    if ("post".equalsIgnoreCase(req.getMethod())) {
      resp.addHeader("Cache-Control", "no-cache");
    }

    if (filterChain != null) {
      filterChain.doFilter(req, resp);
    }
  }

  @Override public void destroy() {}
  @Override public void init(FilterConfig arg0) throws ServletException {}
}

在您的客户端代码中,您必须设置完整的 url 才能访问您的服务器,但这取决于您使用的 ajax 类型(RPC、RequestFactory、RequestBuilder 等)。

在您使用 RPC 的情况下,您必须这样做:

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

 ((ServiceDefTarget)greetingService)
     .setServiceEntryPoint("http://mygaeapp.appspot.com/mymodule/greet");
于 2013-09-06T23:29:12.667 回答
-1

那么这是否使它成为 GAE 呢?你从哪里得到 500 错误?GAE 还是本地 apache?这是否与您的 gwt 服务器在相同的主机名/端口上运行?如果不是,您可能会使用同源策略。

我认为您想要的架构基本上是这样的:

浏览器 -> GWT 服务器(tomcat?) -> 返回 gwt 代码

浏览器 -> GWT RPC 调用 GWT 服务器 -> GWT 服务器通过服务或休息调用调用 GAE -> GWT 格式化响应并将数据返回给浏览器。

虽然老实说我不知道​​你为什么要把两者分开。看起来你只是让这比必要的更难。

于 2013-09-06T16:17:26.580 回答