【问题标题】:GWT hit HTTP servlet with RequestFactoryGWT 使用 RequestFactory 命中 HTTP servlet
【发布时间】:2013-02-02 20:02:56
【问题描述】:

如果可能,我想使用 GWT 的 RequestFactory 进行所有客户端-服务器通信。我的理解是,你必须在web.xml 中将/gwtServlet 映射到RequestFactoryServlet,然后使用@Service 注释告诉RequestFactoryServlet 如何将客户端请求映射到其相应的服务。

有人可以在客户端和服务器端提供此过程的完整代码示例吗?我想从客户端发送一个Widget 对象到服务器端的WidgetProcessor 服务:

public class Widget {
    // This is a domain object (POJO).
}

public class WidgetProcessor {
    public void processWidget(Widget w) {
        // Inspect the Widget. If certain properties contain certain
        // values, place it on a queue. Else "process" the Widget
        // and persist it to a DB.

        if(w.containsSpecialValues())
            QueueManager.sendToQueue(w);
        else {
            // Process widget...

            WidgetDAO.save(w);
        }
    }
}

在非 GWT 上下文中,我只需定义一个 WidgetProcessorServlet,将其映射到 /processWidget,并使其看起来像:

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
    WidgetProcessor widgetProcessor = new WidgetProcessor();
    widgetProcessor.processWidget(getWidgetFromRequest(request));
}

这在RequestFactory-land 中是如何工作的?提前致谢。

【问题讨论】:

  • 在回应您的陈述:“RF 可能只是作为数据访问层”和“不可能使用 RF 发送我的小部件......”我会说 RF 远不止数据访问层 - 它为 CRUD 生命周期提供支持,包括优化以仅发送对实体所做的更改。 RequestContext 是此次转移的关键。当您想从客户端向实体发送更改时,您可以使用 RequestContext.fire(),它会为您完成所有工作。
  • 这是另一个例子:cleancodematters.com/2011/06/04/…
  • 有趣的是你还没有选择答案!!!!!

标签: java gwt servlets requestfactory


【解决方案1】:

我刚刚为您开发了一个简单的骨架项目。 检查我的答案widget-processor on Github

该项目基于 Maven 构建器和 Java EE 平台 (GlassFish)。

项目模块:

  1. ear - 通用耳模块将其他模块集成在一个易于部署的 EAR 包中;
  2. persistence - 该模块只有一个文件persistence.xml 并将所有外部实体链接到一个数据源;
  3. ejb - 这个模块有实体 Widget 和无状态 EJB WidgetProcessor;
  4. web - 带有 RequestFactory 的通用 GWT 模块。

调整 Maven 构建过程以正确构建所有内容。该项目可以毫无问题地导入 IntelliJ Idea。并且可以使用标准的 Idea 工具在 Glassfish 中进行调试。

我还将 GWT RF 和 Persistence 样板代码移至 external bilionix-core artifacts on Github

