springboot整合缓存cache详解

springboot整合缓存cache详解

缓存

缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质
使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能
缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间

缓存使用

导入缓存技术对应的starter

<dependency>    
	<groupId>org.springframework.boot</groupId>    
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

启用缓存

@SpringBootApplication
//开启缓存的注解
@EnableCaching
public class Springboot19CacheApplication {    
	public static void main(String[] args) {        
	SpringApplication.run(Springboot19CacheApplication.class, args);    
	}
}

设置当前操作的结果数据进入缓存

//value表示缓存空间名称,key表示存入的关键字,查询是根据key来查询
@Cacheable(value="cacheSpace",key="#id")
public Book getById(Integer id) {    
	return bookDao.selectById(id);
}

SpringBoot提供的缓存技术除了提供默认的缓存方案,还可以对其他缓存技术进行整合,统一接口,方便缓存技术的开发与管理

  • Generic
  • JCache
  • Ehcache
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple(默认)
  • memcached

需求
输入手机号获取验证码,组织文档以短信形式发送给用户(页面模拟)
输入手机号和验证码验证结果
需求分析
提供controller,传入手机号,业务层通过手机号计算出独有的6位验证码数据,存入缓存后返回此数据
提供controller,传入手机号与验证码,业务层通过手机号从缓存中读取验证码与输入验证码进行比对,返回比对结果

解决上诉需求
1.开启缓存

@SpringBootApplicatio
//下面注解开启缓存
@EnableCaching
public class Springboot19CacheApplication {    
	public static void main(String[] args) {        
		SpringApplication.run(Springboot19CacheApplication.class, args);    
	}
}

2.业务层接口

public interface SMSCodeService {   
	/**     
	* 传入手机号获取验证码,存入缓存    
	*  @param tele    
	*  @return     
	* */    
	String sendCodeToSMS(String tele);
    /**     
    * 传入手机号与验证码,校验匹配是否成功     
    *  @param smsCode     
    *  @return     
    * */    
    boolean checkCode(SMSCode smsCode);
}

3.业务层设置获取验证码操作,并存储缓存,手机号为key,验证码为value

@Autowired
private CodeUtils codeUtils;

@CachePut(value = "smsCode",key="#tele")
public String sendCodeToSMS(String tele) {    
	String code = codeUtils.generator(tele);    
	return code;
}

CodeUtils


@Component
public class CodeUtils {

    private String [] patch = {"000000","00000","0000","000","00","0",""};

    public String generator(String tele){
        int hash = tele.hashCode();
        int encryption = 20206666;
        long result = hash ^ encryption;
        long nowTime = System.currentTimeMillis();
        result = result ^ nowTime;
        long code = result % 1000000;
        code = code < 0 ? -code : code;
        String codeStr = code + "";
        int len = codeStr.length();
        return patch[len] + codeStr;
    }

