可扩展且快速的REST API,用于公开ORM方法

时间:2013-04-10 13:29:05

标签: scala rest orm functional-programming

我需要开发REST API以向数据库和一些业务逻辑公开CRUD操作。我更喜欢这个模块是独立的,快速的,可扩展的和灵活的(没有不必要的模块提供我不需要的功能,以降低维护成本)。

发展偏好:
- 进行类型检查的框架/语言
- 具有良好的ORM映射
- 具有良好的TDD / BDD支持
- 功能语言

我想知道是否有像squeryl和blue eyes或squeryl和spary这样的scala模块的组合可以解决问题,但它不一定是scala。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

你所描述的当然是可能的。我对Spray或BlueEyes没有任何经验,但我确实使用过Squeryl + Play,它可以做你想做的事。它可能提供了您不需要的模块,但如果您不使用它们,这些模块不应该导致维护成本。

一个重要的问题是,大多数(如果不是全部)Scala框架是围绕异步编程模型设计的(实际上是大多数其他高可伸缩性框架,如Node.js)。另一方面,ORM通常围绕同步编程模型构建。但是,您可以通过一些胶水代码,一些防御性编码和一些仔细调整(这就是我们所做的)来解决这种不匹配问题。

更激进的替代方案是将ORM交换为MongoDB或CouchDB等文档数据库(文档数据库通常具有合理的异步驱动程序)。

答案 1 :(得分:1)

对于网络前端Play Framework最近已成为默认选择。

对于ORM,我建议SORM Framework

以下是它可以做的完整示例。无需额外代码。

// Declare a model:
case class Artist( name : String, genres : Set[Genre] )
case class Genre( name : String ) 

// Initialize SORM, automatically generating schema:
import sorm._
object Db extends Instance(
  entities = Set( Entity[Artist](), Entity[Genre]() ),
  url = "jdbc:h2:mem:test"
)

// Store values in the db:
val metal = Db.save( Genre("Metal") )
val rock = Db.save( Genre("Rock") )
Db.save( Artist("Metallica", Set(metal, rock) ) )
Db.save( Artist("Dire Straits", Set(rock) ) )

// Retrieve values from the db:
// Option[Artist with Persisted]:
val metallica = Db.query[Artist].whereEqual("name", "Metallica").fetchOne() 
// Stream[Artist with Persisted]:
val rockArtists = Db.query[Artist].whereEqual("genres.item.name", "Rock").fetch() 

答案 2 :(得分:0)

我认为Lift web framework很可能是由于以下原因:

道具

  1. 高度模块化。

    虽然Lift是一个完整的Web应用程序框架,但它是高度模块化的。它有自己的ORM库,但是如果你不喜欢它,就不要将它包含在你的库依赖项中,而是使用像Squeryl这样的其他库。类似地,它具有类型安全的JSON库,但它也是可选的。

  2. 这只是Java Web容器的普通过滤器。

    这意味着您可以将其与在Java Web容器上运行的其他框架一起使用,并指定只有某个URL将转到Lift,而其他URL将只对您的旧框架或仅仅是纯JSP。

  3. 它是类型安全且功能齐全的。

    Lift中的大多数操作都是强类型类型安全的,例如,您可以在SessionVar中存储会话变量而不会丢失它的类型信息。

    Lift还利用了许多函数式编程技术,如部分函数,​​模式匹配和基于转换的pure xHTML/HTML5 template system,而不是在模板中嵌入scala代码来生成动态内容。

  4. 对有状态和无状态的超级简单REST支持。

    创建一个REST API in Lift is super easy,它有一个相当不错的简单DSL。并且它支持有状态和无状态,有时以有状态的方式做事更容易,而Lift会给你这个。有状态和无状态都使用相同的REST DSL,你只需要告诉Lift你想要什么样的风格,它将为你处理所有事情(初始化会话......等)。

    例如,以下代码显示了如何创建支持XML和JSON以获取和发布博客文章的REST API。

    object BlogAPI extends RestHelper {
    
      def getPostXML(postID: String) = <article>{postID}</article>
      def getPostJSON(postID: String): JValue = ("postID" -> 1)
      def addPostJSON(jsonBody: JValue) = {
        // Extract from jsonBody and add post to DB 
        new OkResponse()
      }
    
      serve {
        // Read blog post API in XML and JSON
        case "api" :: "blog" :: "post" :: postID :: Nil XmlGet request => getPostXML(postID)
        case "api" :: "blog" :: "post" :: postID :: Nil JsonGet request => getPostJSON(postID)
    
        // Post blog post API in JSON
        case "api" :: "blog" :: "post" :: Nil JsonPost ((jsonBody, req)) => addPostJSON(jsonBody)
      }
    }
    

    这几乎是您在Lift中制作REST API所需的全部内容。它会将网址GET /api/blog/1.xml与XML响应匹配,GET /api/blog/1.json将返回JSON响应。

  5. 缺点

    Lift的最大缺点是文档比其他框架要少,而且你在网上找到的一些信息已经过时了。

    因为Lift使用了许多高级Scala功能和一些函数式编程风格,所以如果你不熟悉Scala和函数式编程功能,有时候学习它并不容易。