我有以下Java servlet执行我所谓的“ Addition Service ”:
public class AdditionService extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
// The request will have 2 Integers inside its body that need to be
// added together and returned in the response.
Integer addend = extractAddendFromRequest(request);
Integer augend = extractAugendFromRequest(request);
Integer sum = addend + augend;
PrintWriter writer = response.getWriter();
writer.write(sum);
}
}
我试图让GWT的RequestFactory做同样的事情(在app服务器上添加两个数字并将总和作为响应返回)使用ValueProxy
和AdditionService
,并且遇到了几个问题。
这是AdditionRequest
(客户端层),它是一个包含两个要添加的整数的值对象:
// Please note the "tier" (client, shared, server) I have placed all of my Java classes in
// as you read through the code.
public class com.myapp.client.AdditionRequest {
private Integer addend;
private Integer augend;
public AdditionRequest() {
super();
this.addend = 0;
this.augend = 0;
}
// Getters & setters for addend/augend.
}
接下来我的代理(客户端层):
@ProxyFor(value=AdditionRequest.class)
public interface com.myapp.client.AdditionRequestProxy extends ValueProxy {
public Integer getAddend();
public Integer getAugend();
public void setAddend(Integer a);
public void setAugend(Integer a);
}
接下来我的服务API(在共享层中):
@Service(value=DefaultAdditionService.class)
public interface com.myapp.shared.AdditionService extends RequestContext {
Request<Integer> sum(AdditionRequest request);
}
接下来我的请求工厂(共享层):
public class com.myapp.shared.ServiceProvider implements RequestFactory {
public AdditionService getAdditionService() {
return new DefaultAdditionService();
}
// ... but since I'm implementing RequestFactory, there's about a dozen
// other methods GWT is forcing me to implement: find, getEventBus, fire, etc.
// Do I really need to implement all these?
}
最后魔术发生的地方(服务器层):
public class com.myapp.server.DefaultAdditionService implements AdditionService {
@Override
public Request<Integer> sum(AdditionRequest request) {
Integer sum = request.getAddend() + request.getAugend();
return sum;
}
// And because AdditionService extends RequestContext there's another bunch of
// methods GWT is forcing me to implement here: append, create, isChanged, etc.
// Do I really need to implement all these?
}
以下是我的问题:
AdditionService
(在共享中)引用DefaultAdditionService
,它位于服务器上,它不应该这样做。共享类型应该能够在客户端和服务器上同时存在,但不能依赖于... ServiceProvider
应该是实现RequestFactory
的类,还是应该是扩展的接口?如果是后者,我在哪里定义ServiceProvider
impl,以及如何将其链接回所有其他类?ServiceProvider
和DefaultAdditionService
中的所有这些方法怎么样?我是否需要实施所有20多种核心GWT方法?或者我是否错误地使用了API或者没有像我使用它那样简单?我认为我很接近但需要帮助越过终点线。如果有人可以接受我的代码并进行调整以显示使用RF / ValueProxies的正确方法,我认为它会将整个框架与我联系在一起......提前感谢!
答案 0 :(得分:6)
如果你想使用RF作为简单的RPC机制[*],你可以(而且你是对的:只有ValueProxy
s),但你需要更多:ServiceLocator
s(即GWT) 2.1.1)。
使用ServiceLocator
,您只需将服务实现(如servlet)放入实际服务实例中,而不是放入实体对象(因为您只使用ValueProxy
s,没有静态getXyz()
方法),如RF协议所要求的那样。请注意Locator
s的存在,用于从服务器端实体外部化所有这些方法:如果在任何地方使用ValueProxy
则不需要。
ServiceLocator
看起来像(取自official docs):
public class DefaultAdditionServiceLocator implements ServiceLocator {
@Override
public Object getInstance(Class<?> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
您还需要使用定位器参数注释您的DefaultAdditionService
,以便RF知道在将您的请求发送到您的服务时应该依赖什么。类似的东西:
@Service(value = DefaultAdditionService.class, locator = DefaultAdditionServiceLocator.class)
public interface com.myapp.shared.AdditionService extends RequestContext {
// Note here, you need to use the proxy type of your AdditionRequest.
Request<Integer> sum(AdditionRequestProxy request);
}
您的服务将是地球上最简单的事情(无需扩展/实施与RF相关的任何事情):
public class com.myapp.server.DefaultAdditionService {
// The server-side AdditionRequest type.
public Integer sum(AdditionRequest request) {
Integer sum = request.getAddend() + request.getAugend();
return sum;
}
}
如果您错误地sum()
或未实施RequestContext
中声明的方法,则会收到错误。
要实例化RequestContext
,您需要使用RequestFactory
的公共工厂方法扩展 com.myapp.shared.AdditionService
接口。类似的东西:
public interface AdditionServiceRequestFactory extends RequestFactory {
public com.myapp.shared.AdditionService createAdditionServiceRequestContext();
}
您的所有客户电话都将从此开始。如果没有,请参阅文档。
现在,RF的工作原理是完全分离您想要从客户端传递的对象(使用EntityProxy
和ValueProxy
)和服务器(真实对象,{{1值或简单的Entity
类)。您将在客户端/共享层中的任何位置使用代理类型(即,实现自动生成的接口),并且仅在服务器端使用相对域对象(使用DTO
引用的对象)。 RF将负责其余部分。因此,@ProxyFor
将位于您的服务器端,而AdditionRequest
将位于您的客户端(请参阅AdditionRequestProxy
中的注释)。另请注意,如果您只是使用原始/盒装类型作为RequestContext
参数或返回类型,则根本不需要创建RequestContext
,因为它们是默认transportable。
您需要的最后一点是在ValueProxy
上连接RequestFactoryServlet
。请在此处查看docs。请注意,如果您想要使用自定义web.xml
或ExceptionHandler
进行游戏,则可以对其进行扩展,但您并不需要这样做。
说到放置所有内容的地方:
ServiceLayerDecorator
,Locator
,服务实例,域对象和ServiceLocator
扩展程序将位于您的服务器端; RequestFactoryServlet
,RequestContext
扩展名和所有代理类型都在共享端; RequestFactory
扩展名并使用它来获取服务请求的工厂实例。总而言之......用RF创建一个简单的RPC机制,只需:
RequestFactory
; ServiceLocator
(使用服务和定位器值注释); RequestContext
扩展程序以返回RequestFactory
; RequestContext
中使用多个基本类型(比如简单的RequestContext
),只需为它们创建客户端代理接口,用DTO
注释,并记住在哪里使用每种类型; 很像那样。好吧,我写了太多,可能忘记了一些事情:)
供参考,见:
[*]:在这种方法中,您将逻辑从面向数据的转移到面向服务的应用程序。当涉及@ProxyFor
操作时,您放弃使用Entity
,ID
,version
,当然还有客户端和服务器之间的所有复杂差异逻辑。