搭建SpringBoot2.x Kotlin开发环境

Kotlin简介:Kotlin是一个基于JVM的静态类型编程语言,由JetBrains设计开发并开源。Kotlin能够与Java进行完全的交互,可以在同一个项目中同时使用Java和Kotlin。并且支持多种平台,包括移动端、服务端以及浏览器端,Kotlin已正式成为Android官方支持开发语言。
Spring Framework 5.0版本中已经正式支持Kotlin语言,SpringBoot从SpringBoot2开始也正式支持Kotlin。

最近刚开始学习Kotlin,也踩了一些坑,顺便总结一下基于kotlin开发的SpringBoot2.x环境搭建。

一、环境准备

  • 开发工具:idea 2019
  • 项目构建工具:Maven 3.6.1
  • JDK:1.8.0_181
  • SpringBoot:2.2.2.RELEASE
  • Kotlin:1.3.61

二、构建项目

这里直接通过Maven构建一个java项目,然后对pom文件进行修改,添加kotlin相关依赖和插件,完整的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rtxtitanv</groupId>
    <artifactId>springboot-kotlin</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>springboot-kotlin</name>
    <description>SpringBoot2.x kotlin 开发环境</description>

    <parent>
        <!-- SpringBoot 起步依赖 -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- 增量编译:为了使构建更快,为Maven启用增量编译 也可以使用 -Dkotlin.compiler.incremental=true 选项运行构建 -->
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <java.version>1.8</java.version>
        <kotlin.version>1.3.61</kotlin.version>
    </properties>

    <dependencies>
        <!-- SpringBoot Web 起步依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- jackson kotlin 包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <!-- kotlin反射包 -->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <!-- kotlin jdk8核心库 -->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>
        <!-- 单元测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <!-- 编译只有Kotlin的源代码时指定源代码目录 使用maven构建项目时是java
        注意源代码目录与指定一致,这里改成kotlin -->
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- kotlin-maven-plugin 插件 -->
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <configuration>
                    <args>
                        <!-- 负责检查对JSR-305注解的支持 -->
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <compilerPlugins>
                        <!-- Kotlin的类默认都是final的,启用kotlin-spring编译器插件
                        该插件指定了以下注解:@Component、@Async、@Transactional、@Cacheable以及@SpringBootTest。
                        由于元注解的支持,标注有@Configuration、@Controller、@RestController、@Service或者@Repository
                        的类会自动添加open,因为这些注解标注有元注解@Component -->
                        <plugin>spring</plugin>
                        <!-- 无参(no-arg)编译器插件为具有特定注解的类生成一个额外的零参数构造函数
                        这个生成的构造函数是合成的,因此不能从Java或Kotlin中直接调用,但可以使用反射调用。
                        对于JPA支持用“jpa”插件 -->
                        <plugin>no-arg</plugin>
                    </compilerPlugins>
                    <pluginOptions>
                        <!-- 指定应用no-arg插件的自定义注解 -->
                        <option>no-arg:annotation=com.rtxtitanv.annotation.KtNoArgsConstructor</option>
                    </pluginOptions>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-noarg</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals> <goal>compile</goal> </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals> <goal>test-compile</goal> </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

项目结构如下:
在这里插入图片描述
编写主启动类,一个最简单的基于Kotlin的SpringBoot项目就构建完成了。

package com.rtxtitanv

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

/**
 * @name com.rtxtitanv.KotlinApplication
 * @description 主启动类
 * @author rtxtitanv
 * @date 2020/1/16 14:48
 * @version 1.0.0
 */
@SpringBootApplication
class KotlinApplication

fun main(args: Array<String>) {
    runApplication<KotlinApplication>(*args)
}

三、使用测试

进行一些简单的测试,看能否正常使用Kotlin开发SpringBoot应用。

1.数据模型类

这里使用Data数据类,一般情况下编译器会自动生成equals()、 hashCode()、toString()等函数,至于getter和setter,没有显示定义Kotlin会默认自动生成。

package com.rtxtitanv.model

import com.rtxtitanv.annotation.KtNoArgsConstructor

/**
 * @name com.rtxtitanv.model.User
 * @description 用户实体类
 * @author rtxtitanv
 * @date 2020/1/16 16:07
 * @version 1.0.0
 */
@KtNoArgsConstructor
data class User(var id: Long? = null,// ?表示声明为Nullable变量
                var userName: String? = null,
                var passWord: String? = null,
                var nickName: String? = null,
                var age: Int? = null,
                var tel: String? = null,
                var addr: String? = null)

自定义如下注解主要用于Kotlin的no-arg插件,指定该注解应用于no-arg插件,即注解有该注解的类。no-arg插件会为其自动添加无参构造函数,不过该无参构造函数只能通过反射调用,如果User类主构造函数中初始化了属性值,则可以通过User()调用无参构造函数,省略no-args插件也可以,也可以反射调用无参构造函数。

