RedisJava后台Java编程社区

SpringBoot+Mybatis+Redis 实现缓存

2019-07-31  本文已影响195人  盼旺

环境版本

Mysql-8.0
springboot-2.1.6
jdk-1.8

1.新建项目

新建项目

2.采用mybatis-generator自动生成mapper,dao,entity

链接:https://www.jianshu.com/p/b519e9ef605f

3.首先实现springboot+mybatis

链接:https://www.jianshu.com/p/16f910aa4cf4

4.先安装redis数据库

Linux下和Win10下:https://www.jianshu.com/p/1299f5754d74

5.项目中配置redis

1.添加redis的properties的配置

# ==============================
# redis configurations
# ==============================
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
# Redis数据库索引(默认为0)
spring.redis.database=0
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8  
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8  
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0

添加依赖

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2.Redis Java配置(RedisConfig.java)
package com.wglvzyx.mybatisredis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


import java.time.Duration;
import java.util.*;

/**
 * @description redis配置  配置序列化方式以及缓存管理器
 */
@EnableCaching // 开启缓存
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {

    /**
     *  配置自定义redisTemplate
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setValueSerializer(jackson2JsonRedisSerializer());
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    /**
     * json序列化
     * @return
     */
    @Bean
    public RedisSerializer<Object> jackson2JsonRedisSerializer() {
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        return serializer;
    }

    /**
     * 缓存管理器配置
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 设置缓存的默认过期时间,也是使用Duration设置
        config = config.entryTtl(Duration.ofMinutes(1))
                // 设置 key为string序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 设置value为json序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
                // 不缓存空值
                .disableCachingNullValues();

        // 设置一个初始化的缓存空间set集合
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("timeGroup");
        cacheNames.add("user");

        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("timeGroup", config);
        configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));

        // 使用自定义的缓存配置初始化一个cacheManager
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
                // 一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
                .initialCacheNames(cacheNames)
                .withInitialCacheConfigurations(configMap)
                .build();
        return cacheManager;
    }

    /**
     * 缓存的key是 包名+方法名+参数列表
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, objects) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append("::" + method.getName() + ":");
            for (Object obj : objects) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }

}

3.介绍缓存注解

@Cacheable – 表明对应方法的返回结果可以被缓存,首次调用后,下次就从缓存中读取结果,方法不会再被执行了。
@CachePut – 更新缓存,方法每次都会执行
@CacheEvict – 清除缓存,方法每次都会执行
...等等
因为主要的业务逻辑在服务层实现,一般会把缓存注解加在服务层的方法上。

4.缓存举例子

//key 是学生id value 是学生这个实体
    @Cacheable(key = "#stuid", value = "Student")
    public Student SelectOneStuById(int stuid){
        return studentMapper.selectByPrimaryKey(stuid);
    }
    @CacheEvict(key = "#stuid", value = "Student")
    public Student updateStuName(int stuid, String stuname) {
        Student oldstu = studentMapper.selectByPrimaryKey(stuid);
        oldstu.setUsername(stuname);
        int f = studentMapper.updateByPrimaryKey(oldstu);
        return oldstu;
    }

控制器中添加俩个访问地址来测试

    // 读取学生信息,测试缓存使用:除了首次读取,接下来都应该从缓存中读取
    @RequestMapping(value="{id}")
    @ResponseBody
    public Student getStu(@PathVariable long id){
        System.out.println(id);
        Student onestu = studentService.SelectOneStuById((int) id);
        return onestu;
    }
/***************************'或者'*****************************/
    // 读取学生信息,测试缓存使用:除了首次读取,接下来都应该从缓存中读取 
//用http://localhost:8080/GetOneStu?uid=1访问

    @GetMapping(value="/GetOneStu")
    @ResponseBody
    public Student getOneStu(String uid){
        int id = Integer.parseInt(uid);
        System.out.println(id);
        Student onestu = studentService.SelectOneStuById(id);
        return onestu;
    }
/****************************************************************/
    // 更新学生信息
    @RequestMapping(value="{id}/wgname")
    @ResponseBody
    public Student UpdateStu(@PathVariable long id){
        System.out.println(id);
        String name = "ceshi";
        Student onestu = studentService.updateStuName((int) id,name);
        return onestu;
    }

5.运行测试
监控redis服务器,打开redis-cli.exe,然后使用monitor命令开始监控:


获取用户信息

修改用户信息

6.使用RedisTemplate访问redis服务器

  //@Resource的作用相当于@Autowired,只不过@Autowired按byType(按类型)自动注入,而@Resource默认按 byName(按名称)自动注入罢了
    @Resource(name = "redisTemplate")
    RedisTemplate<String,Object> redis;

    // 使用RedisTemplate访问redis服务器
    @RequestMapping(value="/redis", method=RequestMethod.GET, produces="application/json")
    @ResponseBody
    public String redis() throws Exception {
        // 设置键"ceshi-key=wg",值"ceshi-value=zyx"
        redis.opsForValue().set("ceshi-key=wg", "ceshi-value=zyx");
        String value = (String) redis.opsForValue().get("ceshi-key=wg");
        return value;
    }
在软件Postman中测试

redis数据库存入了指定的键值对

   //向redis里存入数据和设置缓存时间
    wgRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);  
     
    //value做-1操作
    wgRedisTemplate.boundValueOps("test").increment(-1);  
     
    //根据key获取缓存中的value
    wgRedisTemplate.opsForValue().get("test") 
     
    //value做+1操作  
    wgRedisTemplate.boundValueOps("test").increment(1);
     
    //根据key获取过期时间  
    wgRedisTemplate.getExpire("test")
     
    //根据key获取过期时间并换算成指定单位 
    wgRedisTemplate.getExpire("test",TimeUnit.SECONDS) 
     
    //根据key删除缓存
    wgRedisTemplate.delete("test");  
     
    //检查key是否存在,返回boolean值
    wgRedisTemplate.hasKey("546545");  
     
    //向指定key中存放set集合
    wgRedisTemplate.opsForSet().add("red_123", "1","2","3");
      
    //设置过期时间
    wgRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS); 
     
    //根据key查看集合中是否存在指定数据  
    wgRedisTemplate.opsForSet().isMember("red_123", "1")
     
    //根据key获取set集合
    wgRedisTemplate.opsForSet().members("red_123");

参考文章:https://www.qikegu.com/docs/2576

上一篇下一篇

猜你喜欢

热点阅读