SpringBoot集成Redis来实现缓存技术方案

主要学习几个注解:@CachePut、@Cacheable、@CacheEvict、@CacheConfig

@Cacheable

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

参数解释example
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:
@Cacheable(value=”mycache”)
@Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

 @CachePut

@CachePut 的作用 主要针对方法配置,能够根据方法的返回值对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用,在其他地方写的是根据方法的请求参数对其结果进行缓存,实际是按方法返回值进行缓存的,这里我就遇到了一个坑,我开始的时候是在Mybatis的Mapper层进行缓存的,如下面的代码。但是缓存到Redis的是Null值,今天看了一博友的博客,交流了一下,才知道它缓存的是方法的返回值,如果把下面update的返回值该为int,在redis中保存的是int类型,报的错误是int无法转换成User对象。

    @CachePut(value="user",key = "#p0.id")
    @Update({"UPDATE user SET name=#{name},age=#{age} WHERE id =#{id}"})
    void update(User user);
参数解释example
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个@CachePut(value=”my cache”)
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合@CachePut(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存@CachePut(value=”testcache”,condition=”#userName.length()>2”)

 @CachEvict

 @CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空

参数解释example
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个@CacheEvict(value=”my cache”)
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合@CacheEvict(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存@CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存@CachEvict(value=”testcache”,beforeInvocation=true)

@CacheConfig

所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。

1、在Maven pom.xml文件中加入Redis包

1

2

3

4

5

6

<!--redis-->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-redis</artifactId>

    <version>${boot.version}</version>

</dependency>

 

2、SpringBoot配置文件中配置Redis连接(YAML方式配置)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

spring:

    application:

        name: spring-boot-redis

    redis:

        host: 192.168.145.132

        port: 6379

        timeout: 20000

        cluster:

            nodes: 192.168.211.134:7000,192.168.211.134:7001,192.168.211.134:7002

            maxRedirects: 6

        pool:

            max-active: 8

            min-idle: 0

            max-idle: 8

            max-wait: -1

解释:本配置采用Redis一主三从的的配置方式来提高缓存的吞吐量

 

3、Redis配置类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@Configuration

public class RedisConfig {

 

   @Bean

   public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {

      RedisTemplate<Object, Object> template = new RedisTemplate<>();

      template.setConnectionFactory(connectionFactory);

 

      //使用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);

 

      template.setValueSerializer(serializer);

      //使用StringRedisSerializer来序列化和反序列化redis的key值

      template.setKeySerializer(new StringRedisSerializer());

      template.afterPropertiesSet();

      return template;

   }

}

解释:SpringBoot提供了对Redis的自动配置功能,在RedisAutoConfiguration中默认为我们配置了JedisConnectionFactory(客户端连接)、RedisTemplate以及StringRedisTemplate(数据操作模板),其中StringRedisTemplate模板只针对键值对都是字符型的数据进行操作,本示例采用RedisTemplate作为数据操作模板,该模板默认采用JdkSerializationRedisSerializer的二进制数据序列化方式,为了方便演示本示例采用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值,使用StringRedisSerializer来序列化和反序列化redis的key值。

 

4、Service层应用缓存(注解方式)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

@Service

public class PersonService {

 

    @Autowired

    private PersonRepo personRepo;

 

   /**

     * @Cacheable 应用到读取数据的方法上,先从缓存中读取,如果没有再从DB获取数据,然后把数据添加到缓存中

    * unless 表示条件表达式成立的话不放入缓存

     * @param username

     * @return

     */

    @Cacheable(value = "user", key = "#root.targetClass + #username", unless = "#result eq null")

    public Person getPersonByName(String username) {

        Person person = personRepo.getPersonByName(username);

        return person;

    }

 

   /**

    * @CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存

     * @param person

     * @return

     */

    @CachePut(value = "user", key = "#root.targetClass + #result.username", unless = "#person eq null")

    public Person savePerson(Person person) {

        return personRepo.savePerson(person);

    }

 

   /**

    * @CacheEvict 应用到删除数据的方法上,调用方法时会从缓存中删除对应key的数据

     * @param username

     * @return

     */

    @CacheEvict(value = "user", key = "#root.targetClass + #username", condition = "#result eq true")

    public boolean removePersonByName(String username) {

        return personRepo.removePersonByName(username) > 0;

    }

 

    public boolean isExistPersonName(Person person) {

        return personRepo.existPersonName(person) > 0;

    }

}

解释:

 

1、这里的缓存key为简单的字符串组合,也可根据具体需要实现自定义的Key生成器,然后在注解中使用keyGenerator来引用。

 

2、Spring Cache提供了一些供我们使用的SpEL上下文数据,通过#来引用,具体可查看Spring官网:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#cache-spel-context。

 

5、数据访问资源类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

@Component

@Path("personMgr")

public class PersonMgrResource {

 

    @Autowired

    private PersonService personService;

 

    @GET

    @Path("getPersonByName")

    @Produces(MediaType.APPLICATION_JSON)

    public JsonResp getPersonByName(@QueryParam("username") String username) {

        Person person = personService.getPersonByName(username);

        return JsonResp.success(person);

    }

 

    @POST

    @Path("removePersonByName")

    @Produces(MediaType.APPLICATION_JSON)

    public JsonResp removePersonByName(@QueryParam("username") String username) {

        if (personService.removePersonByName(username)) {

            return JsonResp.success();

        }

        return JsonResp.fail("系统错误!");

    }

 

    @POST

    @Path("savePerson")

    @Produces(MediaType.APPLICATION_JSON)

    public JsonResp savePerson(Person person) {

        if (personService.isExistPersonName(person)) {

            return JsonResp.fail("用户名已存在!");

        }

        if (personService.savePerson(person).getId() > 0) {

            return JsonResp.success();

        }

        return JsonResp.fail("系统错误!");

    }

}

 

6、通过postman工具来测试缓存是否生效

 

第一次访问查找用户:

 

 

 

第一次通过用户名称来查找用户可以看到是从库中查询的数据,我们可以通过RedisClient工具来查看数据已放入了缓存

 

第二次查找用户:发现服务端并未打印任何数据库查询日志,可以知道第二次查询是从缓存中查询得到的数据。

 

总结

本文介绍如何通过SpringBoot来一步步集成Redis缓存,关于Redis的使用它不仅可以用作缓存,还可以用来构建队列系统,Pub/Sub实时消息系统,分布式系统的的计数器应用,关于Redis更多的介绍,请前往查阅官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值