GWT 和 Google Cloud Endpoints
Posted
技术标签:
【中文标题】GWT 和 Google Cloud Endpoints【英文标题】:GWT and Google Cloud Endpoints 【发布时间】:2013-05-23 02:32:33 【问题描述】:几天前,我开始使用 Google App Engine 和 Google Cloud Endpoints 开发移动应用程序后端。 This tutorial 展示了端点是如何自动生成的,以及适用于 android 的客户端库。
所以我们有我们的实体:
@Entity
public class Person implements IsSerializable
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String name;
//...
还有这个类的端点:
@Api(name = "personendpoint")
public class PersonEndpoint
@ApiMethod(name = "getPerson")
public Person getPerson(@Named("id") Long id)
...
此外,使用生成的 Android 端点库(使用 REST API)我想在服务器上添加一个用户界面,使用 Google Web Toolkit (GWT) 构建强>。但是我应该如何操作服务器端的日期呢?我可以看到不同的方法...
选项 A1:在 GWT 中添加 RPC 服务
public interface PersonServiceAsync
void insertPerson(Person person, AsyncCallback<Person> callback);
@RemoteServiceRelativePath("api")
public interface PersonService extends RemoteService
public Person insertPerson(Person person);
public class PersonServiceImpl extends RemoteServiceServlet implements PersonService
public Person insertPerson(Person person)
EntityManager mgr = getEntityManager();
try
if (containsPerson(person))
throw new EntityExistsException("Object already exists");
mgr.persist(person);
finally
mgr.close();
return person;
//...
但现在我的PersonServiceImpl
和PersonEndpoint
做的大致相同。所以我们没有关注DRY :) 此外,不允许那个人有com.google.appengine.api.datastore.Key
,所以我们必须改变我们的实体。
选项 A2:服务调用端点类
@Override
public Person insertPerson(Person person)
return new PersonEndpoint().insertPerson(person);
应该可以工作,但仍然没有com.google.appengine.api.datastore.Key
在实体中键入,并且由于端点使用CollectionResponse<Person>
,我们必须将其转换为Collection<Person>
,以防listPerson()
。
选项 B1:使用 Java 端点客户端库
我们可以将 GWT 客户端从我们的 App Engine API 后端中分离出来,并使用生成的 Java 端点客户端库。所以我们从RemoteServiceServlet
中调用REST/Endpoint-API。但是,即使 GWT 客户端和 Endpoints 在同一台服务器上或什至在同一项目中,这不会以两个请求结束吗?
GWT 客户端 --(RPC)--> GWT 服务器 --(HTTP 请求)--> App Engine 后端服务器
选项 B2:使用 JavaScript 端点客户端库
可能是最好的方法,但最终会导致大量 JSNI。
那么最佳做法是什么?我在一个项目中找不到任何使用 Google Cloud Endpoints 和 GWT 的示例项目 :)
【问题讨论】:
你见过code.google.com/p/gwt-google-apis 是的,但它们处于早期的 Alpha 版本并用于 Google API。我说的是您自己的 API/端点,由 GAE 生成。 该库适用于任何基于发现的 API,而您的 API/端点恰好是(即基于发现的)。 我也有同样的困境。我们希望使用 Endpoint API,但开发 GWT 前端。我有一种感觉,它可能必须是一个或另一个...... 也在寻找解决方案。暂时使用 JSNI。 【参考方案1】:旧的 DTO 困境。没有对与错,只有对你来说足够好的。
重复自己可能是一件好事。现在您正在通过端点公开您的数据模型,这意味着您的实体的任何更改都会影响您的移动应用程序用户。假设您在服务器端重命名了一个属性 -> 每个未更新应用程序的客户端都会关闭。
安全性也是一个问题:如果您的 User 实体具有“email”属性,通过 GWT RPC 对其进行序列化将使您的用户的电子邮件几乎可用于任何 javascript 调试器。
真的是你想要的吗?
不要误会我的意思,我不喜欢那些“洋葱层”怪物应用程序,其中 80% 的代码似乎用于将对象转换为具有几乎相同属性的其他对象。
我认为正确的解决方案介于两者之间:拥有一个“客户端”模型 (DTO),由您通过 GWT RPC 和客户端端点公开的可序列化 POJO(没有数据存储、ORM、JAXB 或任何注释)组成。 您的 GWT servlet 实现和端点服务器将调用相同的服务,将您的客户端模型转换为实体并处理/保留它们。
通过这种方式,您可以重复使用您的代码,仍然保持简单,在您的 API 中拥有统一的接口,并允许您的内部管道在不改变客户端接口的情况下发展。
【讨论】:
尽管我很长时间没有使用 GWT,但我经常遇到类似的困境(商业模式与 DTO)。早在 2014 年,这个答案并没有真正让我满意。但经过多年的高级 Java 开发经验和数千行代码之后,我必须说您当时的评论完全符合您的观点,我完全同意您的看法。【参考方案2】:也许我不明白什么。 但一切似乎(对我来说)都很容易。
GWT(客户端!)不在服务器上。它是在客户端浏览器中执行的编译 Javascript。
Google 插件生成 Javascript 客户端代码,使用合适的 JSON 调用 Endpoint。
可以从 GWT 调用以上代码。
瞧?
【讨论】:
是的,所以这将是选项 B2。但正如我提到的那样,它会起作用,但最终会出现很多 JSNI。因为客户端的大部分是用 Java (GWT) 编写/定义的,但调用端点的逻辑是生成的 Javascript 代码。工作,但不是很好。以上是关于GWT 和 Google Cloud Endpoints的主要内容,如果未能解决你的问题,请参考以下文章
在 Google Web Toolkit (GWT) 中实现页眉、页脚和菜单栏
GWT Servlet 错误 com.google.gwt.user.client.rpc .StatusCodeException: Tomcat 服务器上的 404
GWT - 偶尔出现 com.google.gwt.user.client.rpc.SerializationException
com.google.gwt.view.client.Range 的 GWT SerializationException
尽早避免 GWT 的 com.google.gwt.user.client.rpc.SerializationException 的最佳实践