如果可能,我想将GWT的RequestFactory
用于所有客户端 - 服务器通信。我的理解是,您必须在/gwtServlet
中将RequestFactoryServlet
映射到web.xml
,然后使用@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
- 土地上运作?提前谢谢。
答案 0 :(得分:4)
你对RequestFactory场景感到有点困惑。
您需要从这里开始 - https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory
浏览示例RequestFactory demo @ DynatableRF代码 - http://code.google.com/p/google-web-toolkit/source/browse/#svn/trunk/samples/dynatablerf
下载示例RequestFactory demo @ DynatableRF代码 - http://google-web-toolkit.googlecode.com/files/gwt-2.5.0.zip
修改 RequestFactory示例使用MVP,活动和编辑器框架进行复杂化。需要付出大量的努力才能得出RF,编辑,MVP和放大器的哪种组合。您的方案需要的活动。
答案 1 :(得分:4)
它可以与RequestFactories一起使用,但也可以使用GWT-RPC。我更喜欢RequestFactories。
您将拥有以下类和接口:
在服务器上:
在客户端:
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));
}
}
WidgetProcessor
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);
}
}
}
WidgetProxy
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
}
WidgetRequest
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...
}
});
}
}
<强> Addtionally: 如果您再次向用户回复已处理的小部件,您可以这样做:
@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.
}
}
答案 2 :(得分: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);
}
ASynchronous接口(客户端的关键部分):
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface WidgetRPCInterfaceAsync
{
public void widgetProcessRPCWidget myWidget, AsyncCallback callback);
}
您可以使用 Service
(等于servlet)来实现“WidgetRPCInterface”
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 * package中
小部件类应该在共享*包
中WidgetRPCImpl 应该在server * package
中并查看RPC示例
答案 3 :(得分:1)
您的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类也在服务器端。对于要插入或更新的每个Widget,您需要创建一个RequestContext。 RequestContext标识将对该实体进行操作的方法。这些方法的实际实现再次在服务器端...您可以引入一个包含方法的单独类,或者将它们添加到实体类(在您的情况下为Widget)。我更喜欢将它们分成“DAO”类,将实体类(即Widget)限制为一个简单的bean。 (您的DAO类名为WidgetProcessor)。客户端上的RequestContext是扩展RequestContext接口的接口。您的RequestContext接口告诉请求工厂在服务器上找到DAO的位置,以及您使用@Service注释的位置。
请看看Thomas Broyer的博客,以获得一个很好的介绍:GWT 2.1.1 RequestFactory。我还发现GWT in Action(第二版)这本书是一本有用的资源。我根据自己的学习经验创建了一个示例,这对您也很有用:A GWT Request Factory Journey;再次,这可能有用也可能没用!
答案 4 :(得分:1)
我刚刚为您的目的开发了一个简单的骨架项目。 检查我的回答widget-processor on Github。
该项目基于Maven构建器和Java EE平台(GlassFish)。
项目模块:
ear
- 普通耳模块将其他模块整合到一个易于部署的EAR包中; persistence
- 此模块只有一个文件persistence.xml
,并将所有外部实体链接到一个数据源; ejb
- 此模块包含实体Widget
和无状态EJB WidgetProcessor
; web
- 带有RequestFactory的常规GWT模块。Maven构建过程已调整为正确构建所有内容。该项目可以毫无问题地导入IntelliJ Idea。它可以使用标准的Idea工具在Glassfish中进行调试。
此外,我已将GWT RF和持久性样板代码移至external bilionix-core
artifacts on Github。