目录
前言
Ktor是使用kotlin语音写的一个高性能web框架, 你可以类比认为 Tomcat 服务器.
本篇只是简单的说明 如何启动一个web服务 ,
项目结构
项目使用Gradle管理, 整个项目结果如下:
Gradle的包依赖管理
定义了kotlin 和 ktor的版本 , 并且引入了日志框架logback
和我最喜欢的工具包hutool
项目的最外部的build.gradle
文件的内容如下:
buildscript {
ext {
kotlin_version = '1.5.30'
ktor_version = '1.6.7'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
subprojects {
apply plugin: "idea"
apply plugin: "kotlin"
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
mavenCentral()
jcenter()
}
dependencies {
compile "ch.qos.logback:logback-classic:1.2.5"
compile "cn.hutool:hutool-all:5.7.10"
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
}
nexus模块
build.gradle文件
其中 ktor 开头的包都是 相关的包, hibernate和postgresql相关的包入门的时候可以先删除, 后面我会接入hibernate和postgresql的.
plugins {
id 'kotlin'
id 'application'
}
group 'com.github.blanexie'
version '1.0-SNAPSHOT'
application {
mainClass = 'com.github.blanexie.nexusj.AppKt'
}
dependencies {
implementation 'org.postgresql:postgresql:42.3.3'
implementation 'org.hibernate:hibernate-core:5.6.5.Final'
implementation "io.ktor:ktor-server-core:$ktor_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "io.ktor:ktor-auth:$ktor_version"
implementation "io.ktor:ktor-auth-jwt:$ktor_version"
implementation "io.ktor:ktor-gson:$ktor_version"
testImplementation "io.ktor:ktor-server-test-host:$ktor_version"
testImplementation "org.jetbrains.kotlin:kotlin-test"
}
test {
useJUnitPlatform()
}
resource目录下的application.conf文件
这个是ktor的配置文件, 其中定义了端口号等信息, 也定义了jwt鉴权相关的信息.
ktor {
development = true
deployment {
port = 8080
autoreload = true
}
application {
modules = [ com.github.blanexie.nexusj.AppKt.module ]
watch = [ com.github.blanexie.nexusj ]
}
}
jwt {
domain = "https://jwt-provider-domain/"
audience = "jwt-audience"
realm = "ktor sample app"
}
App启动类
package com.github.blanexie.nexusj
import com.github.blanexie.nexusj.support.Auth
import com.github.blanexie.nexusj.support.Config
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.auth.jwt.*
import io.ktor.features.*
import io.ktor.gson.*
import io.ktor.http.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import java.text.DateFormat
import javax.persistence.EntityManagerFactory
import javax.persistence.Persistence
import javax.persistence.PersistenceUnit
fun main(args: Array<String>): Unit {
io.ktor.server.netty.EngineMain.main(args)
}
fun Application.module(testing: Boolean = true) {
Config.build(environment)
//响应自动完善请求头
install(AutoHeadResponse)
//启用压缩
install(Compression)
//启用日志打印
install(CallLogging)
//json序列化设置, 使用了gson
install(ContentNegotiation) {
gson {
setDateFormat(DateFormat.LONG)
setPrettyPrinting()
}
}
//跨域设置
install(CORS) {
method(HttpMethod.Options)
method(HttpMethod.Get)
method(HttpMethod.Post)
method(HttpMethod.Put)
method(HttpMethod.Delete)
method(HttpMethod.Patch)
header(HttpHeaders.Authorization)
header(HttpHeaders.ContentType)
allowCredentials = true
allowNonSimpleContentTypes = true
//允许跨域的域名. 最新版本的必须要指定需要跨域的域名
host("localhost")
}
//JWT鉴权
install(Authentication) {
jwt {
verifier(Auth.verifier)
validate {
JWTPrincipal(it.payload)
}
}
}
//路由设置
routing {
route("/announce") {
get() {
val uri = call.request.uri
//生成jwt的token
val token= Auth.makeToken("xiezc")
//获取配置文件的信息
val domain = Config.getConfig().getStringOrNull("jwt.domain")
call.respondText("Request uri: $uri ; $token; $domain")
}
}
//需要鉴权访问的路由
route("/api/nexus") {
authenticate {
get("/test") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}
}
}
}
//拦截器的配置
intercept(ApplicationCallPipeline.Call) {
if (call.request.uri == "/") {
call.respondText("Test String")
}
}
}
上面的代码配置了两个路由, 一个拦截器, 我们访问下:
http://localhost:8080/announce
token也生成了, domain配置文件的信息也获取到了
http://localhost:8080/
返回了拦截器的信息
http://localhost:8080/api/nexus/test
鉴权生效了
Auth类代码
这个类中主要是jwt相关的代码
package com.github.blanexie.nexusj.support
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.interfaces.JWTVerifier
import java.util.*
object Auth {
private const val SECRET_KEY = "secret"
private val algorithm = Algorithm.HMAC512(SECRET_KEY)
private const val issuer = "ktor.io"
private const val validityInMs = 3600 * 1000 * 72 // 72 hours
val verifier = JWT
.require(algorithm)
.withIssuer(issuer)
.build()!!
//生成token
fun makeToken(name: String): String = JWT.create()
.withSubject("Authentication")
.withIssuer(issuer)
.withClaim("name", name)
.withExpiresAt(getExpiration())
.sign(algorithm)
private fun getExpiration() = Date(System.currentTimeMillis() + validityInMs)
}
Config 配置类
获取ktor中配置文件信息的工具类
package com.github.blanexie.nexusj.support
import io.ktor.application.*
/**
* 配置信息
*
* @author :xiezc
* @date :2022/2/28 3:05 PM
*/
class Config(val environment: ApplicationEnvironment) {
companion object {
private var config: Config? = null
fun build(environment: ApplicationEnvironment): Config {
this.config = Config(environment)
return this.config!!
}
fun getConfig(): Config {
return this.config!!
}
}
fun getString(key: String): String {
return environment.config.property(key).getString();
}
fun getStringOrNull(key: String): String? {
return environment.config.propertyOrNull(key)?.getString();
}
fun getList(key: String): List<String> {
return environment.config.property(key).getList();
}
fun getListOrNull(key: String): List<String>? {
return environment.config.propertyOrNull(key)?.getList();
}
}
启动
结尾
ktor的文档地址:
https://ktor.kotlincn.net/servers/application.html
可以参考这个文档地址 进行一些个性化的改造, 比如:
- 序列化使用jackson等.
- 鉴权方式使用basic等
本篇只是简单搭起一个可以运行的web服务, 后面还要接入hibernate和数据库postgresql
敬请期待