几天前,我开始使用Google App Engine和Google Cloud Endpoints开发移动应用后端 . This tutorial显示了如何自动生成 endpoints ,以及Android的客户端库 .
所以我们有我们的实体:
@Entity
public class Person implements IsSerializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String name;
//...
}
这个类的 endpoints :
@Api(name = "personendpoint")
public class PersonEndpoint {
@ApiMethod(name = "getPerson")
public Person getPerson(@Named("id") Long id) {
...
此外,使用生成的Android endpoints 库(使用REST API)我想 add 服务器上的用户界面,使用 Google Web Toolkit (GWT) 构建 . 但是我应该如何操作服务器端的日期?我可以看到不同的方法......
Option A1: Adding an RPC Service in GWT
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
所以我们必须更改我们的实体 .
Option A2: Service calls endpoint class
@Override
public Person insertPerson(Person person) {
return new PersonEndpoint().insertPerson(person);
}
应该工作,但仍然没有 com.google.appengine.api.datastore.Key
在实体中输入,因为 endpoints 正在使用 CollectionResponse<Person>
,我们必须在 listPerson()
的情况下将其转换为 Collection<Person>
.
Option B1: Using the Java Endpoint Client Library
我们可以从App Engine API后端拆分GWT客户端,并使用生成的Endpoint Client Libraries for Java . 所以我们在 RemoteServiceServlet
内调用REST / Endpoint-API . 但是,即使GWT客户端和 endpoints 在同一台服务器上,甚至在同一个项目中,这最终会不会出现在两个请求中?
GWT客户端 - (RPC) - > GWT服务器 - (HTTP请求) - > App Engine后端服务器
Option B2: Using the JavaScript Endpoint Client Library
可能是最好的方法,但最终将成为大规模的JSNI .
那么什么是最佳实践?我在一个项目中找不到任何使用Google Cloud Endpoints和GWT的示例项目:)
2 回答
好老的DTO困境 . 没有对错,只有对你有用的东西 .
重复自己可能是一件好事 . 现在,您通过 endpoints 公开数据模型,这意味着您的实体的任何更改都会影响您的移动应用用户 . 假设您在服务器端重命名属性 - >每个未更新应用程序的客户端都会关闭 .
安全性也是一个问题:如果您的用户实体具有“电子邮件”属性,则通过GWT RPC对其进行序列化将使您的用户的电子邮件几乎可用于任何JavaScript调试器 .
Is it really what you want?
不要误会我的意思,我不是那些“洋葱层”怪物应用程序的粉丝,其中80%的代码似乎是将对象转换为具有几乎相同属性的其他对象 .
我认为正确的解决方案介于两者之间:拥有一个“客户端”模型(DTO),由可通过GWT RPC和客户端 endpoints 公开的可序列化POJO(无数据存储,ORM,JAXB,无论注释)组成 . 您的GWT servlet实现和Endpoint服务器将调用相同的服务,该服务将您的客户端模型转换为实体并处理/持久化它们 .
通过这种方式,您可以重用代码,保持简单,在API中具有统一的接口,并允许您的内部管道工程在不改变客户端接口的情况下发展 .
也许我不明白 . 但似乎(对我来说)一切都很容易 .
GWT(客户端!)不在服务器上 . 它是在客户端浏览器中执行的编译Javascript .
Google插件生成Javascript客户端代码,使用合适的JSON调用Endpoint .
可以从GWT调用上面的代码 .
瞧?