Kotlin学习笔记(13)--搭建Kotlin+SpringBoot项目

创建项目

使用 Spring Boot Starter 创建项目,创建地址:https://start.spring.io/。

配置如下:
image

pom.xml 文件

<?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>  
    <parent>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-parent</artifactId>  
        <version>3.3.4</version>  
        <relativePath/> <!-- lookup parent from repository -->  
    </parent>  
    <groupId>com.example</groupId>  
    <artifactId>kotlin-spring-demo</artifactId>  
    <version>0.0.1-SNAPSHOT</version>  
    <name>kotlin-spring-demo</name>  
    <description>Demo project for Spring Boot and Kotlin</description>  
  
    <properties>  
        <java.version>17</java.version>  
        <kotlin.version>1.9.25</kotlin.version>  
        <jackson.version>2.17.2</jackson.version>  
    </properties>  
  
    <repositories>  
        <repository>  
            <id>spring-repo</id>  
            <url>https://repo.spring.io/release</url>  
        </repository>  
    </repositories>  
  
    <dependencies>  
	    <!-- spring boot -->
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-data-jpa</artifactId>  
        </dependency>  
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-data-redis</artifactId>  
        </dependency>  
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-web</artifactId>  
        </dependency>

		<!-- kotlin -->
        <dependency>  
            <groupId>com.fasterxml.jackson.module</groupId>  
            <artifactId>jackson-module-kotlin</artifactId>  
        </dependency>  
        <dependency>  
            <groupId>org.jetbrains.kotlin</groupId>  
            <artifactId>kotlin-reflect</artifactId>  
        </dependency>  
        <dependency>  
            <groupId>org.jetbrains.kotlin</groupId>  
            <artifactId>kotlin-stdlib</artifactId>  
        </dependency>  
        <dependency>  
            <groupId>org.jetbrains.kotlin</groupId>  
            <artifactId>kotlin-allopen</artifactId>  
            <version>${kotlin.version}</version>  
        </dependency>
	    
	    <!-- jackson -->
        <dependency>  
            <groupId>com.fasterxml.jackson.module</groupId>  
            <artifactId>jackson-module-kotlin</artifactId>  
            <version>${jackson.version}</version>  
        </dependency>  

		<!-- mysql -->
        <dependency>  
            <groupId>com.mysql</groupId>  
            <artifactId>mysql-connector-j</artifactId>  
            <scope>runtime</scope>  
        </dependency>
		
		<!-- test -->
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-test</artifactId>  
            <scope>test</scope>  
        </dependency>  
        <dependency>  
            <groupId>org.jetbrains.kotlin</groupId>  
            <artifactId>kotlin-test-junit5</artifactId>  
            <scope>test</scope>  
        </dependency>  
    </dependencies>  
  
    <build>  
        <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>  
            <plugin>  
                <groupId>org.jetbrains.kotlin</groupId>  
                <artifactId>kotlin-maven-plugin</artifactId>  
                <configuration>  
                    <args>  
                        <arg>-Xjsr305=strict</arg>  
                    </args>  
                    <compilerPlugins>  
                        <plugin>spring</plugin>  
                        <plugin>jpa</plugin>  
                        <plugin>all-open</plugin>  
                    </compilerPlugins>  
                    <pluginOptions>  
                        <option>all-open:annotation=jakarta.persistence.Entity</option>  
                        <option>all-open:annotation=jakarta.persistence.MappedSuperclass</option>  
                        <option>all-open:annotation=jakarta.persistence.Embeddable</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>  
            </plugin>  
        </plugins>  
    </build>  
  
</project>

配置 MySQL 和 Redis 连接

src/main/resources/application.yml 中配置 MySQLRedis 连接。

spring:
  datasource:
    url: jdbc:mysql://localhost:13306/test_db?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true
  redis:
    host: localhost
    port: 6379
  cache:
    type: redis

# 服务器端口
server:
  port: 8080

编写主应用程序类

src/main/kotlin/demo 目录下创建 DemoApplication.kt

package demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.cache.annotation.EnableCaching

@SpringBootApplication
@EnableCaching
class DemoApplication

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

配置缓存

src/main/kotlin/demo 目录下创建 CacheConfig.kt

package demo  
  
