使用 Kotlin 开发的 Spring Boot2

服务器端的Kotlin很受欢迎呢!(?)
由于Kotlin的框架处于早期阶段,我认为选择Java的框架可能更好。
提到Java的框架,就不得不说Spring Framework呢。
我尝试了用Kotlin做Spring Boot 2。

我将创建一个从数据库中获取数据并返回的RestAPI,用于示例。

创建项目

Spring Initializr.png

使用IntelliJ IDEA等工具打开已下载的项目。

如果您希望在AP服务器上使用Jetty而不是Tomcat,则可以在dependencies中添加Jetty并排除spring-boot-starter-web中包含的Tomcat。

implementation('org.springframework.boot:spring-boot-starter-jetty')
configurations {
    implementation.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}

因为我们已经安装了jdbc,所以在启动时需要驱动程序。请将其添加到依赖项中。

runtime('com.h2database:h2')

如果您希望使用application.yml而不是application.properties,也可以这样做:请删除application.properties并创建一个名为application.yml的文件。

## 例です
logging:
  level:
    root: warn
    org:
      springframework:
        web: info
spring:
  main:
    banner-mode: "off"

创建控制器

首先,我们将创建一个简单的API。
您可以自由使用该API,不需要担心注释。

import com.fasterxml.jackson.annotation.JsonProperty
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping(value = ["/api"])
class DemoRestController {

    @GetMapping(
            value = ["/"],
            produces = [MediaType.APPLICATION_JSON_VALUE]
            )
    fun index(): IndexJson {
        return IndexJson("hogehoge", 12345)
    }
}

data class IndexJson(
        @JsonProperty(value = "name") val name: String,
        @JsonProperty(value = "no") val no: Int
)

返回的只是原样的 Data Class,所以非常方便呢。

开始

$ ./gradlew bootRun
$ curl -D - http://localhost:8080/api/
HTTP/1.1 200 OK
Date: Wed, 19 Dec 2018 10:30:50 GMT
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked

{"name":"hogehoge","no":12345}

好的,返回的是Json格式的数据。

数据库连接

我要添加H2的定义。

spring:
  main:
    banner-mode: "off"
  datasource:
    url: jdbc:h2:/tmp/h2/demo
    username: sa
    password:
  h2:
    console:
      enabled: true

如果重新启动应用程序,H2的Web控制台将启动。
您可以通过”http://localhost:8080/h2-console/”访问控制台。

スクリーンショット 2018-12-19 20.08.08.png
スクリーンショット 2018-12-19 22.16.17.png

请登录后,将会显示一个可以执行SQL的页面。请随意创建并注册表格和数据。

create table test (
  name varchar2(10),
  no int
);

insert into test values ('hoge1', 10);
insert into test values ('hoge2', 20);
insert into test values ('hoge3', 30);

仓库、服务

创建一个从数据库表中获取数据的Repository和Service。

data class User(val name: String, val no:Int)
interface DemoRepository {
    fun all(): List<User>
    fun findByName(name: String): User
}
import com.example.demo.repository.DemoRepository
import com.example.demo.repository.User
import org.springframework.jdbc.core.RowMapper
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
import org.springframework.stereotype.Repository

@Repository
class JdbcDemoRepository(private val jdbcTemplate: NamedParameterJdbcTemplate) : DemoRepository {

    private val rowMapper = RowMapper<User> { rs, _ ->
        User(
                rs.getString("name"),
                rs.getInt("no")
        )
    }

    override fun all(): List<User> =
        jdbcTemplate.query("select name, no from test", rowMapper)

    override fun findByName(name: String): User {
        val res = jdbcTemplate.query(
                "select name, no from test where name = :targetName",
                MapSqlParameterSource().addValue("targetName", name),
                rowMapper
        )

        return res.requireNoNulls()[0]
    }
}
import com.example.demo.repository.User

interface DemoService {
    fun findUser(name: String): User
}
import com.example.demo.repository.DemoRepository
import com.example.demo.repository.User
import com.example.demo.service.DemoService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

@Service
class DemoServiceImpl(@Autowired var repository: DemoRepository): DemoService {
    override fun findUser(name: String): User = repository.findByName(name)
}

我将修改最初创建的控制器。

import com.example.demo.service.DemoService
import com.fasterxml.jackson.annotation.JsonProperty
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.validation.annotation.Validated
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
import javax.validation.Valid
import javax.validation.constraints.NotBlank

@Validated
@RestController
@RequestMapping(value = ["/api"])
class DemoRestController {

    @Autowired
    lateinit var service: DemoService

    @GetMapping(
            value = ["/{name}"],
            produces = [MediaType.APPLICATION_JSON_VALUE]
            )
    fun index(@PathVariable("name") @Valid @NotBlank userName: String): IndexJson {
        val user= service.findUser(userName)
        return IndexJson(user.name, user.no)
    }
}

data class IndexJson(
        @JsonProperty(value = "name") val name: String,
        @JsonProperty(value = "no") val no: Int
)

我将重新启动并尝试调用API。

$ curl http://localhost:8080/api/hoge1
{"name":"hoge1","no":10}
$ curl http://localhost:8080/api/hoge2
{"name":"hoge2","no":20}

我的感受

我在使用时几乎没有遇到任何困难。
说到Spring,依赖注入是其中的一部分,但在使用Kotlin时,我对如何声明属性部分感到困惑,并且对构造函数的写法也不太熟悉。

让我们继续使用 Kotlin,我对此的想法变得更加坚定了。让我们享受 Kotlin 的乐趣吧!

广告
将在 10 秒后关闭
bannerAds