spring boot 使用Spring Cache集成Redis

}

添加依赖


在 pom.xml 中添加 spring-boot-starter-data-redis的依赖

org.springframework.boot

spring-boot-starter-data-redis

org.apache.commons

commons-pool2

org.springframework.boot

spring-boot-starter-test

test

属性配置


在 application.properties 文件中配置如下内容,由于Spring Boot2.x 的改动,连接池相关配置需要通过spring.redis.lettuce.pool 或者 spring.redis.jedis.pool 进行配置了。使用了Spring Cache后,能指定spring.cache.type就手动指定一下,虽然它会自动去适配已有Cache的依赖,但先后顺序会对Redis使用有影响(JCache -> EhCache -> Redis -> Guava

spring.redis.host=localhost

spring.redis.password=battcn

# 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配

spring.cache.type=redis

# 连接超时时间(毫秒)

spring.redis.timeout=10000

# Redis默认情况下有16个分片,这里配置具体使用的分片

spring.redis.database=0

# 连接池最大连接数(使用负值表示没有限制) 默认 8

spring.redis.lettuce.pool.max-active=8

# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1

spring.redis.lettuce.pool.max-wait=-1

# 连接池中的最大空闲连接 默认 8

spring.redis.lettuce.pool.max-idle=8

# 连接池中的最小空闲连接 默认 0

spring.redis.lettuce.pool.min-idle=0

具体编码


实体类

创建一个User类,目的是为了模拟对象存储

package com.battcn.entity;

import java.io.Serializable;

/**

  • @author Levin

  • @since 2018/5/11 0007

*/

public class User implements Serializable {

private static final long serialVersionUID = 8655851615465363473L;

private Long id;

private String username;

private String password;

// TODO 省略get set

}

定义接口

package com.battcn.service;

import com.battcn.entity.User;

_/**

  • @author Levin

  • @since 2018/5/11 0011

*/_

public interface UserService {

_/**

  • 删除

  • @param user 用户对象

  • @return 操作结果

*/_

User saveOrUpdate(User user);

_/**

  • 添加

  • @param id key值

  • @return 返回结果

*/_

User get(Long id);

_/**

  • 删除

  • @param id key值

*/_

void delete(Long id);

}

###实现类

为了方便演示数据库操作,直接定义了一个Map<Long, User> DATABASES,这里的核心就是@Cacheable@CachePut@CacheEvict 三个注解

package com.battcn.service.impl;

import com.battcn.entity.User;

import com.battcn.service.UserService;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.CachePut;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.stereotype.Service;

import java.util.HashMap;

import java.util.Map;

_/**

  • @author Levin

  • @since 2018/5/11 0011

*/_

@Service

public class UserServiceImpl implements UserService {

private static final Map<Long, User> DATABASES = new HashMap<>();

static {

DATABASES.put(1L, new User(1L, “u1”, “p1”));

DATABASES.put(2L, new User(2L, “u2”, “p2”));

DATABASES.put(3L, new User(3L, “u3”, “p3”));

}

private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

@Cacheable(value = “user”, key = “#id”)// 根据方法的请求参数对其结果进行缓存

@Override

public User get(Long id) {

// TODO 我们就假设它是从数据库读取出来的

log.info(“进入 get 方法”);

return DATABASES.get(id);

}

@CachePut(value = “user”, key = “#user.id”)// 根据方法的请求参数对其结果进行缓存

@Override

public User saveOrUpdate(User user) {

DATABASES.put(user.getId(), user);

log.info(“进入 saveOrUpdate 方法”);

return user;

}

@CacheEvict(value = “user”, key = “#id”)// 根据条件对缓存进行清空

@Override

public void delete(Long id) {

DATABASES.remove(id);

log.info(“进入 delete 方法”);

}

}

主函数

@EnableCaching 必须要加,否则spring-data-cache相关注解不会生效…

package com.battcn;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cache.annotation.EnableCaching;

_/**

  • @author Levin

*/_

@SpringBootApplication

@EnableCaching

public class Chapter9Application {

public static void main(String[] args) {

SpringApplication.run(Chapter9Application.class, args);

}

}

测试

完成准备事项后,编写一个junit测试类来检验代码的正确性,有很多人质疑过Redis线程安全性,故下面也提供了响应的测试案例,如有疑问欢迎指正

package com.battcn;

import com.battcn.entity.User;

import com.battcn.service.UserService;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

_/**

  • @author Levin

  • @since 2018/5/10 0010

*/_

@RunWith(SpringRunner.class)

@SpringBootTest

public class Chapter9ApplicationTest {

private static final Logger log = LoggerFactory.getLogger(Chapter9ApplicationTest.class);

@Autowired

private UserService userService;

@Test

public void get() {

final User user = userService.saveOrUpdate(new User(5L, “u5”, “p5”));

log.info(“[saveOrUpdate] - [{}]”, user);

final User user1 = userService.get(5L);

log.info(“[get] - [{}]”, user1);

userService.delete(5L);

}

}

启动测试类,结果和我们期望的一致,可以看到增删改查中,查询是没有日志输出的,因为它直接从缓存中获取的数据,而添加、修改、删除都是会进入方法内执行具体的业务代码,然后通过切面去删除掉Redis中的缓存数据。其中 # 号代表这是一个 SpEL 表达式,此表达式可以遍历方法的参数对象,具体语法可以参考 Spring 的相关文档手册。

2018-05-14 09:20:55.303 INFO 21176 — [ main] com.battcn.service.impl.UserServiceImpl : 进入 saveOrUpdate 方法

2018-05-14 09:20:55.582 INFO 21176 — [ main] io.lettuce.core.EpollProvider : Starting without optional epoll library

2018-05-14 09:20:55.584 INFO 21176 — [ main] io.lettuce.core.KqueueProvider : Starting without optional kqueue library

2018-05-14 09:20:56.316 INFO 21176 — [ main] com.battcn.Chapter9ApplicationTest : [saveOrUpdate] - [User{id=5, username=‘u5’, password=‘p5’}]

2018-05-14 09:20:56.320 INFO 21176 — [ main] com.battcn.Chapter9ApplicationTest : [get] - [User{id=5, username=‘u5’, password=‘p5’}]

2018-05-14 09:20:56.322 INFO 21176 — [ main] com.battcn.service.impl.UserServiceImpl : 进入 delete 方法

其它类型

下列的就是Redis其它类型所对应的操作方式

  • opsForValue: 对应 String(字符串)

  • opsForZSet: 对应 ZSet(有序集合)

  • opsForHash: 对应 Hash(哈希)

  • opsForList: 对应 List(列表)

  • opsForSet: 对应 Set(集合)

  • opsForGeo: 对应 GEO(地理位置)

根据条件操作缓存

根据条件操作缓存内容并不影响数据库操作,条件表达式返回一个布尔值,true/false,当条件为true,则进行缓存操作,否则直接调用方法执行的返回结果。

  • 长度: @CachePut(value = "user", key = "#user.id",condition = "#user.username.length() < 10") 只缓存用户名长度少于10的数据

  • 大小: @Cacheable(value = "user", key = "#id",condition = "#id < 10") 只缓存ID小于10的数据

  • 组合: @Cacheable(value="user",key="#user.username.concat(##user.password)")

  • 提前操作: @CacheEvict(value="user",allEntries=true,beforeInvocation=true) 加上beforeInvocation=true后,不管内部是否报错,缓存都将被清除,默认情况为false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值