首页 > kotlin + springboot 整合redis,Redis工具类编写及单元测试

kotlin + springboot 整合redis,Redis工具类编写及单元测试

参考自:  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.0org.springframework.bootspring-boot-starter-parent2.1.7.RELEASEcom.exampletest-redis0.0.1-SNAPSHOTtest-redisDemo project for Spring Boot1.81.2.71org.jetbrains.kotlinkotlin-reflectorg.jetbrains.kotlinkotlin-stdlib-jdk8org.springframework.bootspring-boot-starter-testtestorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-data-redisorg.jetbrains.kotlinkotlin-test-junit51.2.70test${project.basedir}/src/main/kotlin${project.basedir}/src/test/kotlinorg.springframework.bootspring-boot-maven-pluginorg.jetbrains.kotlinkotlin-maven-plugin-Xjsr305=strictspringorg.jetbrains.kotlinkotlin-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等数据。

 

转载于:https://www.cnblogs.com/wushengwuxi/p/11372713.html

更多相关:

  • 前言 近期在做on nvme hash引擎相关的事情,对于非全序的数据集的存储需求,相比于我们传统的LSM或者B-tree的数据结构来说 能够减少很多维护全序上的计算/存储资源。当然我们要保证hash场景下的高写入能力,append-only 还是比较友好的选择。 像 Riak的bitcask 基于索引都在内存的hash引擎这种,...

  • 前言 最近在读 MyRocks 存储引擎2020年的论文,因为这个存储引擎是在Rocksdb之上进行封装的,并且作为Facebook 内部MySQL的底层引擎,用来解决Innodb的空间利用率低下 和 压缩效率低下的问题。而且MyRocks 在接入他们UDB 之后成功达成了他们的目标:将以万为单位的服务器集群server个数缩减了一...

  • 1、引入maven依赖 org.springframework.bootspring-boot-starter-data-redis   2、redis连接配置 spring:redis:h...

  • json 键值对增加、删除 obj.key='value'; // obj.key=obj[key]=eval("obj."+key); delete obj.key; vue中新增和删除属性 this.$set(object,key,value) this.$delete( object, key ) 触发视图更新 遍历键值 for...

  • /*判断屏幕宽高比是否为16:9*/ function isScreen16to9() {return window.screen.height / window.screen.width === 9 / 16; }...

  • /*关闭、刷新、跳转、离开当前网页前提示*/ onbeforeunload = function () {return false; };  ...

  • let json = {/**判断JSON格式*/ isJSON: function (str) {if (typeof str == "string") {try {var obj = JSON.parse(str);if (typeof obj == "object" && obj) {return true;} else {...

  •   项目结构   index.js //必须要安装否则就别想运行了❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤ //npm i body-parser -D & cnpm i express & cnpm i node-xlsx & cnp...

  • 一、递归 函数    为什么要有函数,提高代码的可读性,避免重复的代码,提高代码的复用性      在函数中能用return的不要print 1、递归的最大深度997 def foo(n):print(n)n+=1foo(n) foo(1) 递归的最大深度 2、修改递归的最大深度     由此我们可以看出,未报错之前能看到的最大数...