领先一步
VMware 提供培训和认证,助您加速进步。
了解更多更新:现已提供一份全面的 Spring Boot + Kotlin 教程。
恰逢 Kotlin 1.0 发布,我们在 https://start.spring.io 中增加了对 Kotlin 语言的支持,以便更轻松地使用该语言启动新的 Spring Boot 项目。
这篇博文也给了我一个机会,解释为什么我认为这种语言很有趣,向您详细展示一个示例项目,并为您提供一些技巧。
Kotlin 是由 JetBrains 创建的一种语言。它运行在 JVM 之上(但不仅限于 JVM),它是一种面向对象的语言,融合了许多函数式编程的思想。我不会过多地介绍 Kotlin 的所有特性(PDF,HTML),但我希望重点介绍我发现最有趣的那些特性。
您可以在这篇 Kotlin 2015 摘要 的博文中找到许多有助于提高 Kotlin 知识的有用链接。还可以看看这些简单的 Kotlin 练习,快速了解该语言。
Kotlin 的设计旨在与 Java 生态系统良好协作,在我看来,它与 Spring Boot 拥有相同的务实、创新和固执己见的理念,因此它们可以很好地协同工作。您可以查看这个简单的 Spring Boot + Spring Data JPA Kotlin 项目,更具体地了解它的样子。
Kotlin 凭借其非常简洁的 类 声明语法,可以轻松编写(和阅读)您的领域模型。您可以看到 Kotlin 允许您指定参数的默认值,并且类型在变量/参数名称之后声明。
@Entity
class Customer(
var firstName: String = "",
var lastName: String = "",
@Id @GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0
)
下面看到的 Spring MVC REST 控制器使用了构造函数注入,并且 Kotlin 中的默认可见性是 public,因此无需指定。当函数返回单个表达式时,可以省略花括号,并且主体在 = 符号之后指定。这更好,因为编译器可以推断出返回类型。
@RestController
class CustomerController (val repository:CustomerRepository) {
@GetMapping("/")
fun findAll() = repository.findAll()
@GetMapping("/{name}")
fun findByLastName(@PathVariable name:String)
= repository.findByLastName(name)
}
Spring Data 存储库不言自明。
interface CustomerRepository : CrudRepository<Customer, Long> {
fun findByLastName(name: String): List<Customer>
}
由于 Kotlin 支持顶级函数,您可以像这样简单地声明您的应用程序:
@SpringBootApplication
class Application {
@Bean
fun init(repository: CustomerRepository) = CommandLineRunner {
repository.save(Customer("Jack", "Bauer"))
repository.save(Customer("Chloe", "O'Brian"))
repository.save(Customer("Kim", "Bauer"))
repository.save(Customer("David", "Palmer"))
repository.save(Customer("Michelle", "Dessler"))
}
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
您需要使用 kotlin-spring 插件 来自动使 @Configuration 类以及其他一些 @Service 或 @Repository 成为 open,因为它们在 Spring 中不能是 final 的,这归因于 CGLIB 代理的使用(Kotlin 中的类和方法默认是 final 的,没有 open 修饰符)。使用 JDK 动态代理的 Bean 不需要 open 修饰符。
尽管 Spring Boot 和 Kotlin 配合得很好,但以下附加提示也值得了解。请参阅 此 issue 了解有关改进 Spring Boot 中 Kotlin 支持的更多详细信息。
与 Java 不同,Kotlin 目前不允许将数组注解属性指定为单个值(value 属性除外),因此请注意,您必须编写 @RequestMapping(method = arrayOf(RequestMethod.GET)) 或 @EnableAutoConfiguration(exclude = arrayOf(Foo::class))。
预计此行为将在即将发布的 Kotlin 1.2 中得到改进(有关更多详细信息,请参阅此 Kotlin issue)。Spring Framework 4.3 的复合注解(如 @GetMapping 或 @PostMapping)也可以提供帮助。
我们之前已经看到了如何进行构造函数注入,因为这是推荐的方法(尤其是在 Kotlin 中)。如果您必须执行属性注入,您将不得不使用延迟初始化属性,因为通常,声明为非可空类型的原始属性必须在构造函数中初始化。
@RestController
class CustomerController {
@Autowired
lateinit var repository:CustomerRepository
// ...
}
在 Kotlin 中,$ 用于字符串插值,因此在使用属性占位符时应对其进行转义:@Value("\${some.property}")。作为替代,您也可以使用@ConfigurationProperties,有关更多详细信息,请参阅此Stack Overflow答案。
如果您使用 Jackson,您可能希望添加 com.fasterxml.jackson.module:jackson-module-kotlin 依赖项,以便它能够处理没有默认构造函数或使用 Kotlin 集合的数据类。Spring Framework 4.3+ 会自动注册它。
最后一个提示,IntelliJ IDEA 中的 Java 转 Kotlin 转换器(菜单 Code -> Convert Java file to Kotlin file)在您无法弄清楚如何在 Kotlin 中编写某些内容时非常有用。因此,请不要犹豫,先用 Java 编写一些内容,然后使用它来查找 Kotlin 的对应项。此与 Java 的对比文档也可以提供一些帮助。
我们对您使用 Kotlin 开发 Spring 应用程序的反馈很感兴趣。这篇博文只是一个介绍,还有很多内容可以讨论,尤其是在使用 Spring Boot 和更具 Kotlin 风格的代码(如使用 Exposed SQL 库)方面,敬请期待 **(更新:下一篇 Kotlin 博文现已发布 在此)**……