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

示例代码:boot-cache

小结

本文主要讨论了如何使用基于JVM的语言Kotlin创建Spring Boot应用程序,Kotlin现在越来越受到更多人的使用,也成为了安卓开发的有利工具,对于后端开发可能涉及较少,但是,每一次实战都可以增强我们的动手能力,这才是最重要的。

参考资源

1、https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0
2、https://kotlinlang.org/docs/reference/

猜你喜欢

转载自blog.csdn.net/mickjoust/article/details/80267502