领先一步
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`,因为由于 CGLIB 代理的使用,它们在 Spring 中不能是`final`(Kotlin 中的类和方法默认为`final`,没有`open`修饰符)。使用 JDK 动态代理的 Bean 不需要`open`修饰符。
即使 Spring Boot 和 Kotlin 可以很好地协同工作,这些额外的提示也值得了解。有关详细信息,请参阅关于改进 Spring Boot 中 Kotlin 支持的此问题。
与 Java 不同,Kotlin 目前不允许将数组注解属性指定为单个值(`value`属性除外),因此请注意,您必须编写`@RequestMapping(method = arrayOf(RequestMethod.GET))`或`@EnableAutoConfiguration(exclude = arrayOf(Foo::class))`。
此行为有望在即将推出的 Kotlin 1.2 中得到改进(有关详细信息,请参阅此 Kotlin 问题)。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 转换器(菜单 代码 -> 将 Java 文件转换为 Kotlin 文件)在你不知道如何用 Kotlin 编写某些内容时非常有用。因此,不要犹豫,先用 Java 编写一些代码,然后用它来查找 Kotlin 的对应代码。这份与 Java 的对比文档也可以提供一些帮助。
我们非常关注您关于使用 Kotlin 开发 Spring 应用程序的反馈。这篇博文只是一个介绍,还有很多内容需要讲述,特别是关于使用 Spring Boot 和更符合 Kotlin 风格的代码(例如使用Exposed SQL 库),敬请关注(更新:下一篇 Kotlin 博文现已上线)……