spring boot与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
}

好了,一个简单的 starter 就完成了,最后加入一些配置就可以完成:

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.isyscore.ktor.starter.configuration.KConfiguration

然后加入对配置项的描述:

additional-spring-configuration-metadata.json

{
 "properties": [
  {
   "name": "spring.ktor.port",
   "type": "java.lang.Integer",
   "description": "服务启动时使用的端口号."
  },
  {
   "name": "spring.ktor.host",
   "type": "java.lang.String",
   "description": "服务的主机IP或域名."
  },
  {
   "name": "spring.ktor.compress",
   "type": "java.lang.Boolean",
   "description": "是否启用压缩."
  },
  {
   "name": "spring.ktor.redirectHttps",
   "type": "java.lang.Boolean",
   "description": "是否自动重定向到 https."
  },
  {
   "name": "spring.ktor.headers",
   "type": "java.lang.String",
   "description": "默认的请求头,以分号隔开."
  }
 ]
}

最后我们只需要将这个 starter 发布到私有的 nexus 就完成了:

$ gradle publish

使用 starter

新建一个 SpringBoot 项目,并引入 starter:

implementation "com.rarnu:spring-boot-starter-ktor:0.0.1"

此时可以先在 yml 内加入配置项:

spring:
 ktor:
  port: 9000
  compress: true
  headers: X-Engine=Ktor

然后来实现 Configuration,Controller 和 Module:

TestConfiguration.kt

class TestConfiguration {
  @Bean
  fun engineFactory() = TestEngine
}

TestModule.kt

@Component
class TestModule : KModule {
  override fun Application.register() {
  // TODO: install custom plugins
  }
}

TestController.kt

@Controller
class TestController : KRouter {

  override fun Routing.route() {

    request("/") {
      call.respond(mapOf("code" to "001", "msg" to "操作成功。"))
    }

    get("/hello") {
      call.respondText { "OK" }
    }
  }
}

完成后我们只需要写一个 Application,并且启动服务即可:

SpringKtorApplication.kt

@SpringBootApplication
open class SpringKtorApplication

fun main(args: Array<String>) {
  runApplication<SpringKtorApplication>(*args)
}

现在就可以编译项目并且运行程序了:

$ gradle clean build
$ java -jar test-ktor.jar

总结

现在即可使用 Ktor 的写法来编写 SpringBoot 的路由了

可以使用 Ktor 协程

可以使用各种方便的 Ktor 插件

用上 Ktor 后,代码不麻烦了,心情也好了,效率更高了 :)

到此这篇关于spring boot与ktor整合的文章就介绍到这了,更多相关spring boot与ktor整合内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • spring boot与ktor整合的实现方法

    背景 在用了一阵子 Ktor 之后,深感基于协程的方便,但是公司的主要技术栈是 SpringBoot,虽然已经整合了 Kotlin,但是如果有 Ktor 加持则会更加的方便.因此作了一番研究后,也完全可以实现这样的整合了. 建立一个 starter 首先新建一个 Kotlin 项目,在其 build.gradle 内加入对 SpringBoot 和 Ktor 的依赖,并同时加入对打为 jar 包的代码: dependencies { implementation "org.springframe

  • Spring Boot集成MyBatis访问数据库的方法

    基于spring boot开发的微服务应用,与MyBatis如何集成? 集成方法 可行的方法有: 1.基于XML或者Java Config,构建必需的对象,配置MyBatis. 2.使用MyBatis官方提供的组件,实现MyBatis的集成. 方法一 建议参考如下文章,完成集成的验证. MyBatis学习 之 一.MyBatis简介与配置MyBatis+Spring+MySql 基于Spring + Spring MVC + Mybatis 高性能web构建 spring与mybatis三种整合

  • 移动开发Spring Boot外置tomcat教程及解决方法

    springboot微服务内置了tomcat,在工程目录下执行:mvn clean package,可以将项目打成jar,通过java -jar jar包名.jar启动项目. 有哪些场景需要将springboot打成war包去部署呢? 1.一个tomcat管理多个项目 2.springboot整合jsp等 解决方法: 1.<packaging>jar</packaging>中的jar改成war 2.引入依赖: <dependency> <groupid>or

  • Spring Boot 中使用cache缓存的方法

    一.什么是缓存 Cache Cache 一词最早来自于CPU设计 当CPU要读取一个数据时,首先从CPU缓存中查找,找到就立即读取并送给CPU处理:没有找到,就从速率相对较慢的内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存.正是这样的读取机制使CPU读取缓存的命中率非常高(大多数CPU可达90%左右),也就是说CPU下一次要读取的数据90%都在CPU缓存中,只有大约10%需要从内存读取.这大大节省了CPU直接读取内存的

  • Spring Boot和Thymeleaf整合结合JPA实现分页效果(实例代码)

    在项目里,我需要做一个Spring Boot结合Thymeleaf前端模版,结合JPA实现分页的演示效果.做的时候发现有些问题,也查了现有网上的不少文档,发现能全栈实现的不多,所以这里我就把我的做法,全部代码和步骤贴出来供大家参考. 1 创建项目,用pom.xml引入依赖 这里将创建名为ThymeleafWithDB的Maven,在pom.xml里引入如下的依赖包. <dependencies> <dependency> <groupId>org.springframe

  • Spring Boot+Mybatis的整合过程

    依赖配置 结合前面的内容,这里我们要嵌入数据库的操作,这里以操作MySQL为例整合Mybatis,首先需要在原来的基础上添加以下依赖 <!-- mybatis依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1<

  • spring Boot与Mybatis整合优化详解

    SpringBoot官方文档http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ 关于spring-boot与mybatis整合优化方面的介绍,就是Mybatis-Spring-boot-starter的介绍: 1.取消spring-mybatis.xml配置 ①自动检测已存在的Datasource 之前,需要在spring-mybatis.xml中配置datasource的Bean,现在只需要在applicat

  • Spring Boot使用Druid和监控配置方法

    Spring Boot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource Druid是Java语言中最好的数据库连接池,并且能够提供强大的监控和扩展功能. 下面来说明如何在 Spring Boot 中配置使用Druid (1)添加Maven依赖 (或jar包)\ <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId&g

  • Spring Boot中使用MongoDB数据库的方法

    MongoDB数据库简介 简介 MongoDB是一个高性能,开源,无模式的,基于分布式文件存储的文档型数据库,由C++语言编写,其名称来源取自"humongous",是一种开源的文档数据库──NoSql数据库的一种.NoSql,全称是 Not Only Sql,指的是非关系型的数据库. 特点 MongoDB数据库的特点是高性能.易部署.易使用,存储数据非常方便.主要功能特性有: * 面向集合存储,易存储对象类型的数据. * 模式自由. * 支持动态查询. * 支持完全索引,包含内部对象

  • Spring Boot 2.0多数据源配置方法实例详解

    两个数据库实例,一个负责读,一个负责写. datasource-reader: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://192.168.43.61:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false username: icbc password: icbc driver-class-na

随机推荐