软件编程
位置:首页>> 软件编程>> java编程>> spring boot与ktor整合的实现方法

spring boot与ktor整合的实现方法

作者:猫哥不懂技术  发布时间:2022-01-18 04:20:19 

标签:springboot,整合,ktor

背景

在用了一阵子 Ktor 之后,深感基于协程的方便,但是公司的主要技术栈是 SpringBoot,虽然已经整合了 Kotlin,但是如果有 Ktor 加持则会更加的方便。因此作了一番研究后,也完全可以实现这样的整合了。

建立一个 starter

首先新建一个 Kotlin 项目,在其 build.gradle 内加入对 SpringBoot 和 Ktor 的依赖,并同时加入对打为 jar 包的代码:


dependencies {
 implementation "org.springframework.boot:spring-boot-starter-aop:${springBootVersion}"
 implementation "io.ktor:ktor-jackson:${ktorVersion}"
 compile "io.ktor:ktor-server-netty:${ktorVersion}"
 compile "io.ktor:ktor-html-builder:${ktorVersion}"

testImplementation "org.springframework.boot:spring-boot-starter-test:${springBootVersion}"
 testCompile "io.ktor:ktor-client-apache:${ktorVersion}"
 testCompile "io.ktor:ktor-server-test-host:${ktorVersion}"
}

jar {
 from {
   configurations.runtime.collect { zipTree(it) }
 }
}

task sourceJar(type: Jar) {
 from sourceSets.main.allSource
 classifier 'sources'
}

对于 SpringBoot 来说,工程内的 Configuration,Controller,Module 都是必要的,因此也需要 Ktor 可以符合这些约定俗成的组件。

那么就简单来实现一下吧,首先实现 Controller 的代码,我们只需要让 SpringBoot 的 Controller 支持 Ktor 的路由写法就可以了:


interface KRouter {
 fun Routing.route()
}

@ContextDsl
fun Routing.request(
path: String,
body: PipelineInterceptor<Unit, ApplicationCall>
) = route(path) { handle(body) }

然后实现基础的 Module:


interface KModule {

fun Application.defaultRegister(
  useCompress: Boolean = false,
  redirectHttps: Boolean = false,
  headers: String = ""
 ) {
   install(ContentNegotiation) { jackson { } }
   install(PartialContent) { maxRangeCount = 10 }
   if (useCompress) {
     install(Compression) {
       gzip { priority = 1.0 }
       deflate {
         priority = 10.0
         minimumSize(1024)
       }
     }
   }
   if (redirectHttps) {
     install(HttpsRedirect) {
       sslPort = URLProtocol.HTTPS.defaultPort
       permanentRedirect = true
     }
   }
   if (headers != "") {
     install(DefaultHeaders) {
       headers.toCookieMap().forEach { (t, u) -> header(t, "$u") }
     }
   }
 }

@ContextDsl
 fun Application.register()
}

在这个 Module 内,defaultRegister 是通过读取 application.yml 内的配置的参数来决定的,register 是用来让用户覆盖,并实现额外的模块注册。

最后只需要实现 Configuration 就可以了,这里实现读取 yml 并且调用 defaultRegister 等方法:


/**
* spring.ktor 配置项
* @param host 服务器主机名
* @param port 绑定端口
* @param compress 是否启用压缩
* @param redirectHttps 是否自动重定向到 https
* @param headers 默认的请求头
*/
@ConfigurationProperties(prefix = "spring.ktor")
open class KProperties(
   open var host: String = "0.0.0.0",
   open var port: Int = 8080,
   open var compress: Boolean = false,
   open var redirectHttps: Boolean = false,
   open var headers: String = ""
)

用这个类来映射 yml 内的配置,并且在取值后即可实现对模块,路由等的初始化:


@Configuration
@EnableConfigurationProperties(KProperties::class)
open class KConfiguration {

@Resource
 private lateinit var properties: KProperties

@Bean
 @ConditionalOnMissingBean
 open fun engineFactory() = Netty

@Bean
 @ConditionalOnMissingBean
 open fun applicationEngine(
  engineFactory: ApplicationEngineFactory<ApplicationEngine, out ApplicationEngine.Configuration>,
  context: ApplicationContext
 ): ApplicationEngine {
   return embeddedServer(engineFactory, host = properties.host, port = properties.port) {
     val modules = context.getBeansOfType(KModule::class.java).values
     val routes = context.getBeansOfType(KRouter::class.java).values
     modules.forEach { it.apply {
       defaultRegister(
         useCompress = properties.compress,
         redirectHttps = properties.redirectHttps,
         headers = properties.headers)
       register()
     } }
     routing { routes.forEach { it.apply { route() } } }
   }.start()
 }

@Bean
 @ConditionalOnMissingBean
 open fun application(
   applicationEngine: ApplicationEngine,
   context: ApplicationContext
 ): Application = applicationEngine.environment.application
}

来源:https://rarnu.xyz/archives/实现springboot与ktor的整合

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com