语言: 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,数据是从数据库中读取的)

    [原创]Springboot整合redis从安装到FLUSHALL_json 第一次请求

  • 通过redis desktop manager查看redis缓存中已经存储了我们刚才list返回的值

    [原创]Springboot整合redis从安装到FLUSHALL_json_02 image.png

  • 后续请求(未执行sql,直接读取的是redis中的值)
  • [原创]Springboot整合redis从安装到FLUSHALL_spring_03 后续请求

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
}
}
  • 测试结果

  • 请求(序列化)

    [原创]Springboot整合redis从安装到FLUSHALL_spring_04 image.png

  • redis desktop manager中查看

    [原创]Springboot整合redis从安装到FLUSHALL_json_05 查看

  • 读取(反序列化)

    [原创]Springboot整合redis从安装到FLUSHALL_json_06 读取

# 坑

  • 使用注解的方式存入的数据使用redis desktop manager或者​​redis-cli --raw​​查看显示的是编码之后的,但是使用java代码手动set并不会出现这样的问题(后期需要检查使用注解的方式是不是走了自定义的序列化)

# TODO

  • redis数据的持久化

我在这里等你:


[原创]Springboot整合redis从安装到FLUSHALL_spring_07 image.png