領先一步
VMware 提供培訓和認證,助你加速進步。
瞭解更多更新:一份全面的Spring Boot + Kotlin 教程現已推出。
恰逢Kotlin 1.0 版本釋出之際,我們正在向https://start.spring.io新增 Kotlin 語言支援,以便更輕鬆地使用這種語言啟動新的 Spring Boot 專案。
這篇部落格文章也是一個機會,讓我解釋為什麼我覺得這種語言很有趣,向你詳細展示一個示例專案,並給你一些提示。
Kotlin 是由 JetBrains 建立的一種語言。它執行在 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 Repository 是不言自明的
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 中,由於使用了 CGLIB 代理,它們不能是 final
(在 Kotlin 中,如果沒有 open
修飾符,類和方法預設是 final
的)。使用 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 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 部落格文章現已釋出,請點選此處檢視)...