    @Cacheable(value = "smsCode",key="#tele")
    public String get(String tele){
        return null;
    }

业务层设置校验验证码操作,校验码通过缓存读取,返回校验结果

@Autowired
private CodeUtils codeUtils;
public boolean checkCode(SMSCode smsCode) {    
//取出内存中的验证码与传递过来的验证码比对,如果相同,返回true
 	String code = smsCode.getCode();    
 	String cacheCode = codeUtils.get(smsCode.getTele());    
 	return code.equals(cacheCode);
 }

缓存供应商变更:Ehcache

加入Ehcache坐标(缓存供应商实现)

<dependency>   
	<groupId>net.sf.ehcache</groupId>   
	<artifactId>ehcache</artifactId>
</dependency>

缓存设定为使用Ehcache

spring:  
	cache:    
		type: ehcache    
		ehcache:      
			config: ehcache.xml

提供ehcache配置文件ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         
		xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"         
		updateCheck="false">    
		<!--默认缓存策略 -->    
		<!-- external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为false-->    
		<!-- diskPersistent:是否启用磁盘持久化-->    
		<!-- maxElementsInMemory:最大缓存数量-->   
		<!-- overflowToDisk:超过最大缓存数量是否持久化到磁盘-->
		<!-- timeToIdleSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果-->  
		<!-- timeToLiveSeconds:最大存活时间-->   
		<!-- memoryStoreEvictionPolicy:缓存清除策略-->    
		<defaultCache           
				eternal="false"            
				diskPersistent="false"           
				maxElementsInMemory="1000"           
				overflowToDisk="false"            
				timeToIdleSeconds="60"            
				timeToLiveSeconds="60"           
				memoryStoreEvictionPolicy="LRU" />
		</ehcache>

提供ehcache配置文件ehcache.xml

<cache            
		name="smsCode"            
		eternal="false"            
		diskPersistent="false"            
		maxElementsInMemory="1000"         
		overflowToDisk="false"            
		timeToIdleSeconds="10"            
		timeToLiveSeconds="10"            
		memoryStoreEvictionPolicy="LRU" />

缓存供应商变更:Redis

加入Redis坐标(缓存供应商实现)

<dependency>  
	<groupId>org.springframework.boot</groupId>   
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis服务器,缓存设定为使用Redis

spring:  
	redis:    
		host: localhost    
		port: 6379  
	cache:    
		type: redis
		use-key-prefix: true      # 是否使用前缀名(系统定义前缀名)
        key-prefix: sms_          # 追加自定义前缀名      
        time-to-live: 10s         # 有效时长      
        cache-null-values: false  # 是否允许存储空值

缓存供应商变更:memcached

下载memcached
地址:https://www.runoob.com/memcached/window-install-memcached.html

安装memcached
使用管理员身份运行cmd指令
在这里插入图片描述
安装输入下面命令,并配置到服务当中

memcached.exe -d install

运行memcached
启动服务

memcached.exe -d start

停止服务

memcached.exe -d stop

memcached客户端选择
Memcached Client for Java:最早期客户端,稳定可靠,用户群广
SpyMemcached:效率更高
Xmemcached:并发处理更好
SpringBoot未提供对memcached的整合,需要使用硬编码方式实现客户端初始化管理

加入Xmemcache坐标(缓存供应商实现)

<dependency>    
	<groupId>com.googlecode.xmemcached</groupId>    
	<artifactId>xmemcached</artifactId>    
	<version>2.4.7</version>
</dependency>

配置memcached服务器必要属性

memcached:    
	# memcached服务器地址    
	servers: localhost:11211    
	# 连接池的数量   
	poolSize: 10   
	# 设置默认操作超时    
	opTimeout: 3000

创建读取属性配置信息类,加载配置

@Component
@ConfigurationProperties(prefix = "memcached")
@Data
public class XMemcachedProperties {    
	private String servers;    
	private Integer poolSize;   
	private Long opTimeout;
}

创建客户端配置类

@Configuration
public class XMemcachedConfig {    
	@Autowired    
	private XMemcachedProperties xMemcachedProperties;    
	@Bean    
	public MemcachedClient getMemcachedClinet() throws IOException {        
		MemcachedClientBuilder builder = new XMemcachedClientBuilder(xMemcachedProperties.getServers());       
		MemcachedClient memcachedClient = builder.build();        
		return memcachedClient;   
		}
	}

配置memcached属性

@Service
public class SMSCodeServiceMemcacheImpl implements SMSCodeService {    
	@Autowired    
	private CodeUtils codeUtils;    
	@Autowired    
	private MemcachedClient memcachedClient;    
	@Override    
	public String sendCodeToSMS(String tele) {        
		String code = this.codeUtils.generator(tele);        
		//将数据加入memcache       
		try {            
			memcachedClient.set(tele,0,code);		
			// key,timeout,value        
		} catch (Exception e) {            
			e.printStackTrace();        
		}        
			return code;    
		}

	@Override   
	public boolean checkCode(CodeMsg codeMsg) {       
		String value = null;        
		try {           
			value = memcachedClient.get(codeMsg.getTele()).toString();        
		} catch (Exception e) {            
			e.printStackTrace();        
		}         
			return codeMsg.getCode().equals(value);    
		}
	}

缓存供应商变更:jetcache

jetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能
jetCache设定了本地缓存与远程缓存的多级缓存解决方案