package com.rtxtitanv.annotation

/**
 * @name com.rtxtitanv.annotation.KtNoArgsConstructor
 * @description kotlin自定义无参构造器注解
 * @author rtxtitanv
 * @date 2020/1/16 16:57
 * @version 1.0.0
 */
annotation class KtNoArgsConstructor

2.单元测试

package com.rtxtitanv

import com.rtxtitanv.model.User
import org.junit.Test
import org.junit.runner.RunWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

/**
 * @name com.rtxtitanv.KotlinTest
 * @description 单元测试类
 * @author rtxtitanv
 * @date 2020/1/16 15:33
 * @version 1.0.0
 */
@RunWith(SpringRunner::class)
@SpringBootTest(classes = [KotlinApplication::class])
class KotlinTest {

    private val logger: Logger = LoggerFactory.getLogger(KotlinTest::class.java)

    @Test
    fun kotlinTest() {
        // 通过反射调用自动生成的无参构造函数
        val user1 = User::class.java.newInstance()
        // 在User类主构造函数中初始化了属性值,则可以通过User()调用无参构造函数,省略no-args插件也可以,也可以反射调用
        // 如果没有在主构造函数中初始化属性值,则不能通过User()显式调用无参构造函数,必须要加上应用no-args插件的注解
        // 且通过反射调用
        val user2 = User()
        logger.info("user1: " + user1.toString())
        logger.info("user2: " + user2.toString())
    }
}

控制台打印的日志说明自动生成了无参构造函数。

2020-01-17 21:39:21.172  INFO 15164 --- [           main] com.rtxtitanv.KotlinTest                 : user1: User(id=null, userName=null, passWord=null, nickName=null, age=null, tel=null, addr=null)
2020-01-17 21:39:21.172  INFO 15164 --- [           main] com.rtxtitanv.KotlinTest                 : user2: User(id=null, userName=null, passWord=null, nickName=null, age=null, tel=null, addr=null)

3.service层

这里省去了数据层,数据为手动模拟的,主要用于控制层返回数据测试。

package com.rtxtitanv.service

import com.rtxtitanv.model.User

/**
 * @name com.rtxtitanv.service.KotlinService
 * @description KotlinService接口
 * @author rtxtitanv
 * @date 2020/1/16 17:06
 * @version 1.0.0
 */
interface KotlinService {

    /**
     * 根据年龄查询用户
     */
    fun findUserByAge(age: Int): List<User>
}
package com.rtxtitanv.service.impl

import com.rtxtitanv.model.User
import com.rtxtitanv.service.KotlinService
import org.springframework.stereotype.Service

/**
 * @name com.rtxtitanv.service.impl.KotlinServiceImpl
 * @description KotlinService实现类
 * @author rtxtitanv
 * @date 2020/1/16 17:07
 * @version 1.0.0
 */
@Service
class KotlinServiceImpl : KotlinService {
    /**
     * 模拟根据年龄查询用户,只是测试,返回写死的user数据
     */
    override fun findUserByAge(age: Int): List<User> {
        val user1 = User(1L, "aaa",
                "123456", "abc",
                age, "198658632", "北京")
        val user2 = User(2L, "bbb",
                "111222", "cba",
                age, "15963247851", "上海")
        val userList = ArrayList<User>()
        userList.add(user1)
        userList.add(user2)
        return userList
    }
}

4.controller层

package com.rtxtitanv.controller

import com.rtxtitanv.model.User
import com.rtxtitanv.service.KotlinService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

/**
 * @name com.rtxtitanv.controller.KotlinController
 * @description KotlinController
 * @author rtxtitanv
 * @date 2020/1/16 14:59
 * @version 1.0.0
 */
@RequestMapping("/kotlin")
@RestController
class KotlinController(private val kotlinService: KotlinService) {
    /**
     * springboot2.x kotlin开发环境测试
     */
    @GetMapping("/test")
    fun helloKotlin(): String {
        return "hello kotlin!"
    }

    /**
     * 根据年龄查询用户
     */
    @GetMapping("/user/{age}")
    fun findUser(@PathVariable age: Int): List<User> {
        return kotlinService.findUserByAge(age)
    }
}

访问localhost:8080/kotlin/test
访问localhost:8080/kotlin/test结果
访问localhost:8080/kotlin/user/25
访问localhost:8080/kotlin/user/25结果
能正常返回json数据,说明一个基于Kotlin的简单SpringBoot2.x开发环境就搭建完成了。可以看出Kotlin非常适合开发服务器端应用程序,可以编写出简明且表现力强的代码,同时保持与现有基于Java的技术栈的完全兼容性,所以Kotlin还是有必要学习和掌握的。

代码示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RtxTitanV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值