1.缓存技术
缓存实际上是为了减轻数据库服务器的负载。使用缓存,可以将一些常用的数据放入到缓存中,在使用这些数据的时候,首先从缓存中查找,如果缓存中没有,才会到数据库中查询。
|
2.Spring Boot 缓存技术实现
Ehcache:将数据放入JVM内存中。支持2级:内存和硬盘
Redis: 存储在内存中的非关系型数据库。缓存数据库
|
3.前期准备springboot+mybatis+thymeleaf实现的商品CRUD实现
在springboot+mybatis+thymeleaf实现的商品CRUD基础上添加缓存功能
4.Spring Boot 整合Ehcache 缓存
4.1 打开pom.xml文件,引入ehcache相关的启动器以及jar坐标
<!--springboot支持缓存的启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!--ehcache坐标--> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency>
|
4.2创建Ehcache的配置文件,提供ehcache的基本配置
文件名:ehcache.xml
位置:src/main/resources/ehcache.xml
ehcach配置:找到ehcache的jar包,打开ehcache-failsafe.xml文件,内容复制到ehcache.xml文件中。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下: user.home – 用户主目录 user.dir – 用户当前工作目录 java.io.tmpdir – 默认临时文件路径 --> <diskStore path="java.io.tmpdir"/> <!--默认缓存策略 当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。--> <!-- name:缓存名称。 maxElementsInMemory:缓存最大数目 maxElementsOndisk:硬盘最大缓存个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowTodisk:是否保存到磁盘,当系统当机时 timetoIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timetoLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskSpoolBufferSizeMB:这个参数设置diskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreevictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 memoryStoreevictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。 FIFO,first in first out,这个是大家最熟的,先进先出。 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 --> <defaultCache maxElementsInMemory="10000" eternal="false" timetoIdleSeconds="120" timetoLiveSeconds="120" maxElementsOndisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreevictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </defaultCache> <!--自定义缓存策略--> <cache name="users" maxElementsInMemory="10000" eternal="false" timetoIdleSeconds="120" timetoLiveSeconds="120" maxElementsOndisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreevictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
|
4.3打开application.properties,设置ehcache.xml的路径
#配置ehcache配置文件的路径 spring.cache.ehcache.config=classpath:/ehcache.xml
|
4.4 修改启动类,开启缓存策略
@SpringBootApplication /*SpringBoot启动时,告诉springBoot去哪里扫描mybatis的mapper接口,生成实现类的对象*/ @MapperScan("com.xz.mapper") @EnableCaching /*开启Cache缓存*/ public class SpringBootMybatisThymeleafApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMybatisThymeleafApplication.class, args); } }
|
4.5 修改service业务层,指定哪些业务方法需要进行缓存
@Service @Transactional public class GoodsServiceImpl implements GoodsService { @Autowired GoodsMapper goodsMapper;
@Override
/*@Cacheable采用users的缓存策略,对当前查询的结果做缓存处理*/ @Cacheable(value="users") public List<Goods> getGoodsAll() { return goodsMapper.selectAll(); } }
|
4.6 序列化实体类
@AllArgsConstructor @NoArgsConstructor @Data @ToString public class Goods implements Serializable { private String id; private String name; private double price; private String image; }
|
4.7 启动启动类,查看结果
4.8 @Cacheable 与@Cacheevict 注解讲解
4.8.1 @Cacheable注解
@Cacheable 作用:把方法的返回值添加到 Ehcache 中做缓存
Value 属性:指定一个 Ehcache 配置文件中的缓存策略,如果没有给定value,则表示使用默认的缓存策略。
Key 属性:给存储的值起个名称。在查询时如果有名称相同的,那么则知己从缓存中将数据返回。
如果没有给定key,则表示使用方法的参数作为存储值的名称。
代码演示:查询单个商品信息
@RequestMapping("/getone") @ResponseBody public Goods getone(String id){ Goods goods=goodsService.getGoodsOne(id,1); return goods; }
@Override @Cacheable(value="users",key = "#num") public Goods getGoodsOne(String id,int num) { return goodsMapper.selectById(id); }
|
|
4.8.2 @Cacheevict注解
@Cacheevict 作用:清除缓存。
应用:当对缓存数据进行增,删,改操作时,需要数据同步。
代码演示:删除商品信息
@Override
/*@Cacheevict(value="users",allEntries=true) 清除缓存中以 users 缓存策略缓存的对象 */ @Cacheevict(value = "users",allEntries = true) public void delGoods(String id) { goodsMapper.deleteById(id); }
|
|
5. Spring Boot 整合redis 缓存(单机版)
5.1 打开linux 虚拟机,启动redis的服务器
5.2 打开pom.xml,添加redis相关的坐标
<!--redis启动器的坐标--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
|
5.3 打开application.properties全局配置文件,进行redis的相关配置
#redis相关配置 #连接redis服务器的主机名ip spring.redis.host=192.168.180.130 #连接redis服务器端口号 spring.redis.port=6379 #连接redis服务器的密码 spring.redis.password=123456 #配置连接redis使用的数据库索引 spring.redis.database=0 #配置redis连接池 #配置最大连接数.设置负数是无限值 spring.redis.jedis.pool.max-active=10 #最大空闲连接数 spring.redis.jedis.pool.max-idle=3 #配置最小空闲连接数 spring.redis.jedis.pool.min-idle=0 #设置最大等待时间ms spring.redis.jedis.pool.max-wait=-1
|
5.4 创建 Redistemplate对象: 用于执行 Redis 操作的方法
编写RedisConfig的配置类,在配置类中提供获取Redistemplate对象的bean方法
/** * 获取Redistemplate对象的配置类 */ @Configuration public class RedisConfig { @Bean public Redistemplate<String,Object> getRedistemplate(RedisConnectionFactory factory){ Redistemplate<String,Object> redistemplate=new Redistemplate<String,Object>(); //设置连接的工厂对象 redistemplate.setConnectionFactory(factory); //设置序列化器 :实现序列化和反序列化 //设置key的序列化器 redistemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化器 redistemplate.setValueSerializer(new StringRedisSerializer()); return redistemplate; } }
|
序列化器:实现序列化和反序列化操作
StringRedisSerializer : 简单的字符串序列化
JdkSerializationRedisSerializer: 序列化Java对象(默认)
Jackson2JsonRedisSerializer: 序列化Object对象为json格式字符串
5.5 拷贝JsonUtils的工具类到utils文件夹下
JsonUtils:实现对象和json格式的序列化的操作
public class JsonUtils {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* <p>Title: pojoToJson</p>
* <p>Description: </p>
* @param data
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsstring(data);
return string;
} catch (JsonProcessingException e) {
e.printstacktrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param clazz 对象中的object类型
* @return
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printstacktrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
* <p>Title: jsonToList</p>
* <p>Description: </p>
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printstacktrace();
}
return null;
}
}
|
5.5 修改service层,添加redis的缓存
@Service @Transactional public class GoodsServiceImpl implements GoodsService { @Autowired GoodsMapper goodsMapper; @Autowired Redistemplate<String,Object> redistemplate;
@Override public List<Goods> getGoodsAll() { List<Goods> list=null; //判断redis数据库中是否存在,如果存在,直接获取,如果不存在,从MysqL中获取,并存入到redis中 if(redistemplate.hasKey("goodsList")){ list= JsonUtils.jsonToList(redistemplate.opsForHash().values("goodsList").toString(),Goods.class); }else{ list=goodsMapper.selectAll(); Map<String,String> map=new HashMap<>(); for (Goods goods:list) { map.put(goods.getId(),JsonUtils.objectToJson(goods)); } redistemplate.opsForHash().putAll("goodsList",map); } return list; } }
|
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。