• Play Framework + ReactiveMongo 环境搭建


    Play!是一个full-stack(全栈的)Java/Scala Web应用框架,包括一个简单的无状态MVC模型,具有Hibernate的对象持续,一个基于Groovy的模板引擎,以及建立一个现代Web应用所需的所有东西。

    Mongo DB 是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式备受当前IT从业人员的青睐。Mongo DB很好的实现了面向对象的思想(OO思想),在Mongo DB中 每一条记录都是一个Document对象。Mongo DB最大的优势在于所有的数据持久操作都无需开发人员手动编写SQL语句,直接调用方法就可以轻松的实现CRUD操作。

    ReactiveMongo 是一个 MongoDB 的 Scala 驱动,提供完全的非堵塞和异步 I/O 操作。

    以上就百度百科对Play! 以及MongoDB的简介。这篇博客就是简单的介绍Play+Mongo的环境搭建。

    工具与环境:

    • 编译器 -IDEA
    • Scala -version 2.11.6
    • Play -version 2.3.10
    • MongoDB -version 3.0.6
    • Sbt -version 0.13.8
    • Reactivemongo -version 0.10.5.0.akka23

    安装

    首先你得安装Play!以及MongoDB
    play!的安装不必多说,下载安装SBT,去Play官网下载Activator,添加环境变量,然后activator new 一个工程就可以了。

    创建好mosquito-mongo工程目录如下:

    MongoDB的安装也很简单,去官网下载安装,然后添加环境变量就可以。不过需要注意,要自己指定数据存放位置。如,我将数据存放在D:MongoDBdata中,只需要在d:MongoDBdata文件夹就行:

    然后就可以这样启动:

    到这里,playmongodb就都已安装好了,接下来我们可以实现一个小的demo。

    配置

    添加play.plugins插件。在项目根目录下的conf/文件夹下,创建play.plugins插件并加入

    1100:play.modules.reactivemongo.ReactiveMongoPlugin
    

    添加reactivemongo依赖。打开项目根目录下build.sbt,添加:

    "org.reactivemongo" %% "play2-reactivemongo" % "0.10.5.0.akka23"
    

    配置连接。打开项目根目录下的conf/文件夹下application.conf,加入:

    # ReactiveMongo
    
    mongodb.uri = "mongodb://localhost:27017/mosquito"
    
    mongo-async-driver {
      akka {
    loglevel = DEBUG
      }
    }
    

    建立全局的Global来获取connection。在app目录下创建Global.scala文件,并添加:

    package global
    
    object Global extends GlobalSettings {
    
    	def db = ReactiveMongoPlugin.db
    	def collection = db.collection[JSONCollection]("user")
    
    	override def onStart(app: Application) {
    		Logger.info("Application has started")
    	}
    
    	override def onStop(app: Application) {
    		Logger.info("Application shutdown...")
    	}
    }
    

    然后还需要在conf/文件夹下application.conf,加入:

    application.global=global.Global
    

    到此,所有配置都已结束,接下来实现业务逻辑了。

    实现

    建立模型。根目录下建立models文件夹(如果没有的话),并建立User.scala,并加入:

    package models
    
    import play.api.libs.json.Json
    
    case class User(
    	               var id:Option[Long],
    	               var name:Option[String],
    	               var password:Option[String],
    	               var address :Option[String] = None)
    
    
    trait JSONFormats {
    
    	implicit val UserFormats = Json.format[User]
    
    }
    

    实现。在controllers/下的Application.scala中加入以下代码:

    package controllers
    
    import akka.util.Timeout
    import global.Global
    import models.{JSONFormats, User}
    import play.api.libs.concurrent.Execution.Implicits.defaultContext
    import play.api.libs.json._
    import play.api.mvc._
    
    import scala.concurrent.Await
    import scala.concurrent.duration._
    
    // Reactive Mongo plugin, including the JSON-specialized collection
    import play.modules.reactivemongo.MongoController
    
    object Application extends Controller with MongoController with JSONFormats {
    
    	implicit val timeout = Timeout(10 seconds)
    
    	def index = Action {
    		Ok(views.html.index("Your new application is ready."))
    	}
    
    	def add = Action { request =>
    		request.body.asJson.get.validate[User] match {
    			case s:JsSuccess[User] =>{
    				val user = s.get
    				Global.collection.insert(user)
    				Ok(Json.obj("code" -> 200, "message" -> Json.toJson(user)))
    			}
    			case e:JsError => {
    				InternalServerError(Json.obj("code" -> 500, "message" -> e.toString))
    			}
    		}
    	}
    
    	def query = Action.async {
    
    		val userList = Global.collection.find(Json.obj())
    			.cursor[User].collect[List](upTo = 100, stopOnError = true)
    
    		userList.map(
    			list => Ok(Json.obj("code" -> 200, "message" -> Json.toJson(list))))recover {
    			case e : Exception => InternalServerError(Json.obj("code" -> 500, "message" -> JsNull))
    		}
    
    	}
    
    	def retrieve(id:Int) = Action.async {
    
    		val userOpt = Global.collection.find(Json.obj("id" -> id)).cursor[User].headOption
    
    		userOpt.map(
    			user => Ok(Json.obj("code" -> 200, "message" -> Json.toJson(user)))) recover {
    			case e : Exception => InternalServerError(Json.obj("code" -> 500, "message" -> JsNull))
    		}
    
    	}
    
    	def test = Action.async { request =>
    		val reqJson = request.body.asJson.get
    
    		val name = (reqJson "name").asOpt[String]
    		val password = (reqJson "name").asOpt[String]
    		val address = (reqJson "address").asOpt[String]
    		val idOpt = getId
    
    		val user = User(
    			idOpt,
    			name,
    			password,
    			address
    		)
    
    		Global.collection.insert(user).map(
    			u => Ok(Json.obj("code" -> 200, "message" -> Json.toJson(user))))recover {
    			case e : Exception => InternalServerError(Json.obj("code" -> 500, "message" -> "Oops"))
    		}
    
    	}
    
    	def getId:Option[Long] = {
    		var ret = None:Option[Long]
    		val userList = Global.collection.find(Json.obj())
    			.cursor[User].collect[List](upTo = 100, stopOnError = true)
    
    		val lastUserOpt = Await.result(userList, timeout.duration).lastOption
    
    		if(lastUserOpt.isDefined){
    			val id = lastUserOpt.get.id.get + 1
    			ret= Option(id)
    		}
    
    		ret
    	}
    
    }
    

    说明。

    • add 新增
    • query 查询所有
    • retrieve 查询单个(根据id查询)
    • test 测试uid自增插入
    • getId 获取最大uid传递给test(很low的方式,通过查询出最大的id再+1赋值)

    配置路由。在conf/文件夹下的routes中加入对应的路由:

    GET        /user/:id            controllers.Application.retrieve(id:Int)
    PUT        /user                controllers.Application.add
    GET        /query               controllers.Application.query
    PUT        /test                controllers.Application.test
    

    总目录结构如下:

    测试

    最后是跑一下。运行起来后直接自动建库、建表。

    运行成功。

    测试一下查询。

    测试一下新增(id自增)。

    最后再查询全部。

    Github源码

    本文作者心尖偏左。因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处。有问题欢迎与我讨论,共同进步。
  • 相关阅读:
    软件工程(2018)结对编程第二次作业
    软件工程(2019)结对编程第一次作业
    软件工程(2019)第三次个人作业
    软件工程(2019)第二次作业
    软件工程(2019)第一次作业
    实用的小工具
    php中需要注意的函数(持续更新)
    sql 防注入(更新问题)
    laravel 中将一对多关联查询的结果去重处理
    调试location指令时,直接让location输出文本
  • 原文地址:https://www.cnblogs.com/xjpz/p/4825855.html
Copyright © 2020-2023  润新知