猴子也能懂的springboot教程(三) - springboot整合Redis

20190514180005.jpg

摘要

本文介绍
springboot整合redis
采用RedisCacheManager作为缓存管理器
并使用fastjson序列化

承接上篇
猴子也能懂的springboot教程(二) - springboot整合Mybatis
本次我们在原先代码基础上整合Redis
直接上代码。。。

添加依赖

在pom.xml中添加依赖文件

    
    
        org.springframework.boot
        spring-boot-starter-data-redis
    
    
    
        com.alibaba
        fastjson
        1.2.31
    

新增配置文件

在spring下级添加redis配置文件

spring:
  #mysql 配置略(参见上文)
  #redis
  redis:
    database: 0
    host: 192.168.162.134
    port: 6379
    password: redis
    pool:
      jedis:
        max-active: 200
        max-wait: -1
        max-idle: 10
        min-idle: 1
    timeout: 1000

自定义Redis序列化工具

创建com.gao.utils.FastJsonRedisSerializer类实现RedisSerializer接口

package com.gao.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;

public class FastJsonRedisSerializer implements RedisSerializer{

    private final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private Class clazz;

    public FastJsonRedisSerializer(Class clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if(null == t) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes,DEFAULT_CHARSET);
        return (T)JSON.parseObject(str,clazz);
    }
}

配置Redis

创建com.gao.config.RedisConfig类,

package com.gao.config;

import com.alibaba.fastjson.parser.ParserConfig;
import com.gao.utils.FastJsonRedisSerializer;
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.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        //序列化方式
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
        RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);

        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig();
        //设置缓存过期时间
        defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofMinutes(10));
        defaultCacheConfig = defaultCacheConfig.serializeValuesWith(pair);

        RedisCacheManager rcm = RedisCacheManager.builder(redisCacheWriter).cacheDefaults(defaultCacheConfig).transactionAware().build();
        ParserConfig.getGlobalInstance().addAccept("com.gao");
        return rcm;
    }

    /**
     * @Description: 防止redis入库序列化乱码的问题
     * @return     返回类型
     * @date 2018/4/12 10:54
     */
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        StringRedisTemplate redisTemplate = new StringRedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //使用fastjson序列化
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        //key序列化使用StringRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());//key序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //value序列化使用fastJsonRedisSerializer
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);  //value序列化
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}
 
 

封装redisTemplate

其实上一步已经可以直接调用redisTemplate操作Redis了,不过这里对其做了简单的封装。
缓存接口ICache
创建com.gao.cache.ICache接口类

package com.gao.cache;

public interface ICache {
    /**
     * 60秒
     */
    public static final long ONE_MIN_SECONDS = 60;
    /**
     * 半小时
     */
    public static final long HALF_HOUR_SECONDS = 30 * ONE_MIN_SECONDS;

    /**
     * 保存自定义时长
     */
    void set(final String key, V value, Long expireTime);

    /**
     * 保存半小时
     */
    void setHalfHour(String key, V value);

    /**
     * 查询
     */
    V get(final String key);

    /**
     * 删除
     */
    public void remove(final String key);
}

实现ICache接口
创建com.gao.cache.impl.RedisCache实现ICache接口

package com.gao.cache.impl;
import ...;
import java.util.concurrent.TimeUnit;

@Component
public class RedisCache implements ICache{

    // 在构造器中获取redisTemplate实例, key(not hashKey) 默认使用String类型
    private RedisTemplate redisTemplate;
    private ValueOperations valueOperations;

    // 实例化操作对象后就可以直接调用方法操作Redis数据库
    @Autowired
    public RedisCache(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.valueOperations = redisTemplate.opsForValue();
    }

    @Override
    public void set(String key, V value, Long expireTime) {
        valueOperations.set(key, value ,expireTime, TimeUnit.SECONDS);
    }

    @Override
    public void setHalfHour(String key, V value) {
        set(key,value,HALF_HOUR_SECONDS);
    }

    @Override
    public V get(String key) {
        return valueOperations.get(key);
    }

    @Override
    public void remove(String key) {
        redisTemplate.delete(key);
    }
}

完成,开始测试

修改mapper

mapper接口中添加方法

@Mapper
public interface UserMapper {

    User getUserByName(String username);

    User getUserById(String Id);
}

mapper.xml中添加


    

    

修改service

service接口

public interface IUserService {
    User getUserByUsername(String username);

    User getUserById(String id);
}

service实现类

@EnableCaching
@Service
public class UserServiceIml implements IUserService{

    private Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    private ICache cache;

    @Autowired
    private UserMapper userMapper;

    @Value("${spring.redis.cache.user.key}")
    private String CACHE_USER_KEY;

    //显示调用缓存
    @Override
    public User getUserByUsername(String username) {
        User user = userMapper.getUserByName(username);
        cache.setHalfHour(CACHE_USER_KEY + user.getId(),user);
        return user;
    }
    //使用注解测试cacheManager
    @Cacheable(value = "user_id", key="#id")
    @Override
    public User getUserById(String id) {
        User user = userMapper.getUserById(id);
        logger.info("查询数据库");
        return user;
    }
}

修改controller

@RestController
@RequestMapping("test")
public class TestController {

    @Autowired
    private IUserService userService;

    @GetMapping("name/{name}")
    public String index(@PathVariable String name){
        User user = userService.getUserByUsername(name);
        return "hi " + user.getUsername() + " your id is "+ user.getId();
    }

    @GetMapping("id/{id}")
    public String getUserById(@PathVariable String id){
        User user = userService.getUserById(id);
        return "hi " + user.getId() + " your name is "+ user.getUsername();
    }
}

启动测试

先访问 http://localhost:8890/test/name/stephen 获得id

20190514100001.png

再访问 http://localhost:8890/test/id/8f5689836eef11e9869d000d29242eff 获得name
多次刷新页面,控制台只有一条日志,其余查询走了缓存

20190514100002.png

去Redis查询 keys *


20190514100003.png

至此springboot整合Redis完成

系列文章

猴子也能懂的springboot教程

你可能感兴趣的:(猴子也能懂的springboot教程(三) - springboot整合Redis)