【讨论】:

    【解决方案2】:

    RequestFactories 可以,但 GWT-RPC 也可以。我更喜欢 RequestFactories。

    您将拥有以下类和接口:

    在服务器上:

    1. 小部件(Servlet)
    2. 小部件处理器

    在客户端:

    1. 小部件代理
    2. 小部件请求
    3. WidgetRequestFactory
    4. WidgetPresenter

    WidgetServlet

    package com.foo.bar.server;
    public class Widget {
       //Your methods
        public void yourInstanceMethod(){
           //foo
        }
        public static void yourStaticMethod(){
           //bar
        }
        public static void processWidget(Widget w){
           WidgetProcessor widgetProcessor = new WidgetProcessor();
           widgetProcessor.processWidget(getWidgetFromRequest(request));
        }
    }
    

    小部件处理器

    package com.foo.bar.server;
    public class WidgetProcessor {
        public void processWidget(Widget w) {
            // Inspect the Widget. If certain properties contain certain
            // values, place it on a queue. Else "process" the Widget
            // and persist it to a DB.
    
            if(w.containsSpecialValues())
                QueueManager.sendToQueue(w);
            else {
                // Process widget...
    
                WidgetDAO.save(w);
            }
        }
    }
    

    小部件代理

    package com.foo.bar.server;
    import com.foo.bar.server.Widget;
    @ProxyFor(value = Widget.class)
    public interface WidgetProxy extends EntityProxy{
        //Your getter and Setter methods
    }
    

    小部件请求

    package com.foo.bar.client;
    import com.foo.bar.server.Widget;
    @Service(value = Widget.class)
    public interface WidgetRequest extends RequestContext{
        InstanceRequest<WidgetProxy, Void> yourInstanceMethod();
        Request<Void> yourStaticMethod();
        Request<Void> widgetProcessor(WidgetProxy widget);
    }
    

    WidgetRequestFactory

    package com.foo.bar.client;
    public interface WidgetRequestFactory extends RequestFactory{
        WidgetRequest widgetRequest();      
    }
    

    WidgetPresenter

    package com.foo.bar.client;
    public class WidgetPresenter {
        private final WidgetRequestFactory rf = GWT.create(WidgetRequestFactory.class);
        public WidgetPresenter() {
            rf.initialize(new EventBus());
            rf.widgetRequest().widgetProcessor().fire(new Receiver<Void>() {
                @Override
                public void onSuccess() {
    
                    //Do what you want to confirm to user...
                }
            });
        }
    }
    

    另外: 如果您再次向用户响应已处理的小部件,您将使其如下所示:

    @Service(value = Widget.class)
    public interface WidgetRequest extends RequestContext{
        ...
        Request<WidgetProxy> widgetProcessor(WidgetProxy widget);
    }
    
    public class Widget {
        ...
        public static void processWidget(Widget w){
           WidgetProcessor widgetProcessor = new WidgetProcessor();
           return widgetProcessor.processWidget(getWidgetFromRequest(request));
        }
    }
    
    public class WidgetProcessor {
        public Widget processWidget(Widget w) {
            // Inspect the Widget. If certain properties contain certain
            // values, place it on a queue. Else "process" the Widget
            // and persist it to a DB.
    
            if(w.containsSpecialValues())
                QueueManager.sendToQueue(w);
            else {
                // Process widget...
    
                WidgetDAO.save(w);
            }
            return w;
        }
    }
    
    public class WidgetPresenter {
        private final WidgetRequestFactory rf = GWT.create(WidgetRequestFactory.class);
        public WidgetPresenter() {
            rf.initialize(new EventBus());
            rf.widgetRequest().widgetProcessor().fire(new Receiver<WidgetProxy>() {
                @Override
                public void onSuccess(WidgetProxy response) {
    
                    WidgetView v = new WidgedView(response);
                                RootPanel.get().add(view);
                }
            });
        }
    }
    
    package com.foo.bar.client;
    public class WidgetView {
    
    
        public WidgetView(WidgetProxy widget) {
    
            //paint widget with widget
                // widget.getSomeProperty(); etc.
    
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为没有必要为此与Request Factory 进行头脑风暴。

      根据我的意见,使用Gwt RPC 可以非常简单。

      简单的RPC结构如下:

      GWT Code <===> InterfaceAsync <===> Interface (Synchronous)<===> Server Code 
      

      我正在尝试向您解释它自己的元素。

      同步接口(整个 RPC 的核心):

      import com.google.gwt.user.client.rpc.RemoteService;
      public interface WidgetRPCInterface extends RemoteService
      {
          public Widget widgetProcessRPC(Widget myWidget);
      }
      

      A同步接口(客户端的关键部分):

      import com.google.gwt.user.client.rpc.AsyncCallback;
      
      public interface WidgetRPCInterfaceAsync
      {
          public void widgetProcessRPCWidget myWidget, AsyncCallback callback);
      }
      

      这里使用实现“WidgetRPCInterface”的Service(等于servlet)

      public class WidgetRPCImpl extends RemoteServiceServlet implements RPCInterface
      {
          private static final long serialVersionUID = 1L;
      
          public Widget widgetProcessRPCWidget myWidget)
          {
             //Process your widget  here (CRUD operations)
             //You can change return type and return what ever you want to client . 
          }
      
      **you can override doget,doPost,doDelete....etc along with your methods 
      }
      

      在您的 web.xml 中映射上述类;

           <servlet>
          <servlet-name>widgetrpc</servlet-name>
          <servlet-class>com.server.WidgetRPCImpl</servlet-class>
        </servlet>
      
        <servlet-mapping>
          <servlet-name>widgetrpc</servlet-name>
          <url-pattern>/widgetrpc</url-pattern>
        </servlet-mapping>
      

      最后在您的 GWT 代码中。使用如下服务

      在代码中使用:

      //注册服务。

         private final WidgetRPCInterfaceAsync widgetService = 
              GWT.create(WidgetRPCInterface.class);
              ServiceDefTarget endpoint = (ServiceDefTarget) service;
              endpoint.setServiceEntryPoint('widgetrpc');
      

      通过回调请求服务器

      widgetService.widgetProcessRPC(widgetFromClient, callback);
       AsyncCallback callback = new AsyncCallback()
          {
              public void onFailure(Throwable caught)
              {
                 //Do on fail
              }
      
              public void onSuccess(Object result)
              {
                 //Process successfully done with result (result is which you
                 returned in impl class) .
              }
          };
      

      P.S .注意包结构:

      WidgetRPCInterfaceAsync ,WidgetRPCInterface 应该在 client* 包中

      Widget 类应该在 shared* 包中

      WidgetRPCImpl 应该在 server* 包中

      看看RPC 例子

      【讨论】:

        【解决方案4】:

        您对 RequestFactory 场景有点困惑。

        你需要从这里开始 - https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory

        浏览示例 RequestFactory 演示 @DynatableRF 代码 - http://code.google.com/p/google-web-toolkit/source/browse/#svn/trunk/samples/dynatablerf

        下载示例 RequestFactory 演示 @DynatableRF 代码 - http://google-web-toolkit.googlecode.com/files/gwt-2.5.0.zip

        编辑 - RequestFactory 示例与 MVP、活动和编辑器框架复杂。需要付出大量努力才能确定您的场景需要哪种 RF、编辑器、MVP 和 Activties 组合。

        【讨论】:

        • 感谢@SSR (+1) - 我查看了所有这些资源,但仍然没有“明白”。您能否详细说明您认为我对哪些情况感到困惑?我很欣赏这些链接,但我以前去过所有这些链接,你并没有真正回答我的问题。我试图弄清楚如何在服务器端将WidgetWidgetProcessor 链接起来。
        【解决方案5】:

        您的 Widget 类将位于服务器端。在客户端,您将使用一个接口来表示一个 Widget;此接口将成为实际 Widget 对象的代理。您可以使用 @ProxyFor 注释将代理接口与类相关联。例如,如果你在服务器上有 Widget 类,你可以在客户端有 WidgetProxy 接口:

        @ProxyFor(value = Widget.class)
        public interface WidgetProxy extends EntityProxy {
        }
        

        代理包含实体属性的getter和setter,这些getter和setter在服务器上的类中镜像。请求工厂还需要一种方法来定位与代理关联的类,为此我使用“定位器”类(尽管还有其他方法)。定位器也在@Proxy注解中指定:

        @ProxyFor(value = Widget.class, locator = WidgetLocator.class)
        

        WidgetLocator 类也在服务器端。对于您要插入或更新的每个小部件,您都需要创建一个 RequestContext。 RequestContext 标识将对实体进行操作的方法。这些方法的实际实现再次在服务器端......您可以引入一个包含这些方法的单独类,或者将它们添加到实体类(在您的情况下为 Widget)。我更喜欢将它们分成一个“DAO”类,将实体类(即 Widget)限制为一个简单的 bean。 (您的 DAO 类名为 WidgetProcessor)。客户端的 RequestContext 是一个扩展 RequestContext 接口的接口。你的 RequestContext 接口告诉请求工厂在哪里可以找到服务器上的 DAO,这就是你使用 @Service 注释的地方。

        查看 Thomas Broyer 的博客以获得很好的介绍:GWT 2.1.1 RequestFactory。我还发现 GWT in Action (Second Edition) 一书是一个有用的资源。我根据我的学习经验创建了一个示例,可能对您也有用:A GWT Request Factory Journey;再说一遍,这可能有用也可能没用!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-11
          • 2011-05-26
          • 2012-04-09
          • 1970-01-01
          相关资源
          最近更新 更多