Play2 + ReactiveMongo 实现一个活动报名应用
2015-08-12 17:49
706 查看
Play 2:
ReactiveMongo:
代码在: http://git.oschina.net/socialcredits/social-credits-activity-service
公司要做一些活动,需要一个线上的活动报名应用。想着前几天刚好看了下
这个活动应用的功能非常简单:用户在线填写表单,提交表单,后台存储数据并向指定的专员发送邮箱通知。
MyDriver.scala
BSONImplicits
ActivityRepo
EmailService。
程序中使用了一个
https://playframework.com
ReactiveMongo:
http://reactivemongo.org
代码在: http://git.oschina.net/socialcredits/social-credits-activity-service
公司要做一些活动,需要一个线上的活动报名应用。想着前几天刚好看了下
ReactiveMongo,觉得这个小应用正好练练手。
这个活动应用的功能非常简单:用户在线填写表单,提交表单,后台存储数据并向指定的专员发送邮箱通知。
Play 项目
整个项目目录结构如下:├── app │ ├── controllers │ │ └── inapi │ ├── utils │ └── views │ └── activity ├── conf ├── data │ └── src │ └── main ├── platform │ └── src │ └── main ├── project ├── static │ └── src │ └── site └── util └── src ├── main
app、
conf都是
Play的标准目录,分别放置代码文件和项目配置文件。
app.views包下的是Play的模板页面文件。
static是用于放置前端源文件的,包括:
js、
sass等,使用
gulp编译,并输入到
public目录。
platform目录放置一些业务代码,比如:Service。
data目录是数据相关类的存放地,包括
model、
domain和数据库访问代码,一此数据类相关的隐式转换代码也放置在此。
util就是工具库了,包括常量定义、配置文件读取、枚举等。
ReactiveMongo
connection mongo collection
使用ReactiveMongo连接数据库需要先创建一个
MongoDrvier,并调用
driver.connection方法创建连接,进而通过
conn.db方法获取一个数据库访问。
MyDriver.scala
class MyDriver private() { val driver = new MongoDriver() def connection = driver.connection(List(Settings.mongo.host)) private def db(implicit ex: ExecutionContext) = connection.db(Settings.mongo.dbName) def collActivity(implicit ex: ExecutionContext) = db.collection[BSONCollection]("activity") def collActivityRegistration(implicit ex: ExecutionContext) = db.collection[BSONCollection]("activityRegistration") }
case class 与 BSON的转换。
使用Macros.handler是最简单的实现
case class与
BSON转换的方法,它用到了 scala macro。代码如:
implicit val __activityHandler = Macros.handler[Activity]
BSONImplicits
implicit object LocalDateTimeHandler extends BSONHandler[BSONDateTime, LocalDateTime] { override def read(bson: BSONDateTime): LocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(bson.value), ZoneOffset.ofHours(8)) override def write(t: LocalDateTime): BSONDateTime = BSONDateTime(t.toInstant(ZoneOffset.ofHours(8)).toEpochMilli) } implicit val __activityHandler = Macros.handler[Activity]
数据库访问
查找一个Activity使用find()方法获取一个访问数据库游标,再在游标上调用
.one[Activity]方法即可获取一个
Activity对象,以
Option[Activity]
ActivityRepo
def findOneById(id: BSONObjectID): Future[Option[Activity]] = { activityColl.find(BSONDocument("_id" -> id)).one[Activity] }
发送邮件
邮箱发送使用了commons-email,发送邮件的代码非常简单。
EmailService。
@Singleton class EmailService { private val emailSenderActor = Akka.system.actorOf(Props[EmailServiceActor], "email-sender") def sendEmail(id: String, subject: String, content: String): Unit = { emailSenderActor ! SendEmail(id, subject, content) } } class EmailServiceActor extends Actor with StrictLogging { override def receive: Receive = { case SendEmail(id, subject, content) => val email = new SimpleEmail() email.setHostName(Settings.email.hostName) email.setSmtpPort(Settings.email.portSsl) email.setSSLOnConnect(true) email.setAuthenticator(new DefaultAuthenticator(Settings.email.username, Settings.email.password)) email.setFrom(Settings.email.from) email.setSubject(subject) email.setMsg(content) email.addTo(Settings.email.to: _*) logger.info( s"""id: $id |from: ${Settings.email.from} |to: ${Settings.email.to} |$subject |$content""".stripMargin) val result = email.send() logger.info( s"""id: $id |[result] $result""".stripMargin) } }
程序中使用了一个
Actor来对邮件发送动作做队列化处理,感觉有点小题大作。不过
Actor默认邮箱是
FIFO的,这个特性很适合发送邮件的队列操作。
相关文章推荐
- ReactiveCocoa学习(二)
- 谈谈 React.js 的核心入门知识
- React 初探
- iOS react native 学习资料
- IOS RAC(ReactiveCocoa) -Functional Reactive Programming 详解[转载ReactiveCocoa与Functional Reactive Prog]
- React Native 简介:用 JavaScript 搭建 iOS 应用 (1)
- React Native 简介:用 JavaScript 搭建 iOS 应用 (1)
- Functional Reactive Programming& ReactiveCocoa
- ReactiveCocoa学习(一)
- React 入门实例教程
- React 创建自定义控件
- 轻松入门React和Webpack
- react native 开发IOS
- react学习资源
- Facebook React完全解析
- 探索React生态圈
- 探索React生态圈
- 探索React生态圈
- React中render函数中变量map中事件无法关联的解决办法
- 初识React以及15个由简到难的React demo