但是,我尝试使用Spring Boot 2.0和Kotlin来使用Spring Data Redis

我开始使用Kotlin了,但在一些微妙的地方卡住了。
虽然它有动作,但还有很多令人困惑的地方。

首先,我会简单地说明一下。
我要创建一个仅用于调用API并将数据保存到Redis中,然后进行读取的API。

这里是资源链接。
GitHub的Spring Boot 2.0版本。
GitHub的Spring Boot 1.5版本。

实施

Gradle

buildscript {
    ext {
        kotlinVersion = '1.2.20'
        springBootVersion = '2.0.0.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}

repositories {
    mavenCentral()
}

configurations {
    providedRuntime
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testCompile('org.springframework.boot:spring-boot-starter-test')

    compile('org.springframework.boot:spring-boot-starter-data-redis')
    compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.4")
    compile("org.apache.commons:commons-pool2:2.5.0")
    compile("redis.clients:jedis:2.9.0")
}

第一个谜题是关于在Spring Boot 1.5版本中添加的组件。在那个版本中,我们只需要添加spring-boot-starter-data-redis和jackson-module-kotlin这两个组件。但在2.0版本中,还需要额外的commons-pool2和jedis组件。即使在spring-boot-starter-data-redis中依赖了commons-pool2和jedis也是可以的。

Kotlin是一种编程语言。

package com.example

import com.example.service.SampleService
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController

@RestController
class SampleController(
        val sampleService: SampleService
) {
    @RequestMapping(value = ["/sample-redis"], method = [RequestMethod.GET])
    fun sampleReids(): SampleDto? {
        return sampleService.getSampleDto();
    }

    @RequestMapping(value = ["/sample-redis2"], method = [RequestMethod.GET])
    fun sampleReids2(): SampleDto? {
        return sampleService.getSampleDto2();
    }
}
package com.example

import java.io.Serializable

class SampleDto(val id:Int, val name:String):Serializable
package com.example

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer

@Configuration
class SampleConfiguration {
    @Bean
    fun jedisConnectionFactory(): JedisConnectionFactory {
        return JedisConnectionFactory()
    }

    @Bean
    fun redisTemplate(): RedisTemplate<String, SampleDto> {
        val template  = RedisTemplate<String, SampleDto>()
        template.setConnectionFactory(jedisConnectionFactory())
        template.keySerializer = StringRedisSerializer()

        val jackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(SampleDto::class.java)
        val om = jacksonObjectMapper()
        jackson2JsonRedisSerializer.setObjectMapper(om)
        template.valueSerializer = jackson2JsonRedisSerializer

        return template;
    }

    @Bean
    fun redisTemplate2(): RedisTemplate<String, String> {
        val template  = RedisTemplate<String, String>()
        template.setConnectionFactory(jedisConnectionFactory())
        template.keySerializer = StringRedisSerializer()
        template.valueSerializer = StringRedisSerializer()
        return template;
    }
}

第二个谜题是有关于在设置connectionFactory时的实现在1.5和2.0版本中的差异。

Kotlin: spring-boot 1.5 的代码
template.connectionFactory = jedisConnectionFactory()

Kotlin:Spring Boot 2.0
template.setConnectionFactory(jedisConnectionFactory())。
Kotlin:Spring Boot 2.0
设置template的连接工厂为jedisConnectionFactory()。

真的可以通过设置来实现吗?

由于Kotlin与Java的使用方式不同,无法直接设置和使用Jackson2JsonRedisSerializer。因此,我在创建后设置了jacksonObjectMapper。

我想通过redisTemplate的类型参数将SampleDto设置为Any,但是没有成功。
也许可以做到,但是…
所以,我在Service中使用redisTemplate2进行了json转换,并在Configuration中将其保存为字符串。

package com.example.service

import com.example.SampleDto

interface SampleService {
    fun getSampleDto(): SampleDto?
    fun getSampleDto2(): SampleDto?
}
package com.example.service

import com.example.SampleDto
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.stereotype.Service

@Service
class SampleServiceImpl(
        val redisTemplate:RedisTemplate<String, SampleDto>,
        val redisTemplate2:RedisTemplate<String, String>
):SampleService {
    override fun getSampleDto():SampleDto? {
        redisTemplate.opsForValue().set("test_dto", SampleDto(1, "aab"))
        return redisTemplate.opsForValue().get("test_dto")
    }

    override fun getSampleDto2():SampleDto? {
        val sampleDto = SampleDto(1, "aac")

        val om = jacksonObjectMapper()

        var jsonStr = om.writeValueAsString(sampleDto)
        redisTemplate2.opsForValue().set("test_dto2", jsonStr)

        val jsonStr2 = redisTemplate2.opsForValue().get("test_dto2")
        return om.readValue(jsonStr2 ?: "{}", SampleDto::class.java)
    }
}

请参考

    • Jackson Kotlin Module Example

 

    • Kotlin – Convert Object to/from JSON with Jackson 2.x

 

    Java: Spring Boot で Redis を使う!

Kotlin,很難啊…
充滿謎團啊。

GitHub spring boot 2.0 could be paraphrased in Chinese as “GitHub Spring Boot 2.0” (GitHub春季启动2.0).
Similarly, GitHub spring boot 1.5 can be paraphrased as “GitHub Spring Boot 1.5” (GitHub春季启动1.5).

广告
将在 10 秒后关闭
bannerAds