使用 Kotlin 開發 Spring Boot 應用程式

工程 | Sébastien Deleuze | 2016 年 2 月 15 日 | ...

更新:一份完整的 Spring Boot + Kotlin 教學 已經推出。

適逢 Kotlin 1.0 發布,我們正在 https://start.spring.io 中加入對 Kotlin 語言的支援,以便更容易使用此語言啟動新的 Spring Boot 專案。

這篇部落格文章也是我解釋我為何覺得這種語言有趣、詳細展示一個範例專案並提供一些訣竅的機會。

什麼是 Kotlin?

Kotlin 是由 JetBrains 建立的語言。它執行在 JVM 之上 (但不限於此),它是一種物件導向語言,其中包含許多來自函數式程式設計的想法。我不會過多地介紹所有 Kotlin 功能(PDF, HTML),但我想要強調我認為最有趣的功能

  • Kotlin 是一種靜態類型語言,但由於其 聰明的類型推斷,它允許您編寫程式碼,像動態語言一樣簡短而富有表現力,並且性能接近純 Java 專案
  • 屬性支援
  • 與其他語言相比,相對輕量級的標準函式庫
  • 易於學習:Java 開發人員可以快速理解大多數語言(這份 與 Java 的快速比較 值得閱讀)
  • Java 互通性 是一個首要考量且非常好
  • 非常適合 Android 開發
  • 內建不變性和 空值安全 支援
  • 程式碼易於閱讀,編寫效率高
  • 允許 擴展現有函式庫,而無需繼承該類別或使用任何類型的設計模式,例如 Decorator
  • 不需要分號 ;-)

您將在此 Kotlin digest 2015 部落格文章中找到許多有用的連結,以提升您的 Kotlin 知識。 另請參閱這些簡單的 Kotlin 練習,以快速了解該語言。

一個 Spring Boot + 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,因為由於 CGLIB Proxy 的使用,它們在 Spring 中不能是 final(Kotlin 中的類別和方法預設為 final,而沒有 open 修飾符)。 使用 JDK 動態 Proxy 的 Beans 不需要 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 Kotlin 模組

如果您正在使用 Jackson,您可能會想要新增 com.fasterxml.jackson.module:jackson-module-kotlin 相依性,以便讓它能夠處理沒有預設建構子或 Kotlin 集合的資料類別。 它會由 Spring Framework 4.3+ 自動註冊。

使用 Java 轉 Kotlin 轉換器進行實驗

最後一個提示,IntelliJ IDEA 中提供的 Java 轉 Kotlin 轉換器(選單 Code -> Convert Java file to Kotlin file)在您無法弄清楚如何用 Kotlin 撰寫程式碼時非常有用。 因此,請不要猶豫先用 Java 撰寫一些程式碼,然後使用它來找到 Kotlin 的對應程式碼。 此 與 Java 的比較文件 也可以提供一些幫助。

意見回饋

我們對您使用 Kotlin 開發 Spring 應用程式的意見回饋很感興趣。 這篇部落格文章只是一個介紹,還有很多可以說的,特別是關於使用 Spring Boot 和更多 Kotlin 慣用程式碼,例如使用 Exposed SQL 函式庫,所以請繼續關注(更新:下一篇 Kotlin 部落格文章現在已發布在此...

取得 Spring 電子報

與 Spring 電子報保持聯繫

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部