基本上我开始设计我的项目是这样的:
现在我想知道,如果它真的是最好的设计。 事实上玩Play!我可以很容易地同时托管web gui和服务。 在可能的简单情况下,这将更容易测试和部署。 在需要高性能的复杂情况下,我仍然可以纯粹为gui运行一个实例,而下一个实例只需要作为服务运行(即使每个实例仍然可以提供全部功能)。 另一方面,我不确定它是否会对性能造成太大影响(服务将处理大量数据,而不仅仅是来自网络gui)。还有,它不是混合我应该分开的东西吗?
如果我决定将它们分开,我是否应该只允许通过RESTful服务连接到数据库?如何解决服务和web gui试图使用不同版本的数据库的问题?在这种情况下我应该使用版本化的REST协议吗?
-----------------编辑------------------
我目前的系统结构如下:
但我想知道通过在Play中放置RESTful服务来简化它是否有意义!直接gui web服务器。
-----------------编辑2 ------------------
这是说明我的主要问题的图表。
换句话说清楚一点:连接我的服务和网络gui并分享模型会不好?为什么?
因为也没有什么优势:
那说,这是图:
答案 0 :(得分:1)
为什么需要RESTful服务来连接数据库?最玩!应用程序直接从控制器访问数据库。 Play! philosophy认为通过服务层访问您的模型是反模式。如果您打算与其他(非Play!)应用程序或您控制之外的外部系统共享该数据,则服务层可能很方便,但除此之外,最好保持简单。但您也可以简单地从Play中公开RESTful接口!应用程序本身用于其他系统。
播放!是为了保持简单,避免过去困扰Java开发的过度设计的废话。
答案 1 :(得分:1)
好吧,经过几个小时的思考,我想我找到了能够满足我需求的解决方案。我想实现的目标是:
我之前忘记说的是,我的服务将使用一些嵌入式缓存来聚合和处理数据,然后使用更大的块来提交数据库。它也出现在图表中。
我的班级结构如下:
|
|- models
|- IElementsRepository.scala
|- ElementsRepositoryJSON.scala
|- ElementsRepositoryDB.scala
|- Element.scala
|- Service
|- Element.scala
|- Web
|- Element.scala
|- controlers
|- Element.scala
|- views
|- Element
|- index.scala.html
所以它就像普通的MVC网络应用程序,除了事实上有服务的单独模型类和继承主要的web gui。
在Element.scala中,我将使用DI注入IElementsRepository对象(可能使用Guice)
IElementsRepository有两个具体的实现:
这意味着根据有效的DI配置,服务和web gui都可以从其他服务或本地/外部存储中获取数据。
因此,对于早期开发,我可以将所有内容保持在一个播实例并使用直接缓存和数据库访问(通过ElementsRepositoryDB),然后重新配置web gui以使用JSON(通过ElementsRepositoryJSON)。这也允许我根据需要运行gui和service作为单独的实例。我甚至可以将服务配置为使用其他服务作为数据提供者(但是现在我没有这样的需求)。
或多或少看起来像这样:
答案 2 :(得分:0)
嗯,我认为这里没有客观正确或错误的答案,但我会提出我的意见:我认为你提供的图表是完全正确的。您的RESTful服务是包括您的Web前端在内的所有客户的唯一访问点,我会说它应该是这样的。
没有谈论Play!,Spray或任何其他Web框架(或者,就此而言,任何数据库服务器,HTML模板库,JSON解析器或其他任何东西),显而易见的经验法则是保持严格的关注点分离通过防止实现细节泄漏到您的界面。现在,您提出了两个问题:
性能:将对象编组和解组为JSON表示并通过HTTP提供服务的过程非常快(例如,与JAXB相比)并得到Scala库和Web框架的良好支持。当您不可避免地发现特定组件中的性能瓶颈时,您可以孤立地处理这些瓶颈。
测试和部署: Play的事实!框架shuns servlets确实使事情变得复杂。通常我建议进行测试/暂存,你只需要为你的前端东西和你的web服务的WAR获取WAR,并将它们并排放在同一个servlet容器中。例如,我过去使用Maven Cargo plugin完成了这项工作。对于Play!来说,这并不是那么简单,但是我发现(并且从未使用过)的一个模块是play-cargo模块......点,做你需要做的任何事情来保持层分离,然后粘合根据需要进行测试。
希望这很有用......