我有以下Java servlet执行我称之为" 添加服务 ":
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做同样的事情(在应用服务器上添加两个数字并将总和作为响应返回)使用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 { Requestsum(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 Requestsum(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的正确方法,我认为它会将整个框架与我联系在一起...提前感谢!
如果你想使用RF作为一个简单的RPC机制[*]你可以(而且你是对的:只有ValueProxy
s),但你需要更多ServiceLocator
的东西:s(即GWT 2.1.1).
有了ServiceLocator
你可以简单地把你的服务实现(比如你的servlet)成为一个真正的服务实例,而不是变成一个实体对象(如用户仅ValueProxy
S,没有静态getXyz()
方法)所要求的RF协议.注意Locator
s 的存在,用于从服务器端实体外部化所有这些方法:如果你ValueProxy
在任何地方使用,则不需要.
一个ServiceLocator
看起来像(取自官方文档):
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
)和服务器(真实对象,Entity
值或简单DTO
类)传递的对象来工作.您将在客户端/共享层中的任何位置使用代理类型(即,实现自动生成的接口),并且@ProxyFor
仅在服务器端使用相对域对象(引用的对象).RF将负责其余部分.因此,您AdditionRequest
将在您的服务器端,而AdditionRequestProxy
将在您的客户端(请参阅中的说明RequestContext
).另请注意,如果您只使用原始/盒装类型作为RequestContext
参数或返回类型,则根本不需要创建ValueProxy
s,因为它们是默认可传输的.
你需要的最后一点是连接RequestFactoryServlet
你的web.xml
.请参阅此处的文档.请注意,如果您想要使用自定义ExceptionHandler
s或ServiceLayerDecorator
s,您可以扩展它,但您不需要.
谈谈在哪里放一切:
Locator
s,ServiceLocator
s,服务实例,域对象和RequestFactoryServlet
扩展,将在您的服务器端;
的RequestContext
,RequestFactory
扩展和所有代理的类型将是共用端;
客户端将初始化RequestFactory
扩展并使用它来获取服务请求的工厂实例.
总而言之......用RF创建一个简单的RPC机制,只需:
创造您的服务ServiceLocator
;
RequestContext
为您的请求创建一个(使用服务和定位器值注释);
创建一个RequestFactory
扩展来返回你的RequestContext
;
如果你想在你的RequestContext
(如简单的DTO
s)中使用多个原始类型,只需为它们创建客户端代理接口,注释@ProxyFor
,并记住每种类型的使用位置;
一切都好.
很像那样.好吧,我写的太多了,可能忘记了一些东西:)
供参考,请参阅:
官方RF文件 ;
Thomas Broyer的文章[1],[2] ;
从RF作者的角度来看RF与GWT-RPC.
[*]:在这种方法中,您将逻辑从面向数据的应用程序转移到面向服务的应用程序.当涉及到操作时,你放弃使用Entity
s,ID
s,version
s,当然还有客户端和服务器之间的所有复杂差异逻辑CRUD
.