使用 Kotlin 开发的 Spring Boot2
服务器端的Kotlin很受欢迎呢!(?)
由于Kotlin的框架处于早期阶段,我认为选择Java的框架可能更好。
提到Java的框架,就不得不说Spring Framework呢。
我尝试了用Kotlin做Spring Boot 2。
我将创建一个从数据库中获取数据并返回的RestAPI,用于示例。
创建项目
使用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/”访问控制台。
请登录后,将会显示一个可以执行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 的乐趣吧!