first commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.ray650128
|
||||
|
||||
import com.ray650128.plugins.configureRouting
|
||||
import com.ray650128.plugins.configureSerialization
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
|
||||
fun main() {
|
||||
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
|
||||
configureRouting()
|
||||
configureSerialization()
|
||||
}.start(wait = true)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ray650128.dto
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PersonDto(
|
||||
val id: String? = null,
|
||||
val name: String,
|
||||
val age: Int
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ray650128.extension
|
||||
|
||||
import com.ray650128.dto.PersonDto
|
||||
import com.ray650128.model.Person
|
||||
|
||||
fun Person.toDto(): PersonDto =
|
||||
PersonDto(
|
||||
id = this.id.toString(),
|
||||
name = this.name,
|
||||
age = this.age
|
||||
)
|
||||
|
||||
fun PersonDto.toPerson(): Person =
|
||||
Person(
|
||||
name = this.name,
|
||||
age = this.age
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ray650128.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ErrorResponse(val message: String) {
|
||||
companion object {
|
||||
val NOT_FOUND_RESPONSE = ErrorResponse("Person was not found")
|
||||
val BAD_REQUEST_RESPONSE = ErrorResponse("Invalid request")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ray650128.model
|
||||
|
||||
import org.bson.codecs.pojo.annotations.BsonId
|
||||
import org.litote.kmongo.Id
|
||||
|
||||
data class Person(
|
||||
@BsonId
|
||||
val id: Id<Person>? = null,
|
||||
val name: String,
|
||||
val age: Int
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import com.ray650128.dto.PersonDto
|
||||
import com.ray650128.extension.toDto
|
||||
import com.ray650128.extension.toPerson
|
||||
import com.ray650128.model.ErrorResponse
|
||||
import com.ray650128.model.Person
|
||||
import com.ray650128.service.PersonService
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
|
||||
fun Application.configureRouting() {
|
||||
val service = PersonService()
|
||||
|
||||
routing {
|
||||
get("/") {
|
||||
call.respondText("Hello World!")
|
||||
}
|
||||
|
||||
route("/person") {
|
||||
post {
|
||||
val request = call.receive<PersonDto>()
|
||||
val person = request.toPerson()
|
||||
service.create(person)
|
||||
?.let { userId ->
|
||||
call.response.headers.append("My-User-Id-Header", userId.toString())
|
||||
call.respond(HttpStatusCode.Created)
|
||||
} ?: call.respond(HttpStatusCode.BadRequest, ErrorResponse.BAD_REQUEST_RESPONSE)
|
||||
}
|
||||
|
||||
get {
|
||||
val peopleList = service.findAll().map(Person::toDto)
|
||||
call.respond(peopleList)
|
||||
}
|
||||
|
||||
get("/{id}") {
|
||||
val id = call.parameters["id"].toString()
|
||||
service.findById(id)
|
||||
?.let { foundPerson -> call.respond(foundPerson.toDto()) }
|
||||
?: call.respond(HttpStatusCode.NotFound, ErrorResponse.NOT_FOUND_RESPONSE)
|
||||
}
|
||||
|
||||
get("/search") {
|
||||
val name = call.request.queryParameters["name"].toString()
|
||||
val foundPeople = service.findByName(name).map(Person::toDto)
|
||||
call.respond(foundPeople)
|
||||
}
|
||||
|
||||
put("/{id}") {
|
||||
val id = call.parameters["id"].toString()
|
||||
val personRequest = call.receive<PersonDto>()
|
||||
val person = personRequest.toPerson()
|
||||
val updatedSuccessfully = service.updateById(id, person)
|
||||
if (updatedSuccessfully) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.BadRequest, ErrorResponse.BAD_REQUEST_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
delete("/{id}") {
|
||||
val id = call.parameters["id"].toString()
|
||||
val deletedSuccessfully = service.deleteById(id)
|
||||
if (deletedSuccessfully) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, ErrorResponse.NOT_FOUND_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
routing {
|
||||
get("/json/kotlinx-serialization") {
|
||||
call.respond(mapOf("hello" to "world"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.ray650128.service
|
||||
|
||||
import com.ray650128.model.Person
|
||||
import org.bson.types.ObjectId
|
||||
import org.litote.kmongo.*
|
||||
import org.litote.kmongo.id.toId
|
||||
|
||||
class PersonService {
|
||||
private val client = KMongo.createClient("mongodb://www.ray650128.com:27017")
|
||||
private val database = client.getDatabase("person")
|
||||
private val personCollection = database.getCollection<Person>()
|
||||
|
||||
fun create(person: Person): Id<Person>? {
|
||||
personCollection.insertOne(person)
|
||||
return person.id
|
||||
}
|
||||
|
||||
fun findAll(): List<Person> = personCollection.find().toList()
|
||||
|
||||
fun findById(id: String): Person? {
|
||||
val bsonId: Id<Person> = ObjectId(id).toId()
|
||||
return personCollection.findOne(Person::id eq bsonId)
|
||||
}
|
||||
|
||||
fun findByName(name: String): List<Person> {
|
||||
val caseSensitiveTypeSafeFilter = Person::name regex name
|
||||
return personCollection.find(caseSensitiveTypeSafeFilter).toList()
|
||||
}
|
||||
|
||||
fun updateById(id: String, request: Person): Boolean =
|
||||
findById(id)?.let { person ->
|
||||
val updateResult = personCollection.replaceOne(person.copy(name = request.name, age = request.age))
|
||||
updateResult.modifiedCount == 1L
|
||||
} ?: false
|
||||
|
||||
fun deleteById(id: String): Boolean {
|
||||
val deleteResult = personCollection.deleteOneById(ObjectId(id))
|
||||
return deleteResult.deletedCount == 1L
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.netty" level="INFO"/>
|
||||
</configuration>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ray650128
|
||||
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.server.testing.*
|
||||
import kotlin.test.*
|
||||
import io.ktor.http.*
|
||||
import com.ray650128.plugins.*
|
||||
|
||||
class ApplicationTest {
|
||||
@Test
|
||||
fun testRoot() = testApplication {
|
||||
application {
|
||||
configureRouting()
|
||||
}
|
||||
client.get("/").apply {
|
||||
assertEquals(HttpStatusCode.OK, status)
|
||||
assertEquals("Hello World!", bodyAsText())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user