参考自: https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html
1、maven依赖
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.7.RELEASE com.example test-redis 0.0.1-SNAPSHOT test-redis Demo project for Spring Boot 1.8 1.2.71 org.jetbrains.kotlin kotlin-reflect org.jetbrains.kotlin kotlin-stdlib-jdk8 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-redis org.jetbrains.kotlin kotlin-test-junit5 1.2.70 test ${project.basedir}/src/main/kotlin ${project.basedir}/src/test/kotlin org.springframework.boot spring-boot-maven-plugin org.jetbrains.kotlin kotlin-maven-plugin -Xjsr305=strict spring org.jetbrains.kotlin kotlin-maven-allopen ${kotlin.version}
2、RedisTemplate配置,新建RedisContig.kt
package com.example.demo.configimport com.fasterxml.jackson.annotation.JsonAutoDetect import com.fasterxml.jackson.annotation.PropertyAccessor import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.data.redis.connection.RedisConnectionFactory import org.springframework.data.redis.core.RedisTemplate import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer import org.springframework.data.redis.serializer.StringRedisSerializer@Configuration class RedisConfig {@Beanfun redisTemplate(factory : RedisConnectionFactory) : RedisTemplate{val om = ObjectMapper()//om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY);//om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); val jackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(Any::class.java)jackson2JsonRedisSerializer.setObjectMapper(om)val stringRedisSerializer = StringRedisSerializer()val template = RedisTemplate ()template.setConnectionFactory(factory)template.keySerializer = stringRedisSerializertemplate.hashKeySerializer = stringRedisSerializertemplate.valueSerializer = jackson2JsonRedisSerializertemplate.hashValueSerializer = jackson2JsonRedisSerializertemplate.afterPropertiesSet()return template} }
创建类RedisUtil.kt,作为redis操作类
package com.example.demo.utilimport org.springframework.data.redis.core.RedisTemplate import org.springframework.stereotype.Component import org.springframework.util.CollectionUtils import java.util.concurrent.TimeUnit import javax.annotation.Resource@Component class RedisUtil {@Resourceprivate lateinit var redisTemplate: RedisTemplate// =============================common============================/*** 指定缓存失效时间* @param key 键* @param time 时间(秒)* @return*/fun expire(key: String, time: Long): Boolean {try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS)}return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 根据key 获取过期时间* @param key 键 不能为null* @return 时间(秒) 返回0代表为永久有效*/fun getExpire(key: String): Long {return redisTemplate.getExpire(key, TimeUnit.SECONDS)}/*** 判断key是否存在* @param key 键* @return true 存在 false不存在*/fun hasKey(key: String): Boolean {try {return redisTemplate.hasKey(key)} catch (e: Exception) {e.printStackTrace()return false}}/*** 删除缓存* @param key 可以传一个值 或多个*/fun del(vararg key: String) {if (key.isNotEmpty()) {if (key.size == 1) {redisTemplate.delete(key[0])} else {redisTemplate.delete(key.toList())}}}// ============================String=============================/*** 普通缓存获取* @param key 键* @return 值*/operator fun get(key: String?): Any? {return if (key == null) null else redisTemplate.opsForValue().get(key)}/*** 普通缓存放入* @param key 键* @param value 值* @return true成功 false失败*/operator fun set(key: String, value: Any): Boolean {try {redisTemplate.opsForValue().set(key, value)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 普通缓存放入并设置时间* @param key 键* @param value 值* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期* @return true成功 false 失败*/operator fun set(key: String, value: Any, time: Long): Boolean {try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS)} else {set(key, value)}return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 递增* @param key 键* @param delta 要增加几(大于0)* @return*/fun incr(key: String, delta: Long): Long {if (delta < 0) {throw RuntimeException("递增因子必须大于0")}return redisTemplate.opsForValue().increment(key, delta)!!}/*** 递减* @param key 键* @param delta 要减少几(小于0)* @return*/fun decr(key: String, delta: Long): Long {if (delta < 0) {throw RuntimeException("递减因子必须大于0")}return redisTemplate.opsForValue().increment(key, -delta)!!}// ================================Map=================================/*** HashGet* @param key 键 不能为null* @param item 项 不能为null* @return 值*/fun hget(key: String, item: String): Any? {return redisTemplate.opsForHash ().get(key, item)}/*** 获取hashKey对应的所有键值* @param key 键* @return 对应的多个键值*/fun hmget(key: String): Map {return redisTemplate.opsForHash ().entries(key)}/*** HashSet* @param key 键* @param map 对应多个键值* @return true 成功 false 失败*/fun hmset(key: String, map: Map ): Boolean {try {redisTemplate.opsForHash ().putAll(key, map)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** HashSet 并设置时间* @param key 键* @param map 对应多个键值* @param time 时间(秒)* @return true成功 false失败*/fun hmset(key: String, map: Map , time: Long): Boolean {try {redisTemplate.opsForHash ().putAll(key, map)if (time > 0) {expire(key, time)}return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 向一张hash表中放入数据,如果不存在将创建* @param key 键* @param item 项* @param value 值* @return true 成功 false失败*/fun hset(key: String, item: String, value: Any): Boolean {try {redisTemplate.opsForHash ().put(key, item, value)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 向一张hash表中放入数据,如果不存在将创建* @param key 键* @param item 项* @param value 值* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间* @return true 成功 false失败*/fun hset(key: String, item: String, value: Any, time: Long): Boolean {try {redisTemplate.opsForHash ().put(key, item, value)if (time > 0) {expire(key, time)}return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 删除hash表中的值* @param key 键 不能为null* @param item 项 可以使多个 不能为null*/fun hdel(key: String, vararg item: Any) {redisTemplate.opsForHash ().delete(key, *item)}/*** 判断hash表中是否有该项的值* @param key 键 不能为null* @param item 项 不能为null* @return true 存在 false不存在*/fun hHasKey(key: String, item: String): Boolean {return redisTemplate.opsForHash ().hasKey(key, item)}/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回* @param key 键* @param item 项* @param by 要增加几(大于0)* @return*/fun hincr(key: String, item: String, by: Double): Double {return redisTemplate.opsForHash ().increment(key, item, by)}/*** hash递减* @param key 键* @param item 项* @param by 要减少记(小于0)* @return*/fun hdecr(key: String, item: String, by: Double): Double {return redisTemplate.opsForHash ().increment(key, item, -by)}// ============================set=============================/*** 根据key获取Set中的所有值* @param key 键* @return*/fun sGet(key: String): Set ? {try {return redisTemplate.opsForSet().members(key)} catch (e: Exception) {e.printStackTrace()return null}}/*** 根据value从一个set中查询,是否存在* @param key 键* @param value 值* @return true 存在 false不存在*/fun sHasKey(key: String, value: Any): Boolean {try {return redisTemplate.opsForSet().isMember(key, value)!!} catch (e: Exception) {e.printStackTrace()return false}}/*** 将数据放入set缓存* @param key 键* @param values 值 可以是多个* @return 成功个数*/fun sSet(key: String, vararg values: Any): Long {try {return redisTemplate.opsForSet().add(key, *values)!!} catch (e: Exception) {e.printStackTrace()return 0}}/*** 将set数据放入缓存* @param key 键* @param time 时间(秒)* @param values 值 可以是多个* @return 成功个数*/fun sSetAndTime(key: String, time: Long, vararg values: Any): Long {try {val count = redisTemplate.opsForSet().add(key, *values)if (time > 0)expire(key, time)return count!!} catch (e: Exception) {e.printStackTrace()return 0}}/*** 获取set缓存的长度* @param key 键* @return*/fun sGetSetSize(key: String): Long {try {return redisTemplate.opsForSet().size(key)!!} catch (e: Exception) {e.printStackTrace()return 0}}/*** 移除值为value的* @param key 键* @param values 值 可以是多个* @return 移除的个数*/fun setRemove(key: String, vararg values: Any): Long {try {val count = redisTemplate.opsForSet().remove(key, *values)return count!!} catch (e: Exception) {e.printStackTrace()return 0}}// ===============================list=================================/*** 获取list缓存的内容* @param key 键* @param start 开始* @param end 结束 0 到 -1代表所有值* @return*/fun lGet(key: String, start: Long, end: Long): List ? {try {return redisTemplate.opsForList().range(key, start, end)} catch (e: Exception) {e.printStackTrace()return null}}/*** 获取list缓存的长度* @param key 键* @return*/fun lGetListSize(key: String): Long {try {return redisTemplate.opsForList().size(key)!!} catch (e: Exception) {e.printStackTrace()return 0}}/*** 通过索引 获取list中的值* @param key 键* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推* @return*/fun lGetIndex(key: String, index: Long): Any? {try {return redisTemplate.opsForList().index(key, index)} catch (e: Exception) {e.printStackTrace()return null}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/fun lSet(key: String, value: Any): Boolean {try {redisTemplate.opsForList().rightPush(key, value)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/fun lSet(key: String, value: Any, time: Long): Boolean {try {redisTemplate.opsForList().rightPush(key, value)if (time > 0)expire(key, time)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/fun lSet(key: String, value: List ): Boolean {try {redisTemplate.opsForList().rightPushAll(key, *value.toTypedArray())return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 将list放入缓存** @param key 键* @param value 值* @param time 时间(秒)* @return*/fun lSet(key: String, value: List , time: Long): Boolean {try {redisTemplate.opsForList().rightPushAll(key, *value.toTypedArray())if (time > 0)expire(key, time)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 根据索引修改list中的某条数据* @param key 键* @param index 索引* @param value 值* @return*/fun lUpdateIndex(key: String, index: Long, value: Any): Boolean {try {redisTemplate.opsForList().set(key, index, value)return true} catch (e: Exception) {e.printStackTrace()return false}}/*** 移除N个值为value* @param key 键* @param count 移除多少个* @param value 值* @return 移除的个数*/fun lRemove(key: String, count: Long, value: Any): Long {try {val remove = redisTemplate.opsForList().remove(key, count, value)return remove!!} catch (e: Exception) {e.printStackTrace()return 0}} }
在application.properties中增加redis配置(实际上默认是这些参数)
#Redis数据库索引(默认为0) spring.redis.database=0 #Redis服务器地址 spring.redis.host=127.0.0.1 #Redis服务器连接端口 spring.redis.port=6379 #Redis服务器连接密码(默认为空) spring.redis.password=
3、单元测试
在src/test/kotlin目录下 com.example.demo包下新建类TestRedisUtil.kt
package com.example.demoimport com.example.demo.util.RedisUtil import com.fasterxml.jackson.databind.ObjectMapper import org.junit.Assert import org.junit.FixMethodOrder import org.junit.runners.MethodSorters import org.springframework.boot.test.context.SpringBootTest import javax.annotation.Resource import kotlin.test.Test@SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING) class TestRedisUtil {@Resourceprivate lateinit var redisUtil: RedisUtil@Testfun test001_javaBean() {val student = Student(0, "Aa")redisUtil.set("student", student)val json = redisUtil.get("student")var result: Student? = nullif (json is HashMap<*, *>) {//map 转 beanval mapper = ObjectMapper()//result = mapper.readValue(mapper.writeValueAsString(json), Student::class.java)result = mapper.convertValue(json, Student::class.java)Assert.assertTrue(result == student)}}@Testfun test002_List() {val list = listOf("Aa", "Bb", "Cc")redisUtil.set("listBean", list)val json = redisUtil.get("listBean")if (json != null) {val mapper = ObjectMapper()val type = mapper.typeFactory.constructParametricType(ArrayList::class.java, String::class.java)val result: List= mapper.readValue(mapper.writeValueAsString(json), type)println(result)}}@Testfun test003_stringList() {val list = listOf("Aa", "Bb", "Cc")redisUtil.del("stringList")redisUtil.lSet("stringList", list)val result = redisUtil.lGet("stringList", 0, 10)Assert.assertEquals(list, result)}@Testfun test_studentList() {val list = listOf(Student(1, "Aa"), Student(2, "Bb"), Student(3, "Cc"), null)redisUtil.del("studentList")redisUtil.lSet("studentList", list)val result= redisUtil.lGet("studentList", 0, 10)if (result is List<*> && result.isNotEmpty() && result.get(0) is List<*>) {val resultList = result[0] as List<*>val objectMapper = ObjectMapper()val studentList = resultList.map { item -> objectMapper.convertValue(item, Student::class.java) }Assert.assertEquals(list, studentList)}}@Testfun test_map() {redisUtil.del("map")val map = mutableMapOf ()map.put("A", 0)map.put("B", 1)redisUtil.hmset("map", map)val result = redisUtil.hmget("map");Assert.assertTrue(result == map)}class Student() {var id: Int? = nullvar name: String? = nullconstructor(id: Int?, name: String?) : this() {this.id = idthis.name = name}override fun hashCode(): Int {var result = id ?: 0result = 31 * result + (name?.hashCode() ?: 0)return result}override fun equals(other: Any?): Boolean {if (this === other) return trueif (javaClass != other?.javaClass) return falseother as Studentif (id != other.id) return falseif (name != other.name) return falsereturn true}override fun toString(): String {return "Student(id=$id, name=$name)"}} }
启动本地redis,即可测试从redis中存取String、list、对象及map等数据。