import com.fasterxml.jackson.databind.ObjectMapper  
import com.fasterxml.jackson.databind.module.SimpleModule  
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer  
import com.fasterxml.jackson.module.kotlin.registerKotlinModule  
import org.springframework.cache.CacheManager  
import org.springframework.cache.annotation.EnableCaching  
import org.springframework.context.annotation.Bean  
import org.springframework.context.annotation.Configuration  
import org.springframework.data.redis.cache.RedisCacheConfiguration  
import org.springframework.data.redis.cache.RedisCacheManager  
import org.springframework.data.redis.connection.RedisConnectionFactory  
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer  
import org.springframework.data.redis.serializer.RedisSerializationContext  
import org.springframework.data.redis.serializer.StringRedisSerializer  
import java.time.Duration  
  
@Configuration  
@EnableCaching  
class CacheConfig {  
  
    @Bean  
    fun cacheManager(redisConnectionFactory: RedisConnectionFactory): CacheManager {  
  
        val objectMapper = ObjectMapper().registerKotlinModule()  
  
        // 创建 Jackson 序列化器  
        val jackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(objectMapper, User::class.java)  
  
  
        val cacheConfig = RedisCacheConfiguration.defaultCacheConfig()  
            .entryTtl(Duration.ofMinutes(60)) // 缓存有效期  
            .disableCachingNullValues()  
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer()))  
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))  
  
        return RedisCacheManager.builder(redisConnectionFactory)  
            .cacheDefaults(cacheConfig)  
            .build()  
    }  
}
  • 设置 Redis 作为缓存管理器,并将缓存的默认过期时间设置为 60 分钟。

创建实体类

src/main/kotlin/demo 目录下创建 User.kt

package demo

import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id

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

    val name: String,

    val email: String
)

创建仓库接口

src/main/kotlin/demo 目录下创建 UserRepository.kt

package demo

import com.example.entity.User
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface UserRepository : JpaRepository<User, Long> {
    fun findByEmail(email: String): User?
}

创建服务类并使用缓存

src/main/kotlin/demo 目录下创建 UserService.kt

package demo

import com.example.entity.User
import com.example.repository.UserRepository
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class UserService(private val userRepository: UserRepository) {

    @Cacheable(value = ["users"], key = "#email")
    fun getUserByEmail(email: String): User? {
        println("Fetching user from database for email: $email")
        return userRepository.findByEmail(email)
    }

    @Transactional
    fun createUser(name: String, email: String): User {
        val user = User(name = name, email = email)
        return userRepository.save(user)
    }
}
  • @Cacheable 注解用于将 getUserByEmail 方法的结果缓存到 Redis 中。首次调用时会从数据库获取数据并缓存,之后相同的请求会直接从缓存中获取。
  • value = ["users"] 指定了缓存的名称。

创建控制器

src/main/kotlin/demo 目录下创建 UserController.kt

package demo

import com.example.service.UserService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/users")
class UserController(private val userService: UserService) {

    @GetMapping("/{email}")
    fun getUser(@PathVariable email: String): ResponseEntity<Any> {
        val user = userService.getUserByEmail(email)
        return if (user != null) {
            ResponseEntity.ok(user)
        } else {
            ResponseEntity.notFound().build()
        }
    }

    @PostMapping
    fun createUser(@RequestParam name: String, @RequestParam email: String): ResponseEntity<Any> {
        val user = userService.createUser(name, email)
        return ResponseEntity.ok(user)
    }
}

初始化数据库

在 MySQL 创建数据库:

CREATE DATABASE test_db CHARACTER SET utf8 COLLATE utf8_general_ci;

src/main/resources 目录下创建 schema.sql 文件

CREATE TABLE IF NOT EXISTS user (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE
);
  • Spring Boot 的 spring.jpa.hibernate.ddl-auto=update 属性会自动创建和更新表结构。

运行项目

确保 MySQL 和 Redis 服务正在运行,然后在项目根目录下执行以下命令来构建和运行项目:·

mvn clean install
mvn spring-boot:run

测试接口

创建用户:

POST http://localhost:8080/users?name=Jacob&email=jacob@example.com

获取用户:

GET http://localhost:8080/users/jacob@example.com

验证数据库数据

mysql> select * from user;
+----+-------------------+-------+
| id | email             | name  |
+----+-------------------+-------+
|  1 | jacob@example.com | Jacob |
+----+-------------------+-------+
1 row in set (0.00 sec)
  • 数据库有了新增数据。

验证缓存数据

get users::jacob@example.com

"\"User(id=1, name=Jacob, email=jacob@example.com)\""
posted @ 2024-10-21 10:51  Jacob-Chen  阅读(398)  评论(0)    收藏  举报