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 启动启动类,查看结果
第一次查询走mysql数据库,后面查询走ehcache缓存。
|
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; } }
|
标签:ehcache,缓存,return,Spring,redis,Boot,序列化,public
来源: https://www.cnblogs.com/akwlovezzy/p/16188283.html