其他分享
首页 > 其他分享> > Spring Boot 缓存技术

Spring Boot 缓存技术

作者:互联网

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