1. 程式人生 > >Spring Boot 實踐折騰記(14):使用Kotlin

Spring Boot 實踐折騰記(14):使用Kotlin

博爾赫斯說,沒有比思考更復雜的思考了,因此我們樂此不疲。

從Spring Boot 2開始,Boot也開始正式支援Kotlin程式設計,我們可以在建立Spring Boot應用時程式時使用Spring初始化Kotlin,不過Kotlin要在新的Spring 5版本中才得到支援。

Kotlin

Kotlin(https://kotlinlang.org/)是一個基於JVM的靜態型別程式語言,由JetBrains公司(也就是程式設計師現在常用的IDEA工具的公司)定義和開發。 Kotlin的一個關鍵目標是能與Java進行互操作,以便在同一個專案中可以同時使用Java和Kotlin。

先來看一個由Kotlin編寫簡單的Hello World程式,如下程式碼:

fun main(args: Array<String>){
    println("Hello World");
}

在Kotlin中,沒有像Java那樣的static靜態方法,所以我們只能編寫fun聲名符,並將它作為類裡的一個靜態方法來使用才行,後者單獨作為一個函式類來使用。

Classes

Kotlin中的類class與Scala類很相似,它們都有一個類名,並帶有一個主建構函式和一個或多個次要建構函式。

class Person(val firstname: String,val lastname: String) {
    constructor(name: String) : this
(name, "") fun printDetails() = println("FirstName: ${firstname}, LastName: ${lastname}") }

Interfaces

Kotlin中的介面類似於Java 8中的介面,它們都可以包含有具有抽象方法宣告以及預設實現的方法。

interface ReportSender
{
    fun generateReport() : String
    fun sendReport() {
        val report = generateReport()
        println("Report: "
+ report) } }

Data Classes

在Java中,通常我們會使用私有屬性加setter和getter的方式來建立為POJO(普通Java物件)。 然後自定義或由類庫紫星實現實現equals(),hashCode()和toStirng()等方法。而Kotlin是通過使用資料類(Data Classes)來建立這樣的類。比如:

data class Person(val name: String, val email: String)

只需將類宣告為資料類,Kotlin的編譯器就會自動生成equals(),hashCode()和equals()方法。有興趣的同學通過https://kotlinlang.org/docs/reference/瞭解有關Kotlin的更多詳細資訊。

實戰:在Spring Boot中使用Kotlin

好了,我們還是說回Spring Boot,首先,建立一個Spring Boot的應用,引入web-starter依賴:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

我們也可以使用IDE或http://start.spring.io建立Spring Boot應用程式,只是語言型別要選擇Kotlin,們目前IDEA是預設支援建立的。

其次,在建立成功後,我們還需要引入編譯外掛,以Maven為例,需要kotlin-maven-plugin,目的是為了使用src / main / kotlin和src / test / kotlin分別作為主要和測試原始碼資料夾路徑。 見如下POM清單:

dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jre8</artifactId>
    <version>${kotlin.version}</version>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-reflect</artifactId>
    <version>${kotlin.version}</version>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-test</artifactId>
    <version>${kotlin.version}</version>
    <scope>test</scope>
</dependency>
。。。
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <source>src/main/java</source>
                                <source>src/main/kotlin</source>
                            </sourceDirs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <source>src/test/java</source>
                                <source>src/test/kotlin</source>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>

這裡有個小技巧,如果使用的是IDEA,可以選擇工程配置,自動增加maven依賴,kotlin.version我們就選最新的1.2.41。

還有,Kotlin會預設選擇開啟Spring框架的註解支援(比如,用@Configuration註解的類,@Service,@Component,@Repository等),但並不是必須的,可以根據選擇引入。這裡要特別注意一點,如果想在Kotlin中建立一個非final的類,我們則需要在類中新增open修飾符,比如:

open class Application {
}

比如,我們通常會使用的註釋類 ,@Component,@Async,@Transactional和@ Cacheable ,@Configuration,@Controller,@RestController,@Service和@ Repository等等,這些類在Kotlin中都會自動開啟。 這些配置在初始化過程中,都會被kotlin-spring外掛預設配置。

第一步,建立一個Rest API控制器HomeController.kt,如下所示:

@RestController
class ManController(val manService:ManService) {

    @GetMapping("/ok")
    fun home(): String {
        val man = manService.findByName("mickjoust")
        return "ok ==> kotlin"+"name:"+man.name
    }

}

第二步:建立示例類Man.kt,如下所示:

class Man(
        var id: Int = -1,
        var name: String = "",
        var email: String = ""
) {
    override fun toString(): String {
        return "Man(id=$id, name='$name', email='$email')"
    }
}

注意,因為語法差異,主建構函式是直接寫在類名後,用()表示,過載toString()語法也不同,可以使用IDE自動生成。

第三步,我們建立一個簡單的查詢服務,包含一個介面定義類ManService.kt和介面實現類,程式碼如下:

interface ManService  {
    fun findByName(name: String): Man
}
@Service
class ManServiceImpl : ManService {
    override fun findByName(name: String): Man {
        return Man(1,name,"12323131313")
    }
}

最後一步,建立主啟動類BootKotlinApp.kt,如下所示:

@SpringBootApplication
class BootKotlinApp fun main(args: Array<String>) {

    SpringApplication.run(BootKotlinApp::class.java, *args);

}

以上程式碼中,我們將main()方法建立為頂級函式。這點和java裡的static有一點區別。到這裡,執行會報錯!錯誤為:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
@Configuration class ‘BootKotlinApp’ may not be final.
Remove the final modifier to continue.

我們注意到@Configuration因為使用了final,前面我們說到,在kotlin中預設類都有final標示,要建立需要使用open欄位,我們需要加上,這點和java也是有區別的。修改為:

open class BootKotlinApp fun main(args: Array<String>) {

重新執行,成功! 訪問hlocalhost:8080/ok,返回:

ok ==> kotlinname:mickjoust

小結

本文主要討論瞭如何使用基於JVM的語言Kotlin建立Spring Boot應用程式,Kotlin現在越來越受到更多人的使用,也成為了安卓開發的有利工具,對於後端開發可能涉及較少,但是,每一次實戰都可以增強我們的動手能力,這才是最重要的。

參考資源