PlayN 客户端与服务器的协作
Posted
技术标签:
【中文标题】PlayN 客户端与服务器的协作【英文标题】:Collaboration from PlayN client with server 【发布时间】:2012-01-29 14:10:58 【问题描述】:我在 PlayN 中编写了一个游戏,它必须通过 Seam 与 JavaEE-Server 通信。 首先我只需要运行 html5 的游戏。
当前的问题是 PlayN-client 和 JavaEE-Server 之间的通信
1) 首先,我尝试通过 PlayN.net() 接口使用 JSON 交换信息进行通信。由于 PlayN 在 8888 端口上运行,而服务器在 8080 上运行,我正确地遇到了同源策略的问题。
2) 现在我正在寻找一个可行的解决方案。你会推荐哪一个?您还有其他想法吗?
a) 我正在尝试使用 RPC,如 How to handle RPCs in client-server PlayN game? 中所述 ,使用 GWT-syncproxy。
b) 我尝试让 playN 在与服务器相同的端口上运行,即 8080 - 所以我不再遇到同源策略的问题。问题:HTML5 playN 应用程序可以在同一个端口上运行吗? 因此,当我使用 Eclipse 启动 JavaEE-Server 时,它也应该在端口 8080 上启动 PlayN Web 应用程序,对吗?
这可能吗?
c) 最 hacky 的解决方案(目前正在工作):服务器将 JSON-String 写入文件,playN 客户端读取该文件。
你有什么推荐的?我想实现解决方案 2,因为它是最干净的解决方案,但我不知道它有多难以及它是如何工作的。
感谢您的帮助!
【问题讨论】:
这里也有关于最佳方法的讨论:groups.google.com/group/playn/browse_thread/thread/… 【参考方案1】:我认为问题在于您正在“运行”PlayN,与您的 Seam 服务器分开。
如果我理解正确,您可以执行 Maven 任务以将游戏作为 HTML 运行,另一方面您运行 Jboss(或任何 Java EE 服务器),您应该做的是运行
mvn package
这将创建游戏战争,然后在您的 Java EE 服务器上发布该战争,然后您可以毫无问题地使用 PlayN.net 包,在单个服务器上运行
【讨论】:
谢谢,非常有帮助。我能够创建游戏之战并将其部署到服务器。不,我可以使用 PlayN.net() 毫无问题地进行交流;)【参考方案2】:这就是我们当前处理客户端/服务器通信的方式。我们使用的是无状态 JavaEE 架构,并以 REST 服务的形式提供一切。这允许我们通过添加更多服务器并简单地将它们添加到 Glassfish 配置中的集群条目来进行水平扩展。
但是由于缺少反射或有效的 JSON 库,它迫使我们手动在每个数据传输对象中实现一个 toJson() 方法(注意区分大小写)。我们将服务器项目作为模块添加到 PlayN 元项目,并将核心作为依赖项添加到服务器。因此,您可以将每个 DTO 放在核心项目上(这非常棒)。将它们放在服务器上会导致人们试图将类注释为实体,这将导致在 html 构建期间失败。我目前正在考虑将共享项目添加到构建中,例如在 GWT 项目中。
这就是我们向服务器发送数据的方式(对于这个没有任何抽象的例子,帮自己一个忙并实现一个):
private void loadMapFromServer()
SessionDto session = this.main.getSessionCtrl().getSessionMdl();
PlayN.net().post("http://localhost:8080/server/rest/map/mapMdl",
session.toJson(),
new Callback<String>()
@Override
public void onSuccess(String result)
mapMdl = new MapDto();
@Override
public void onFailure(Throwable cause)
PlayN.log().error("fail " + cause.getMessage());
);
请注意我们如何使用 session.toJson() 对 POST 参数进行混改。这是因为缺少 MIME 类型功能并且通过 GWT 传递 JSON 字符串将失败。 这就是它在服务器上的样子:
package com.fact.server;
//I also posted the imports, for clarity.
import com.fact.core.map.MapDto;
import com.fact.core.user.SessionDto;
import com.fact.server.game.map.MapCtrl;
import com.google.gson.Gson;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.log4j.Logger;
@Stateless
@Path("/map")
public class MapSrvs
@Inject
Logger logger;
@Inject
MapCtrl mapCtrl;
Gson gson = new Gson();
@POST
@Path("/mapMdl/")
@Produces( MediaType.APPLICATION_JSON )
public MapDto getMapMdl(String sessionDtoStr)
//logger.info("map was requested: " + sessionDtoStr);
// Use gson to deserialize the class. Jersey would do this, if PlayN
// would allow to set a correct MIME type (and @Consumes was set).
// We could simply write: getMapMdl(SessionDto sessionDto)
SessionDto sessionDto = gson.fromJson(sessionDtoStr, SessionDto.class);
if(sessionDto == null)
return null;
// [...] check for a valid session
MapDto mapMdl = new MapDto();
mapMdl.foo = "message from server";
return mapMdl;
如果 PlayN 允许您设置 MIME 类型,这会更好一些,这样您就不必使用 Gson 转换字符串。然而,这工作得很好。我们在服务器端使用 Jersey 来处理所有的 REST 内容。为了让它运行,我必须将以下内容放入 web.xml:
<servlet>
<!-- We need jersey for the REST stuff -->
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.fact.server</param-value>
</init-param>
<init-param>
<!-- This took me hours to find :(. It is needed to automatically
map POJOs to JSON code. -->
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Jersey 也已包含在 Java-EE-Api 中,因此可以开箱即用。我希望这有帮助。如果有人知道如何进行客户端 JSON 解析,请看这个问题:How do I convert a POJO to JSON in PlayN?
【讨论】:
我怀疑使用 GWT,如果您可以使用 GWT RPC 机制而不是 json rest api,事情会容易得多。而且您仍然可以保持服务器无状态(将令牌作为 GWT rpc 调用的一部分传递)。每个人都有自己的 - 有些人不喜欢像 GWT rpc 这样的不透明 api,我尊重这一点。以上是关于PlayN 客户端与服务器的协作的主要内容,如果未能解决你的问题,请参考以下文章