这种组合可以像其他任何servlet应用程序一样扩展,同时也可以部署到其他服务器,例如Tomcat。与Node.js之类的东西相比,我更喜欢服务器端的Kotlin。尽管它需要更多的初始设置,但您以后可以使用它,因此会大大受益。对我们来说,最重要的两件事是正确的多线程支持以及正确构建代码的固有需求。
我们使用Jetty为公司中的多个Web应用程序提供服务。为了易于使用和部署,Jetty会永久安装在我们的服务器上,我们不会将其嵌入到webapp本身中。
1.创建一个Kotlin项目。我们使用Gradle,但是您可以根据需要使用Maven。您也可以使用我的模板。
2.除了通常的依赖关系之外,这还需要依赖关系的列表:
dependencies { compile 'org.mongodb:mongodb-driver-sync:3.10.0' compile 'org.litote.kmongo:kmongo:3.9.2' compile 'org.litote.kmongo:kmongo-id-jackson' compile 'org.litote.kmongo:kmongo-id:3.9.2' compile 'org.glassfish.jersey.core:jersey-server:2.30' compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.30' compile 'org.glassfish.jersey.inject:jersey-hk2:2.30' compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.30' }
|
3.创建一个web.xml在src/main/webapp/WEB-INF/web.xml
4.使用此代码段填充您的web.xml。将%%替换为您的信息。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>%%YourProjectName%%</display-name> <servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>%%your.package.here%%</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> </web-app>
|
5.我们需要注册@Provider的KMongo。这将确保JSON对象与KMongo我们接下来创建的数据类之间的转换是无缝的。创建一个KMongoProvider.kt并使用以下代码:
@Provider class KMongoProvider : ContextResolver<ObjectMapper> { override fun getContext(type: Class<*>): ObjectMapper { return KMongoJackson.mapper } }
object KMongoJackson { val mapper = jacksonObjectMapper()
init { mapper.registerModule(IdJacksonModule()) } }
|
6.让我们连接到数据库并创建一个数据模型:class Connect { companion object { val client = KMongo.createClient() val database = client.getDatabase("kotlin-example") } }
data class Dog ( @BsonId var _id: StringId<Dog> = newStringId(), var owner: String, var name: String, var bornAt: Int, var lastVaccineAt: Int? ) { companion object
fun collection(): MongoCollection<Dog> { return Connect.database.getCollection<Dog>("dogs") } }
|
7.现在我们需要为我们的Dog类提供资源。它将告诉Jersey如何与模型进行交互,并将为API访问公开模型:
@Path("dogs") @Produces(APPLICATION_JSON) class DogResource {
@GET fun listDogs(): MongoIterable<Dog> { return Dog.collection().find().map { it } }
@POST fun createDog(token: Dog) { Dog.collection().save(token) }
@GET @Path("{id}") fun getDog(@PathParam("id") id: String): Dog? { return Dog.collection().findById(id) }
@PUT @Path("{id}") fun updateDog(@PathParam("id") id: String, dog: Dog) { dog._id = StringId(id) Dog.collection().replaceById(id, dog) }
@DELETE @Path("{id}") fun deleteDog(@PathParam("id") id: String): Boolean { return Dog.collection().deleteById(id).deletedCount > 0 }
}
|
该listDogs()方法不使用任何参数,而是使用我们为DogResource定义的路径。createDog()方法输入参数是JSON,与数据模型匹配但没有_id密钥。尝试发送错误格式的,JSON以查看其行为。该get / update / delete方法适用于*/dogs/{id}/。8.我使用下面列出的扩展功能轻松地通过id查找/替换内容。创建一个DBUtility.kt并将函数放入其中。
fun <T> MongoCollection<T>.findById(id: String): T? { return this.findOneById(StringId<T>(id)) }
fun <T> MongoCollection<T>.deleteById(id: String): DeleteResult { return this.deleteOneById(StringId<T>(id)) }
fun <T> MongoCollection<T>.replaceById(id: String, newObject: T): UpdateResult { return this.replaceOne(KMongoUtil.idFilterQuery(StringId<T>(id)), newObject) }
|
9.现在进行测试。我使用Postman发送POST请求到localhost:8080/api/dogs/。内容如下:
{ "owner": "John Doe", "name": "Good Boy", "bornAt": 1583158516 }
|
现在,您可以在几分钟内添加任意数量的资源,而无需为此做太多事情。您还可以使用自定义路径并定义所需的任何方法,Jersey将始终为您处理解析和实际servlet创建。