  • 本地缓存(local)
    • LinkedHashMap
    • Caffeine
  • 远程缓存(remote)
    • Redis
    • Tair

加入jetcache坐标

<dependency>    
	<groupId>com.alicp.jetcache</groupId>    
	<artifactId>jetcache-starter-redis</artifactId>    
	<version>2.6.2</version>
</dependency>

配置远程缓存必要属性

jetcache:  
	remote:   
		default:      
			type: redis     
			host: localhost      
			port: 6379      
			poolConfig:        
				maxTotal: 50
		sms:      
			type: redis      
			host: localhost    
			port: 6379      
			poolConfig:        
				maxTotal: 50

配置本地缓存必要属性

jetcache: 
	local:    
		default:      
			type: linkedhashmap      
			keyConvertor: fastjson

配置范例

jetcache:  
	statIntervalMinutes: 15  
	areaInCacheName: false  
	local:    
		default:      
			type: linkedhashmap     
			keyConvertor: fastjson      
			limit: 100 
	remote:   
		default:      
			host: localhost      
			port: 6379      
			type: redis      
			keyConvertor: fastjson      
			valueEncoder: java      
			valueDecoder: java      
			poolConfig:        
				minIdle: 5       
				maxIdle: 20        
				maxTotal: 50

配置属性说明
在这里插入图片描述开启jetcache注解支持

@SpringBootApplication
@EnableCreateCacheAnnotation
public class Springboot19CacheApplication {    
	public static void main(String[] args) {        
		SpringApplication.run(Springboot19CacheApplication.class, args);    
	}
}

声明缓存对象

@Service
public class SMSCodeServiceImpl implements SMSCodeService {    
	@Autowired    
	private CodeUtils codeUtils;    
	@CreateCache(name = "smsCache", expire = 3600)    
	private Cache<String, String> jetSMSCache;
}

操作缓存

@Service
public class SMSCodeServiceImpl implements SMSCodeService {   
	@Override    
	public String sendCodeToSMS(String tele) {        
		String code = this.codeUtils.generator(tele);        
		jetSMSCache.put(tele,code);        
		return code;   
	}    
	@Override    
	public boolean checkCode(CodeMsg codeMsg) {        
		String value = jetSMSCache.get(codeMsg.getTele());        
		return codeMsg.getCode().equals(value);    
	}
}

启用方法注解
在启动类上加

@EnableMethodCache(basePackages = "com.itheima")

使用方法注解操作缓存

@Service
public class BookServiceImpl implements BookService {   
	@Autowired    
	private BookDao bookDao;   

	@Cached(name = "smsCache_", key = "#id", expire = 3600)    
	@CacheRefresh(refresh = 10,timeUnit = TimeUnit.SECONDS)   
	public Book getById(Integer id) {        
		return bookDao.selectById(id);    
	}

	@CacheUpdate(name = "smsCache_", key = "#book.id", value = "#book")    
	public boolean update(Book book) {        
		return bookDao.updateById(book) > 0;   
	}
    
	@CacheInvalidate(name = "smsCache_", key = "#id")    
	public boolean delete(Integer id) {        
		return bookDao.deleteById(id) > 0;    
	}
}

缓存对象必须保障可序列化(实现Serializable)

@Data
public class Book implements Serializable {
}

在这里插入图片描述
查看缓存统计报告

jetcache:  
	statIntervalMinutes: 15

缓存供应商变更:j2cache

j2cache是一个缓存整合框架,可以提供缓存的整合方案,使各种缓存搭配使用,自身不提供缓存功能
基于 ehcache + redis 进行整合

加入j2cache坐标,加入整合缓存的坐标

<dependency>   
	<groupId>net.oschina.j2cache</groupId>   
	<artifactId>j2cache-spring-boot2-starter</artifactId>    
	<version>2.8.0-release</version>
</dependency>
<dependency>    
	<groupId>net.oschina.j2cache</groupId>    
	<artifactId>j2cache-core</artifactId>    
	<version>2.8.4-release</version>
</dependency>
<dependency>    
	<groupId>net.sf.ehcache</groupId>    
	<artifactId>ehcache</artifactId>
</dependency>

配置使用j2cache(application.yml)

j2cache:  
	config-location: j2cache.properties

配置一级缓存与二级缓存以及一级缓存数据到二级缓存的发送方式(j2cache.properties)

# 配置1级缓存
j2cache.L1.provider_class = ehcache
ehcache.configXml = ehcache.xml

# 配置1级缓存数据到2级缓存的广播方式:可以使用redis提供的消息订阅模式,也可以使用jgroups多播实现
j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy

# 配置2级缓存
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section = redis
redis.hosts = localhost:6379

设置使用缓存

@Service
public class SMSCodeServiceImpl implements SMSCodeService {    
	@Autowired    
	private CodeUtils codeUtils;    
	@Autowired    
	private CacheChannel cacheChannel;

	@Override    
	public String sendCodeToSMS(String tele) {        
		String code = codeUtils.generator(tele);        
		cacheChannel.set("sms",tele,code);       
		return code;    
	}   

	@Override    
	public boolean checkCode(SMSCode smsCode) {        
		String code = cacheChannel.get("sms",smsCode.getTele()).asString();        
		return smsCode.getCode().equals(code);    
	}
}
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值