使用 Kotlin、Spring Boot、Mysql、JPA 和 Hibernate 构建 Restful API

x33g5p2x  于11个月前 转载在 Spring  
字(6.4k)|赞(0)|评价(0)|浏览(172)

由于其生产力特性和 Android 中的一流支持,Kotlin 近来广受欢迎。

由于 Kotlin 的日益流行,Spring 框架 5 还引入了在 Spring 应用程序中对 Kotlin 的专门支持。

在本文中,您将学习如何使用 Kotlin 和基于 Spring 框架 5 的 Spring Boot 2.x 构建 Restful CRUD API。

所以请继续关注!

我们将建造什么?

在这篇博文中,我们将为一个迷你博客应用程序构建 Restful API。该博客有一个文章列表。我们将编写用于创建、检索、更新和删除 文章 的 API。一篇文章有​​一个 id、一个 title 和一些 content

我们将使用 MySQL 作为我们的数据源,并使用 JPA 和 Hibernate 来访问数据库中的数据。

好的,现在让我们创建应用程序。

创建应用程序

我们将使用 Spring initializr web 工具来引导我们的应用程序。按照以下步骤生成应用程序:

  1. 前往http://start.spring.io
    1.在语言部分选择Kotlin
  2. 输入 Artifact 作为 kotlin-demo
    1.设置包名com.example.kotlindemo
  3. 添加WebJPAMySQLValidation依赖。
  4. 点击Generate生成并下载项目。

项目生成后,将其解压缩并将其导入您喜欢的 IDE。这是项目的目录结构供您参考。

配置 MySQL

我们需要配置 MySQL 数据库 url、用户名和密码,以便 Spring Boot 可以创建数据源。

打开 src/main/resources/application.properties 文件并向其添加以下属性 -

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/kotlin_demo_app?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root


## Hibernate Properties

# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

请不要忘记根据您的 MySQL 安装更改 spring.datasource.usernamespring.datasource.password

请注意,我已将 spring.jpa.hibernate.ddl-auto 属性设置为 update。每当您在应用程序中创建或修改域模型时,此属性都会更新数据库架构。

创建领域模型

现在让我们创建 Article 域实体。在 com.example.kotlindemo 包中创建一个名为 model 的新包,然后创建一个名为 Article.kt 的新 Kotlin 文件,内容如下——

package com.example.kotlindemo.model

import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.validation.constraints.NotBlank

@Entity
data class Article (
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @get: NotBlank
    val title: String = "",

    @get: NotBlank
    val content: String = ""
)

Entity 类是如此的小而简洁,对吧?这是因为 Kotlin 类不需要像 Java 那样的 getter 和 setter。此外,我在这里使用了 data class 。数据类会自动生成 equals()hashcode()toString()copy() 方法。

请注意,我为 Article 类中的所有字段分配了一个默认值。这是必需的,因为 Hibernate 要求实体具有无参数构造函数。

为所有成员字段分配默认值将使 hibernate 实例化 Article 而不传递任何参数。它有效是因为 Kotlin 支持默认参数 :)。

创建存储库

现在让我们创建用于从数据库访问数据的存储库。首先,在 com.example.kotlindemo 包中创建一个名为 repository 的包,然后创建一个名为 ArticleRepository.kt 的 Kotlin 文件,内容如下——

package com.example.kotlindemo.repository

import com.example.kotlindemo.model.Article
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface ArticleRepository : JpaRepository<Article, Long>

这就是我们需要在这里做的所有事情。由于我们已经从 JpaRepository 接口扩展了 ArticleRepository,我们可以轻松使用 Article 实体上的所有 CRUD 方法。 Spring Boot 在运行时自动插入一个名为 SimpleJpaRepositoryJpaRepository 的默认实现。

创建控制器端点

最后,让我们为 Article 实体上的所有 CRUD 操作创建控制器端点。

首先,在 com.example.kotlindemo 包内创建一个名为 controller 的新包,然后在 controller 包内创建一个名为 ArticleController.kt 的新 kotlin 文件,其内容如下:

package com.example.kotlindemo.controller

import com.example.kotlindemo.model.Article
import com.example.kotlindemo.repository.ArticleRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import java.util.*
import javax.validation.Valid

@RestController
@RequestMapping("/api")
class ArticleController(private val articleRepository: ArticleRepository) {

    @GetMapping("/articles")
    fun getAllArticles(): List<Article> =
            articleRepository.findAll()


    @PostMapping("/articles")
    fun createNewArticle(@Valid @RequestBody article: Article): Article =
            articleRepository.save(article)


    @GetMapping("/articles/{id}")
    fun getArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Article> {
        return articleRepository.findById(articleId).map { article -> 
            ResponseEntity.ok(article)
        }.orElse(ResponseEntity.notFound().build())
    }

    @PutMapping("/articles/{id}")
    fun updateArticleById(@PathVariable(value = "id") articleId: Long,
                          @Valid @RequestBody newArticle: Article): ResponseEntity<Article> {

        return articleRepository.findById(articleId).map { existingArticle ->
            val updatedArticle: Article = existingArticle
                    .copy(title = newArticle.title, content = newArticle.content)
            ResponseEntity.ok().body(articleRepository.save(updatedArticle))
        }.orElse(ResponseEntity.notFound().build())

    }

    @DeleteMapping("/articles/{id}")
    fun deleteArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Void> {

        return articleRepository.findById(articleId).map { article  ->
            articleRepository.delete(article)
            ResponseEntity<Void>(HttpStatus.OK)
        }.orElse(ResponseEntity.notFound().build())

    }
}

控制器为所有 CRUD 操作定义 API。我在所有方法中都使用了 Kotlin 的函数式语法,使它们简短明了。

运行应用程序

您可以通过在终端中键入以下命令来运行该应用程序 -

mvn spring-boot:run

该应用程序将在 Spring Boot 的默认端口 8080 上启动。

探索 Rest API

1. POST /api/articles - 创建文章

curl -i -H "Content-Type: application/json" -X POST \
-d '{"title": "How to learn Spring framework", "content": "Resources to learn Spring framework"}' \
http://localhost:8080/api/articles

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:59 GMT

{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}

2. GET /api/articles - 获取所有文章

curl -i -H 'Accept: application/json' http://localhost:8080/api/articles

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:29 GMT

[{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}]

3. Get /api/articles/{id} - 通过 id 获取文章

curl -i -H 'Accept: application/json' http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:27:51 GMT

{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}

4. PUT /api/articles/{id} - 更新文章

curl -i -H "Content-Type: application/json" -X PUT \
-d '{"title": "Learning Spring Boot", "content": "Some resources to learn Spring Boot"}' \
http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:33:15 GMT

{"id":1,"title":"Learning Spring Boot","content":"Some resources to learn Spring Boot"}

5. DELETE /api/articles/{id} - 删除文章

curl -i -X DELETE http://localhost:8080/api/articles/1

# Output
HTTP/1.1 200 
Content-Length: 0
Date: Fri, 06 Oct 2017 03:34:22 GMT

相关文章

热门文章

更多