gwt server

在 GWT 的术语中,客户机代码与运行在 Web 服务器上的服务 进行通信。用来公开这些服务的 RPC 机制与 Java RMI 使用的方法类似。这意味着只需要编写服务的服务器端实现和两个接口即可。代码生成和反射将负责处理客户机存根和服务器端主干代理(server-side skeleton proxies)。要做的第一步是定义服务的接口,这个接口必须扩展 GWT RemoteService 接口,它包含应该公开给 GWT 客户机代码的服务方法的签名。因为 GWT 中的 RPC 调用是在 JavaScript 代码和 Java 代码之间进行的,所以 GWT 集成了对象序列化机制,用它来协调跨语言分界(language divide)的参数和返回值(请参阅 可序列化类型 侧栏,了解您可以使用哪些可序列化类型)。{可序列化类型

GWT 下可序列化类型的简要概括如下:

    * 基本类(例如 int)和基本包装对象类(例如 Integer)是可序列化的。
    * String 和 Date 是可序列化的。
    * 可序列化类型的数组本身是可序列化的。
    * 如果用户自定义类的所有持久性成员是可序列化的,而且用户自定义类实现了 GWT 的 IsSerializable 接口,那么自定义类是可序列化的。
    * Collection 类可以与 Javadoc 注释结合使用,通过注释声明它们包含的可序列化类型。

因为客户机代码被限制在 GWT 实现的 Java 类的一个很小的子集上,所以这些可序列化类型的覆盖面相当广泛。}

定义了服务接口之后,下一步就是在扩展 GWT 的 RemoteServiceServlet 类的类中实现该接口。顾名思义,这是 Java 语言的 HttpServlet 的一个具体类,所以可以将它放在任何 servlet 容器中。

这里值得一提的一个 GWT 特性是:服务的远程接口必须位于应用程序的 client 包中,因为需要将它集成到 JavaScript 的生成过程中。但是,因为服务器端实现类引用了远程接口,所以现在在服务器端和客户机代码之间存在一个 Java 编译时依赖项。对于这个问题,我的解决方案是将远程接口放在 client 的 common 子包中。然后在 Java 构建中包含 common 包,但不包含 client 包中的剩余部分。这可以确保客户机代码生成的类文件只是那些需要转换成 JavaScript 的文件。更好的解决方案是将包结构分解成两个源目录,一个负责客户端代码,一个负责服务器端代码,然后将公共类复制到两个目录中。

以下代码显示了 Weather Reporter 应用程序使用的远程服务接口 WeatherService。它接受 ZIP 代码和摄氏/华氏标记作为输入,返回包含 HTML 天气描述的 String。清单 6 显示了 YahooWeatherServiceImpl 的框架,它使用 Yahoo! 的天气 API 获得给定 ZIP 代码的 RSS 天气种子,并从中获得 HTML 描述。

public interface WeatherService extends RemoteService {

   /**
    * Return HTML description of weather
    * @param zip zipcode to fetch weather for
    * @param isCelsius true to fetch temperatures in celsius,
    * false for fahrenheit
    * @return HTML description of weather for zipcode area
    */
   public String getWeatherHtml(String zip, boolean isCelsius)
      throws WeatherException;
}

public class YahooWeatherServiceImpl extends RemoteServiceServlet
   implements WeatherService {

   /**
    * Return HTML description of weather
    * @param zip zipcode to fetch weather for
    * @param isCelsius true to fetch temperatures in celsius,
    * false for fahrenheit
    * @return HTML description of weather for zipcode area
    */
   public String getWeatherHtml(String zip, boolean isCelsius)
      throws WeatherException {

     // Clever programming goes here
   }
}


从这时起,就开始脱离标准的 RMI 方法。因为来自 JavaScript 的 Ajax 调用是异步的,所以需要做些额外的工作来定义客户机代码用来调用服务的异步接口。异步接口的方法签名与远程接口的方法签名有所不同,所以 GWT 要依靠 Magical Coincidental Naming。换句话说,在异步接口和远程接口之间不存在静态的编译时关系,但是 GWT 会通过命名约定来指出该关系。清单 7 显示了 WeatherService 的异步接口:

WeatherService 的异步接口

public interface WeatherServiceAsync {

   /**
    * Fetch HTML description of weather, pass to callback
    * @param zip zipcode to fetch weather for
    * @param isCelsius true to fetch temperatures in celsius,
    * false for fahrenheit
    * @param callback Weather HTML will be passed to this callback handler
    */
   public void getWeatherHtml(String zip, boolean isCelsius,
      AsyncCallback callback);
}

可以看到,一般的想法是创建叫做 MyServiceAsync 的接口,并提供与每个方法签名对等的事物,然后删除所返回类型,添加类型为 AsyncCallback 的额外参数。异步接口必须放在与远程接口相同的包中。AsyncCallback 类有两个方法:onSuccess() 和 onFailure()。如果对服务的调用成功,则用服务调用的返回值调用 onSuccess()。如果远程调用失败,则调用 onFailure(),并传递由该服务生成的 Throwable,以表示失败的原因。


从客户机调用服务

有了 WeatherService 和它的异步接口之后,现在就可以修改 Weather Reporter 客户机,从而调用服务并处理服务器响应。第一步只是公式化地设置代码:通过调用 GWT.create(WeatherService.class) 并向下传送所返回的对象,创建一个在 Weather 客户机上使用的 WeatherServiceAsync 实例。接下来,必须将 WeatherServiceAsync 强行转换成 ServiceDefTarget,这样才能在它上面调用 setServiceEntryPoint()。setServiceEntryPoint() 指向对应的远程服务实现所部署的 URL 上的 WeatherServiceAsync 存根。请注意,这实际上是在编译时硬编码的。因为这个代码成为在 Web 浏览器中部署的 JavaScript,所以没办法在运行时从属性文件中查找这个 URL。显然,这限制了编译后的 GWT Web 应用程序的移植性。

显示了 WeatherServiceAsync 对象的设置,然后给出了 fetchWeatherHtm() 的实现,这个实现我在前面提到过

使用 RPC 调用远程服务

// Statically configure RPC service
private static WeatherServiceAsync ws =
   (WeatherServiceAsync) GWT.create(WeatherService.class);
static {
   ((ServiceDefTarget) ws).setServiceEntryPoint("ws");
}

/**
* Asynchronously call the weather service and display results
*/
private void fetchWeatherHtml(String zip, boolean isCelsius) {

   // Hide existing weather report
   hideHtml();

   // Call remote service and define callback behavior
   ws.getWeatherHtml(zip, isCelsius, new AsyncCallback() {
      public void onSuccess(Object result) {

         String html = (String) result;

         // Show new weather report
         displayHtml(html);
      }

      public void onFailure(Throwable caught) {
         Window.alert("Error: " + caught.getMessage());
         txBox.setEnabled(true);
       }
   });
}
对服务的 getWeatherHtml() 的实际调用实现起来非常简单:使用一个匿名回调句柄类将服务器的响应传递给显示响应的方法即可。
参与网站:
http://www.ibm.com/developerworks/cn/java/j-ajax4/index.html

你可能感兴趣的:(JavaScript,html,应用服务器,浏览器,gwt)