Kotlin简介:Kotlin是一个基于JVM的静态类型编程语言,由JetBrains设计开发并开源。Kotlin能够与Java进行完全的交互,可以在同一个项目中同时使用Java和Kotlin。并且支持多种平台,包括移动端、服务端以及浏览器端,Kotlin已正式成为Android官方支持开发语言。
Spring Framework 5.0版本中已经正式支持Kotlin语言,SpringBoot从SpringBoot2开始也正式支持Kotlin。
最近刚开始学习Kotlin,也踩了一些坑,顺便总结一下基于kotlin开发的SpringBoot2.x环境搭建。
这里直接通过maven构建一个java项目,然后对pom
文件进行修改,添加kotlin相关依赖和插件,完整的pom
文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.rtxtitanvgroupId>
<artifactId>springboot-kotlinartifactId>
<version>1.0.0version>
<packaging>jarpackaging>
<name>springboot-kotlinname>
<description>SpringBoot2.x kotlin 开发环境description>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.2.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<kotlin.compiler.incremental>truekotlin.compiler.incremental>
<java.version>1.8java.version>
<kotlin.version>1.3.61kotlin.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.modulegroupId>
<artifactId>jackson-module-kotlinartifactId>
dependency>
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-reflectartifactId>
dependency>
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-stdlib-jdk8artifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlinsourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlintestSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-maven-pluginartifactId>
<version>${kotlin.version}version>
<configuration>
<args>
<arg>-Xjsr305=strictarg>
args>
<compilerPlugins>
<plugin>springplugin>
<plugin>no-argplugin>
compilerPlugins>
<pluginOptions>
<option>no-arg:annotation=com.rtxtitanv.annotation.KtNoArgsConstructoroption>
pluginOptions>
configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-maven-allopenartifactId>
<version>${kotlin.version}version>
dependency>
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-maven-noargartifactId>
<version>${kotlin.version}version>
dependency>
dependencies>
<executions>
<execution>
<id>compileid>
<goals> <goal>compilegoal> goals>
execution>
<execution>
<id>test-compileid>
<goals> <goal>test-compilegoal> goals>
execution>
executions>
plugin>
plugins>
build>
project>
项目结构如下:
编写主启动类,一个最简单的基于Kotlin的SpringBoot项目就构建完成了。
package com.rtxtitanv
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
/**
* @name com.rtxtitanv.KotlinApplication
* @description 主启动类
* @author rtxtitanv
* @date 2020/1/16 14:48
* @version v1.0.0
*/
@SpringBootApplication
class KotlinApplication
fun main(args: Array<String>) {
runApplication<KotlinApplication>(*args)
}
进行一些简单的测试,看能否正常使用Kotlin开发SpringBoot应用。
这里使用Data数据类,一般情况下编译器会自动生成equals()、 hashCode()、toString()等函数,至于getter和setter,没有显示定义Kotlin会默认自动生成。
package com.rtxtitanv.model
import com.rtxtitanv.annotation.KtNoArgsConstructor
/**
* @name com.rtxtitanv.model.User
* @description 用户实体类
* @author rtxtitanv
* @date 2020/1/16 16:07
* @version v1.0.0
*/
@KtNoArgsConstructor
data class User(var id: Long? = null,//?表示声明为Nullable变量
var userName: String? = null,
var passWord: String? = null,
var nickName: String? = null,
var age: Int? = null,
var tel: String? = null,
var addr: String? = null)
自定义如下注解主要用于Kotlin的no-arg插件,指定该注解应用于no-arg插件,即注解有该注解的类。no-arg插件会为其自动添加无参构造函数,不过该无参构造函数只能通过反射调用,如果User类主构造函数中初始化了属性值,则可以通过User()调用无参构造函数,省略no-args插件也可以,也可以反射调用无参构造函数。
package com.rtxtitanv.annotation
/**
* @name com.rtxtitanv.annotation.KtNoArgsConstructor
* @description kotlin自定义无参构造器注解
* @author rtxtitanv
* @date 2020/1/16 16:57
* @version v1.0.0
*/
annotation class KtNoArgsConstructor
package com.rtxtitanv
import com.rtxtitanv.model.User
import org.junit.Test
import org.junit.runner.RunWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
/**
* @name com.rtxtitanv.KotlinTest
* @description 单元测试类
* @author rtxtitanv
* @date 2020/1/16 15:33
* @version v1.0.0
*/
@RunWith(SpringRunner::class)
@SpringBootTest(classes = [KotlinApplication::class])
class KotlinTest {
private val logger: Logger = LoggerFactory.getLogger(KotlinTest::class.java)
@Test
fun kotlinTest() {
//通过反射调用自动生成的无参构造函数
val user1 = User::class.java.newInstance()
//在User类主构造函数中初始化了属性值,则可以通过User()调用无参构造函数,省略no-args插件也可以,也可以反射调用
//如果没有在主构造函数中初始化属性值,则不能通过User()显式调用无参构造函数,必须要加上应用no-args插件的注解
//且通过反射调用
val user2 = User()
logger.info("user1: " + user1.toString())
logger.info("user2: " + user2.toString())
}
}
控制台打印的日志说明自动生成了无参构造函数。
2020-01-17 21:39:21.172 INFO 15164 --- [ main] com.rtxtitanv.KotlinTest : user1: User(id=null, userName=null, passWord=null, nickName=null, age=null, tel=null, addr=null)
2020-01-17 21:39:21.172 INFO 15164 --- [ main] com.rtxtitanv.KotlinTest : user2: User(id=null, userName=null, passWord=null, nickName=null, age=null, tel=null, addr=null)
这里省去了数据层,数据为手动模拟的,主要用于控制层返回数据测试。
package com.rtxtitanv.service
import com.rtxtitanv.model.User
/**
* @name com.rtxtitanv.service.KotlinService
* @description KotlinService接口
* @author rtxtitanv
* @date 2020/1/16 17:06
* @version v1.0.0
*/
interface KotlinService {
/**
* 根据年龄查询用户
*/
fun findUserByAge(age: Int): List<User>
}
package com.rtxtitanv.service.impl
import com.rtxtitanv.model.User
import com.rtxtitanv.service.KotlinService
import org.springframework.stereotype.Service
/**
* @name com.rtxtitanv.service.impl.KotlinServiceImpl
* @description KotlinService实现类
* @author rtxtitanv
* @date 2020/1/16 17:07
* @version v1.0.0
*/
@Service
class KotlinServiceImpl : KotlinService {
/**
* 模拟根据年龄查询用户,只是测试,返回写死的user数据
*/
override fun findUserByAge(age: Int): List<User> {
val user1 = User(1L, "aaa",
"123456", "abc",
age, "198658632", "北京")
val user2 = User(2L, "bbb",
"111222", "cba",
age, "15963247851", "上海")
val userList = ArrayList<User>()
userList.add(user1)
userList.add(user2)
return userList
}
}
package com.rtxtitanv.controller
import com.rtxtitanv.model.User
import com.rtxtitanv.service.KotlinService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/**
* @name com.rtxtitanv.controller.KotlinController
* @description KotlinController
* @author rtxtitanv
* @date 2020/1/16 14:59
* @version v1.0.0
*/
@RequestMapping("/kotlin")
@RestController
class KotlinController(private val kotlinService: KotlinService) {
/**
* springboot2.x kotlin开发环境测试
*/
@GetMapping("/test")
fun helloKotlin(): String {
return "hello kotlin!"
}
/**
* 根据年龄查询用户
*/
@GetMapping("/user/{age}")
fun findUser(@PathVariable age: Int): List<User> {
return kotlinService.findUserByAge(age)
}
}
访问localhost:8080/kotlin/test
:
访问localhost:8080/kotlin/user/25
:
能正常返回json数据,说明一个基于Kotlin的简单SpringBoot2.x开发环境就搭建完成了。可以看出Kotlin非常适合开发服务器端应用程序,可以编写出简明且表现力强的代码,同时保持与现有基于Java的技术栈的完全兼容性,所以Kotlin还是有必要学习和掌握的。
代码示例