-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
160 changed files
with
3,413 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
logs | ||
target | ||
/.idea | ||
/.idea_modules | ||
/.classpath | ||
/.project | ||
/.settings | ||
/RUNNING_PID |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,7 @@ | ||
MIT License | ||
License | ||
------- | ||
Written in 2016 by Lightbend <info@lightbend.com> | ||
|
||
Copyright (c) 2017 mufeng | ||
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
[<img src="https://img.shields.io/travis/playframework/play-scala-starter-example.svg"/>](https://travis-ci.org/playframework/play-scala-starter-example) | ||
|
||
# Play Scala Starter | ||
|
||
This is a starter application that shows how Play works. Please see the documentation at https://www.playframework.com/documentation/latest/Home for more details. | ||
|
||
## Running | ||
|
||
Run this using [sbt](http://www.scala-sbt.org/). If you downloaded this project from http://www.playframework.com/download then you'll find a prepackaged version of sbt in the project directory: | ||
|
||
``` | ||
sbt run | ||
``` | ||
|
||
And then go to http://localhost:9000 to see the running web application. | ||
|
||
There are several demonstration files available in this template. | ||
|
||
## Controllers | ||
|
||
- HomeController.scala: | ||
|
||
Shows how to handle simple HTTP requests. | ||
|
||
- AsyncController.scala: | ||
|
||
Shows how to do asynchronous programming when handling a request. | ||
|
||
- CountController.scala: | ||
|
||
Shows how to inject a component into a controller and use the component when | ||
handling requests. | ||
|
||
## Components | ||
|
||
- Module.scala: | ||
|
||
Shows how to use Guice to bind all the components needed by your application. | ||
|
||
- Counter.scala: | ||
|
||
An example of a component that contains state, in this case a simple counter. | ||
|
||
- ApplicationTimer.scala: | ||
|
||
An example of a component that starts when the application starts and stops | ||
when the application stops. | ||
|
||
## Filters | ||
|
||
- Filters.scala: | ||
|
||
Creates the list of HTTP filters used by your application. | ||
|
||
- ExampleFilter.scala | ||
|
||
A simple filter that adds a header to every response. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import com.google.inject.AbstractModule | ||
import java.time.Clock | ||
|
||
/** | ||
* This class is a Guice module that tells Guice how to bind several | ||
* different types. This Guice module is created when the Play | ||
* application starts. | ||
* Play will automatically use any class called `Module` that is in | ||
* the root package. You can create modules in other locations by | ||
* adding `play.modules.enabled` settings to the `application.conf` | ||
* configuration file. | ||
*/ | ||
class Module extends AbstractModule { | ||
|
||
override def configure() = { | ||
// Use the system clock as the default implementation of Clock | ||
bind(classOf[Clock]).toInstance(Clock.systemDefaultZone) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package controllers | ||
|
||
import javax.inject._ | ||
|
||
import models.{Document, Reply} | ||
import play.api.libs.json.{JsObject, JsValue, Json, Writes} | ||
import play.api.mvc._ | ||
import play.modules.reactivemongo.{MongoController, ReactiveMongoApi, ReactiveMongoComponents} | ||
import reactivemongo.play.json.collection.JSONCollection | ||
import utils.{HashUtil, RoaringBitmapUtil} | ||
import reactivemongo.play.json._ | ||
import collection._ | ||
import reactivemongo.play.json.BSONDateTimeFormat | ||
import models.JsonFormats._ | ||
import org.joda.time.{DateTime, DateTimeZone} | ||
import org.roaringbitmap.RoaringBitmap | ||
import play.api.libs.concurrent.Execution.Implicits.defaultContext | ||
|
||
@Singleton | ||
class ArticleController @Inject()(val reactiveMongoApi: ReactiveMongoApi) extends Controller { | ||
def articleColFuture = reactiveMongoApi.database.map(_.collection[JSONCollection]("common-article")) | ||
|
||
def index() = Action { implicit request: Request[AnyContent] => | ||
Ok(views.html.index()) | ||
} | ||
|
||
def add = Action { implicit request: Request[AnyContent] => | ||
Ok(views.html.article.add()) | ||
} | ||
|
||
def vote(articleId: String, up: Boolean) = Action.async { implicit request: Request[AnyContent] => | ||
|
||
val login = "joymufeng1" | ||
(for { | ||
articleCol <- articleColFuture | ||
objOpt <- articleCol.find(Json.obj("_id" -> articleId)).one[JsObject] | ||
} yield { | ||
//articleCol.insert(Article("0", "", "", "", "", "", "", "", "", List.empty[String], DateTime.now(DateTimeZone.UTC), DateTime.now(DateTimeZone.UTC), List.empty[Reply], 0, List.empty[Long], 0, List.empty[Long], 0)).foreach(println _) | ||
|
||
objOpt.fold(Ok(Json.obj("success" -> false))){ obj => | ||
val bitmapStr = (obj \ "viewBitMap").as[String].trim | ||
val bitmap = RoaringBitmapUtil.fromBase64String(bitmapStr) | ||
val userHash = HashUtil.toInt(login) | ||
println(bitmap.contains(userHash)) | ||
if (!bitmap.contains(userHash)) { | ||
println("add user") | ||
bitmap.add(userHash) | ||
articleCol.update(Json.obj("_id" -> articleId), Json.obj("$inc" -> Json.obj("voteCount" -> 1), "$set" -> Json.obj("viewBitMap" -> RoaringBitmapUtil.toBase64String(bitmap)))) | ||
} else { | ||
println("Already voted.") | ||
} | ||
|
||
Ok(Json.obj("success" -> false)) | ||
} | ||
|
||
}).recover{ case t: Throwable => | ||
println(t.getMessage) | ||
t.printStackTrace() | ||
Ok("error") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package controllers | ||
|
||
import javax.inject._ | ||
|
||
import play.api._ | ||
import play.api.mvc._ | ||
import play.modules.reactivemongo.{MongoController, ReactiveMongoApi, ReactiveMongoComponents} | ||
import reactivemongo.play.json.collection.JSONCollection | ||
import play.api.libs.concurrent.Execution.Implicits.defaultContext | ||
|
||
@Singleton | ||
class HomeController @Inject()(val reactiveMongoApi: ReactiveMongoApi) extends Controller { | ||
def robotColFuture = reactiveMongoApi.database.map(_.collection[JSONCollection]("common-robot")) | ||
|
||
def index() = Action { implicit request: Request[AnyContent] => | ||
Ok(views.html.index()) | ||
} | ||
|
||
def login(login: Option[String]) = Action { implicit request: Request[AnyContent] => | ||
Ok(views.html.login()) | ||
} | ||
|
||
def doLogin = Action { implicit request: Request[AnyContent] => | ||
val login = request.body.asFormUrlEncoded.get.get("login").getOrElse(List(""))(0) | ||
val password = request.body.asFormUrlEncoded.get.get("password").getOrElse(List(""))(0) | ||
Redirect(routes.HomeController.index()).withSession("login" -> login, "name" -> login) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package models | ||
|
||
import org.joda.time.DateTime | ||
|
||
case class User(_id: Int, login: String, password: String, name: String, gender: String, introduction: String, headImg: String, ip: String, createTime: DateTime, updateTime: DateTime, lastLoginTime: DateTime, enabled: Boolean) | ||
case class Category(_id: String, name: String, path: String, parentPath: String, disabled: Boolean) | ||
|
||
// 已整理文档 | ||
case class Document( | ||
_id: String, | ||
title: String, | ||
content: String, | ||
editorType: String, | ||
author: Author, | ||
categoryPath: String, | ||
tags: List[String], | ||
createTime: DateTime, | ||
updateTime: DateTime, | ||
replies: List[Reply], | ||
viewStat: ViewStat, | ||
voteStat: VoteStat, | ||
index: Int // 显示排序 | ||
) | ||
|
||
// 问答 | ||
case class Question( | ||
_id: String, | ||
title: String, | ||
content: String, | ||
editorType: String, | ||
author: Author, | ||
categoryPath: String, | ||
tags: List[String], | ||
createTime: DateTime, | ||
updateTime: DateTime, | ||
answer: Option[Reply], | ||
replies: List[Reply], | ||
viewStat: ViewStat, | ||
voteStat: VoteStat | ||
) | ||
|
||
// 分享 | ||
case class Article( | ||
_id: String, | ||
title: String, | ||
content: String, | ||
editorType: String, | ||
author: Author, | ||
categoryPath: String, | ||
tags: List[String], | ||
createTime: DateTime, | ||
updateTime: DateTime, | ||
replies: List[Reply], | ||
viewStat: ViewStat, | ||
voteStat: VoteStat, | ||
top: Boolean, // 置顶 | ||
recommended: Boolean // 精华 | ||
) | ||
|
||
case class Author(_id: String, login: String, name: String, headImg: String) | ||
case class ViewStat(viewCount: Int, viewBitMap: String) | ||
case class VoteStat(voteCount: Int, voteBitMap: String) | ||
case class Reply(_id: String, content: String, editorType: String, replier: Author, replyTime: DateTime, viewStat: ViewStat, comments: List[Comment]) | ||
case class Comment(_id: String, content: String, editorType: String, commentator: Author, commentTime: DateTime) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package models | ||
|
||
import play.api.libs.json.Json | ||
|
||
/** | ||
* Created by Le'novo on 2017/7/2. | ||
*/ | ||
object JsonFormats { | ||
|
||
implicit val viewStatFormat = Json.format[ViewStat] | ||
implicit val voteStatFormat = Json.format[VoteStat] | ||
implicit val authorFormat = Json.format[Author] | ||
implicit val commentFormat = Json.format[Comment] | ||
implicit val replyFormat = Json.format[Reply] | ||
implicit val documentFormat = Json.format[Document] | ||
implicit val articleFormat = Json.format[Article] | ||
implicit val questionFormat = Json.format[Question] | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package service | ||
|
||
import javax.inject.{Inject, Singleton} | ||
import play.api.libs.json.{JsObject, Json} | ||
import play.modules.reactivemongo.ReactiveMongoApi | ||
import reactivemongo.play.json.collection.JSONCollection | ||
import scala.concurrent.Future | ||
import play.api.libs.concurrent.Execution.Implicits.defaultContext | ||
import reactivemongo.play.json._ | ||
|
||
@Singleton | ||
class CounterService @Inject()(val reactiveMongoApi: ReactiveMongoApi) { | ||
def articleColFuture = reactiveMongoApi.database.map(_.collection[JSONCollection]("common-counter")) | ||
|
||
def getNextSequence(name: String): Future[Int] = { | ||
articleColFuture.flatMap{ articleCol => | ||
articleCol.findAndModify( | ||
Json.obj("_id" -> "user-sequence"), | ||
articleCol.updateModifier(Json.obj("$inc" -> Json.obj("value" -> 1)), true, true) | ||
).map(_.result[JsObject]).map{ | ||
case Some(obj) => (obj \ "value").as[Int] | ||
case None => 0 | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package utils; | ||
|
||
/** | ||
* Created by Le'novo on 2017/7/2. | ||
*/ | ||
public class HashUtil { | ||
public static int toInt(String s) { | ||
//return s.hashCode() & 0x7fffffff; | ||
return s.hashCode(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package utils; | ||
|
||
import org.roaringbitmap.RoaringBitmap; | ||
import org.roaringbitmap.buffer.ImmutableRoaringBitmap; | ||
import java.io.DataOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.nio.ByteBuffer; | ||
import java.util.Base64; | ||
|
||
/** | ||
* Created by Le'novo on 2017/7/3. | ||
*/ | ||
public class RoaringBitmapUtil { | ||
public static String toBase64String(RoaringBitmap bitmap) throws IOException { | ||
bitmap.runOptimize(); | ||
ByteBuffer buffer = ByteBuffer.allocate(bitmap.serializedSizeInBytes()); | ||
bitmap.serialize(new DataOutputStream(new OutputStream(){ | ||
ByteBuffer mBB; | ||
OutputStream init(ByteBuffer mbb) { mBB = mbb; return this; } | ||
public void close() {} | ||
public void flush() {} | ||
public void write(int b) { mBB.put((byte) b); } | ||
public void write(byte[] b) { mBB.put(b); } | ||
public void write(byte[] b, int off, int l) { mBB.put(b,off,l); } | ||
}.init(buffer))); | ||
|
||
buffer.flip(); | ||
return Base64.getEncoder().encodeToString(buffer.array()); | ||
} | ||
|
||
public static RoaringBitmap fromBase64String(String base64) { | ||
if (base64 != null && !base64.trim().equals("")) { | ||
ByteBuffer buffer = ByteBuffer.wrap(Base64.getDecoder().decode(base64.trim())); | ||
return new RoaringBitmap(new ImmutableRoaringBitmap(buffer)); | ||
} else { | ||
return new RoaringBitmap(); | ||
} | ||
} | ||
} |
Oops, something went wrong.