语言: java+kotlin
# windows下安装redis
# 安装redis可视化工具 Redis Desktop Manager
# 依赖
compile('org.springframework.boot:spring-boot-starter-data-redis')
# application.yml配置
spring:
# redis
redis:
database: 0
host: localhost
port: 6379
password: 12345
jedis:
pool:
max-active: 10
min-idle: 0
max-idle: 8
timeout: 10000
# redis配置类 new RedisConfiguration
package com.futao.springmvcdemo.foundation.configuration
import org.springframework.cache.CacheManager
import org.springframework.cache.annotation.CachingConfigurerSupport
import org.springframework.cache.annotation.EnableCaching
import org.springframework.cache.interceptor.KeyGenerator
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheManager
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.StringRedisSerializer
import javax.annotation.Resource
/**
* redis配置类
*
* @author futao
* Created on 2018/10/16.
*
* redisTemplate.opsForValue();//操作字符串
* redisTemplate.opsForHash();//操作hash
* redisTemplate.opsForList();//操作list
* redisTemplate.opsForSet();//操作set
* redisTemplate.opsForZSet();//操作有序set
*
*/
@Configuration
@EnableCaching
open class RedisConfiguration : CachingConfigurerSupport() {
/**
* 自定义redis key的生成规则
*/
@Bean
override fun keyGenerator(): KeyGenerator {
return KeyGenerator { target, method, params ->
val builder = StringBuilder()
builder.append("${target.javaClass.simpleName}-")
.append("${method.name}-")
for (param in params) {
builder.append("$param-")
}
builder.toString().toLowerCase()
}
}
/**
* 自定义序列化
* 这里的FastJsonRedisSerializer引用的自己定义的
*/
@Bean
open fun redisTemplate(factory: RedisConnectionFactory): RedisTemplate<String, Any> {
val redisTemplate = RedisTemplate<String, Any>()
val fastJsonRedisSerializer = FastJsonRedisSerializer(Any::class.java)
val stringRedisSerializer = StringRedisSerializer()
return redisTemplate.apply {
defaultSerializer = fastJsonRedisSerializer
keySerializer = stringRedisSerializer
hashKeySerializer = stringRedisSerializer
valueSerializer = fastJsonRedisSerializer
hashValueSerializer = fastJsonRedisSerializer
connectionFactory = factory
}
}
@Resource
lateinit var redisConnectionFactory: RedisConnectionFactory
override fun cacheManager(): CacheManager {
return RedisCacheManager.create(redisConnectionFactory)
}
}
# 自定义redis中数据的序列化与反序列化 new FastJsonRedisSerializer
package com.futao.springmvcdemo.foundation.configuration
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.serializer.SerializerFeature
import com.futao.springmvcdemo.model.system.SystemConfig
import org.springframework.data.redis.serializer.RedisSerializer
import java.nio.charset.Charset
/**
* 自定义redis中数据的序列化与反序列化
*
* @author futao
* Created on 2018/10/17.
*/
class FastJsonRedisSerializer<T>(java: Class<T>) : RedisSerializer<T> {
private val clazz: Class<T>? = null
/**
* Serialize the given object to binary data.
*
* @param t object to serialize. Can be null.
* @return the equivalent binary data. Can be null.
*/
override fun serialize(t: T?): ByteArray? {
return if (t == null) {
null
} else {
JSON.toJSONString(t, SerializerFeature.WriteClassName).toByteArray(Charset.forName(SystemConfig.UTF8_ENCODE))
}
}
/**
* Deserialize an object from the given binary data.
*
* @param bytes object binary representation. Can be null.
* @return the equivalent object instance. Can be null.
*/
override fun deserialize(bytes: ByteArray?): T? {
return if (bytes == null || bytes.isEmpty()) {
null
} else {
val string = String(bytes, Charset.forName(SystemConfig.UTF8_ENCODE))
JSON.parseObject(string, clazz) as T
}
}
}
# 启动类
package com.futao.springmvcdemo;
import com.alibaba.fastjson.parser.ParserConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
/**
* @author futao
* ServletComponentScan 开启servlet和filter
*/
@SpringBootApplication
@ServletComponentScan
@MapperScan("com.futao.springmvcdemo.dao")
@EnableCaching
//@EnableAspectJAutoProxy
public class SpringmvcdemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringmvcdemoApplication.class, args);
/**
* redis反序列化
* 开启fastjson反序列化的autoType
*/
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
}
}
# 使用
1. 基于注解的方式
- @Cacheable() redis中的key会根据我们的keyGenerator方法来生成,比如对应下面这个例子,如果曾经以mobile,pageNum,pageSize,orderBy的值执行过list这个方法的话,方法返回的值会存在redis缓存中,下次如果仍然以相同的mobile,pageNum,pageSize,orderBy的值来调用这个方法的话会直接返回缓存中的值
@Service
public class UserServiceImpl implements UserService {
@Override
@Cacheable(value = "user")
public List<User> list(String mobile, int pageNum, int pageSize, String orderBy) {
PageResultUtils<User> pageResultUtils = new PageResultUtils<>();
final val sql = pageResultUtils.createCriteria(User.class.getSimpleName())
.orderBy(orderBy)
.page(pageNum, pageSize)
.getSql();
return userDao.list(sql);
}
}
- 测试
第一次请求(可以看到执行了sql,数据是从数据库中读取的)
第一次请求
通过redis desktop manager查看redis缓存中已经存储了我们刚才list返回的值
image.png
- 后续请求(未执行sql,直接读取的是redis中的值)
后续请求
2. 通过java代码手动set与get
package com.futao.springmvcdemo.controller
import com.futao.springmvcdemo.model.entity.User
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import javax.annotation.Resource
/**
* @author futao
* Created on 2018/10/17.
*/
@RestController
@RequestMapping(path = ["kotlinTest"], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE])
open class KotlinTestController {
@Resource
private lateinit var redisTemplate: RedisTemplate<Any, Any>
/**
* 存入缓存
*/
@GetMapping(path = ["setCache"])
open fun cache(
@RequestParam("name") name: String,
@RequestParam("age") age: Int
): User {
val user = User().apply {
username = name
setAge(age.toString())
}
redisTemplate.opsForValue().set(name, user)
return user
}
/**
* 获取缓存
*/
@GetMapping(path = ["getCache"])
open fun getCache(
@RequestParam("name") name: String
): User? {
return if (redisTemplate.opsForValue().get(name) != null) {
redisTemplate.opsForValue().get(name) as User
} else null
}
}
测试结果
请求(序列化)
image.png
redis desktop manager中查看
查看
读取(反序列化)
读取
# 坑
- 使用注解的方式存入的数据使用redis desktop manager或者
redis-cli --raw
查看显示的是编码之后的,但是使用java代码手动set并不会出现这样的问题(后期需要检查使用注解的方式是不是走了自定义的序列化)
# TODO
- redis数据的持久化
我在这里等你:
image.png