kotlin是由IntelliJ IDEA的开发商Jetbrain推出的一种基于JVM的开发语言,目标是简化Java中很多繁琐的设计,可以和Java无缝的集成,之前一直在单元测试的时候试着使用,最近正好由契机,试着用来写一下Spring Boot脚手架。
官方定义: Statically typed programming language for the JVM, Android and the browser
项目介绍
长期目标是使用kotlin开发一个完整的spring boot应用,目前搭建了最小量的脚手架。
在本次实践中增加了gradle docker插件的使用,使用gradle一站式的完成从开发、测试、打包到发布docker镜像的整个过程。
项目结构
SpringBootKotlon
│
├─── build.gradle
└─── src
├───main
│ ├─── docker
│ ├─── java
│ ├─── kotlin
│ └─── resources
│ └─── config/application.properties
└───test
├─── java
├─── kotlin
└─── resources
在main目录的java、kotlin、resources下面,包名是一样的。也就是说在kotlin/com/app和java/com/app下的类,在classpath引用的时候是同一个包。
创建Spring Boot项目
Spring Boot项目的创建,可以参考《用Gradle和SpringBoot实现简单的RESTful框架应用》。
为了支持kotlin本项目的build.gradle
中需要增加kotlin的支持,并且配置docker插件。
buildscript {
ext.kotlin_version = '1.1.0'
ext.spting_boot_version = '1.5.2.RELEASE'
... ...
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath("org.springframework.boot:spring-boot-gradle-plugin:$spting_boot_version")
}
}
... ...
apply plugin: "kotlin"
apply plugin: 'org.springframework.boot'
dependencies {
... ...
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
sourceSets{
main{
... ...
kotlin {srcDir "src/main/kotlin"}
}
test{
... ...
kotlin {srcDir "src/test/kotlin"}
}
}
配置完之后,运行gradle idea
,下载相应的gradle依赖包。在repositories中使用国内镜像和自建的本地nexus,可以加快依赖包的下载速度maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
配置sourceSets增加kotlin的包之后,可以自己创建一个gradle task,自动创建sourceSets对应的目录;gradle createJavaProject
会根据sourceSets中配置的路径,创建指定set对应的目录。
task createJavaProject << {
sourceSets*.java.srcDirs*.each { it.mkdirs() }
sourceSets*.kotlin.srcDirs*.each { it.mkdirs() }
sourceSets*.resources.srcDirs*.each { it.mkdirs()}
}
运行spring boot程序
项目的application入口类,使用kotlin语言实现,在kotlin中是没有静态方法的,所以如果要实现main函数,有两种方法,一种是将main函数写在class的外面;或者使用companion object {}
,将需要静态调用的方法写在{}中。
@SpringBootApplication
open class SpringBootKotlinApplication
fun main(args: Array){
SpringApplication.run(SpringBootKotlinApplication::class.java,*args)
}
相比spring mvc,spring boot给人最大的感触就是,用简单的注解和application.properties配置的方式,避免了spring mvc中繁琐而且容易出错的xml配置文件,极大的简化了spring boot的配置。值得一提的是,application配置文件,也可以使用yaml文件。
application配置文件说明
端口
通过在配置文件中设置server.port
属性,可以指定spring boot运行时绑定的端口。
freemarker
spring.freemarker.*
是spring boot提供的freemarker相关配置,可以配置的属性,和注解或者xml文件是一样的,要使用spring.freemarker配置,需要在gradle中,引入org.springframework.boot:spring-boot-starter-freemarker
这个包。
此外,spring boot的application配置文件,还可以配置包括数据库在内的各种常见第三方工具或者库,应该是将提供了一系列starter包,将注解和配置过程包装起来了。
配置完成之后,就可以在Application类的子目录中编写Spring MVC的控制器代码。
编写restful controller
一个最基本的RestController代码如下:
@RestController
@RequestMapping(value = "/api/data")
class DataController {
@RequestMapping(value = "",method = arrayOf(RequestMethod.GET,RequestMethod.PUT))
fun index():Map{
val resultMap = HashMap()
resultMap["status"] = true
resultMap["msg"] = "success"
return resultMap
}
@RequestMapping(value = "show",method = arrayOf(RequestMethod.PUT),consumes = arrayOf(MediaType.APPLICATION_JSON_UTF8_VALUE))
fun test(@RequestBody reqMap:Map):Map{
return reqMap
}
}
代码解读:
- kotlin中使用arrayof来初始化数组;
- 对于不指定类型或者Obejct型的变量,kotlin使用Any类型
- method方法中可以指定对种请求头,很灵活
- 在consumes中,可以指定接受的contentType为JSON格式
- 如果请求是json格式,用ResponseBody就可以接收JSON对象
完成所有代码之后,运行gradle bootRun
就可以启动服务。
curl 'http://localhost:8080/api/data/show' \
-X 'PUT' \
-H 'content-type: application/json' \
-H 'accept: application/json' \
--data-binary '{"data":"hello","who":"echo"}' --compressed
测试spring boot程序
spring boot和kotlin都提供了强大的测试套件,能够很好的和JUnit集成,进行集成测试和单元测试。编写一些基本的集成测试,检查接口是否正常。
spring boot starter test集成了JUnit 、Mockito、AssertJ 、Hamcrest 、Spring Test & Spring Boot Test可以方便的开始测试
@RunWith(SpringJUnit4ClassRunner::class)
@WebMvcTest(HomeController::class)
class HomeControllerStandaloneTest {
@Autowired
private var mvc: MockMvc? = null
@Test
@Throws(Exception::class)
fun indexTest() {
mvc!!.perform(MockMvcRequestBuilders.get("/").accept(MediaType.TEXT_HTML))
.andExpect(status().isOk)
.andExpect(model().attributeExists("data"))
.andExpect { content().string(containsString("Spring Boot Kotlin ")) }
}
}
MockMvc可以依赖注入绑定通过WebMvcTest注解的HomeController控制器,然后针对指定的controller模拟请求。andExpect方法,检查response的header,body是否符合测试的期望。
源代码:https://github.com/liuwill-projects/SpringBootKotlin