前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理

【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理

原创
作者头像
yukong
修改2018-08-20 17:28:41
5330
修改2018-08-20 17:28:41
举报
文章被收录于专栏:yukong的小专栏

【SpringBoot2.0系列01】初识SpringBoot

【SpringBoot2.0系列02】SpringBoot之使用Thymeleaf视图模板

【SpringBoot2.0系列03】SpringBoot之使用freemark视图模板

【SpringBoot2.0系列04】SpringBoot之使用JPA完成简单的rest api

【SpringBoot2.0系列05】SpringBoot之整合Mybatis

【SpringBoot2.0系列06】SpringBoot之多数据源动态切换数据源

【SpringBoot2.0系列07】SpringBoot之redis使用(Lettuce版本)

【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理

目标

实现数据缓存,如果缓存中没有数据,则从数据库查询,并且写入redis缓存,如果redis缓存中有数据,则直接从redis中读取,同事删除更新等操作也需要维护缓存。本文基于前面两篇文章而来,部分重复就不贴。

实现

1、依赖

代码语言:txt
复制
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- redis依赖commons-pool 这个依赖一定要添加 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>

2、配置redis跟mybatis

yml配置如下:

代码语言:txt
复制
server:
  port: 8989
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        max-idle: 8
        min-idle: 0
        max-active: 8
mybatis:
  config-location: classpath:/mybatis/config/mybatis-config.xml
  mapper-locations: classpath:/mybatis/mapper/*.xml
logging:
  level:
    com:
      yukong:
        chapter7:
          repository: debug

这里就是配置了一下mybati跟redis 但是比之前多了一点就是配置了我们

com.yukong.chapter.repository包的日志级别为debug这样sql就会打印出来。

然后之前一样的配置一下RedisConfig.java

代码语言:txt
复制
    
/**
 * @author xiongping22369
 * @date 2018/8/20 15:33
 * @description redis配置  配置序列化方式以及缓存管理器 @EnableCaching 开启缓存
 */
@EnableCaching
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {


    /**
     * 配置自定义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 serializer = new Jackson2JsonRedisSerializer(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;
    }
}

相比上节,我们多配置了一个缓存管理器,在springboot2中配置缓存管理是新的api也就是builder模式构建。然后通过@EnableCaching 开启缓存注解。然后需要注意的是 你在redistemplate中的配置的key,value序列化方法并不会生效,需要在RedisCacheConfiguration中单独配置。

3、使用caching注解

一般缓存在service层中使用。

代码如下

代码语言:txt
复制
/**
 * @author yukong
 * @date 2018/8/20 14:35
 * @description user业务层实现
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;


    @Override
    public User saveUser(User user) {
        userMapper.save(user);
        // 返回用户信息,带id
        return user;
    }

    /**
     * @CacheEvict 应用到删除数据的方法上,调用方法时会从缓存中删除对应key的数据
     *      condition 与unless相反,只有表达式为真才会执行。
     * @param id 主键id
     * @return
     */
    @CacheEvict(value = "user", key = "#root.args[0]", condition = "#result eq true")
    @Override
    public Boolean removeUser(Long id) {
        // 如果删除记录不为1  则是失败
        return userMapper.deleteById(id) == 1;
    }

    /**
     *  @Cacheable 应用到读取数据的方法上,先从缓存中读取,如果没有再从DB获取数据,然后把数据添加到缓存中
     *            key 缓存在redis中的key
     *            unless 表示条件表达式成立的话不放入缓存
     * @param id 主键id
     * @return
     */
    @Cacheable(value = "user", key = "#root.args[0]", unless = "#result eq null ")
    @Override
    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    /**
     *  @CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存
     * @param user 用户信息
     * @return
     */
    @CachePut(value = "user", key = "#root.args[0]", unless = "#user eq null ")
    @Override
    public User updateUser(User user) {
        userMapper.update(user);
        return user;
    }
}

其中每个注解的作用都写在注释中了。

4、测试

然后我们编写一下对应的rest接口来测试

代码语言:txt
复制
/**
 * @author yukong
 * @date 2018/8/20 15:27
 * @description user控制器
 */
@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User save(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @PutMapping
    public User update(@RequestBody User user) {
        return userService.updateUser(user);
    }

    @DeleteMapping(value = "/id/{id}")
    public Boolean delete(@PathVariable  Long id) {
        return userService.removeUser(id);
    }

    @GetMapping(value = "/id/{id}")
    public User findById (@PathVariable Long id) {
        return userService.getById(id);
    }

}

启动程序。首先访问http://localhost:8989/user/id/2

成功请求数据 并且控制台打印sql

image.png
image.png

查看redis是否成功缓存数据。

image.png
image.png

成功缓存数据,并且key为主键id。

再次刷新访问。

image.png
image.png

并没有打印sql,说明缓存生效,数据是从缓存中去的,而没有去访问数据库。

至于修改跟删除两个注解就交给大家测试。

关于本文,其中mybatis相关的代码并没有贴出,全部代码放在github上,地址如下。

最后配套教程的代码全部在这里

github https://github.com/YuKongEr/SpringBoot-Study。麻烦点个star或者fork吧。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目标
  • 实现
    • 1、依赖
      • 2、配置redis跟mybatis
        • 3、使用caching注解
          • 4、测试
          相关产品与服务
          云数据库 Redis
          腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档