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坐标



    org.springframework.boot
    spring-boot-starter-cache



    net.sf.ehcache
    ehcache

 4.2创建Ehcache的配置文件,提供ehcache的基本配置

文件名:ehcache.xml

位置:src/main/resources/ehcache.xml 

ehcach配置:找到ehcache的jar包,打开ehcache-failsafe.xml文件,内容复制到ehcache.xml文件中。



    
    
    
                maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    defaultCache>
    
                maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    cache>

   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 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相关的坐标



    org.springframework.boot
    spring-boot-starter-data-redis

 

  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 getRedisTemplate(RedisConnectionFactory factory){
        RedisTemplate redisTemplate=new RedisTemplate();
        //设置连接的工厂对象
        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字符串。

     *

Title: pojoToJson

     *

Description:

     * @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 jsonToPojo(String jsonData, Class beanType) {

        try {

            T t = MAPPER.readValue(jsonData, beanType);

            return t;

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    /**

     * 将json数据转换成pojo对象list

     *

Title: jsonToList

     *

Description:

     * @param jsonData

     * @param beanType

     * @return

     */

    public static List jsonToList(String jsonData, Class beanType) {

        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);

        try {

            List 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 redisTemplate;

    @Override
    public List getGoodsAll() {
        List list=null;
        //判断redis数据库中是否存在,如果存在,直接获取,如果不存在,从mysql中获取,并存入到redis中
        if(redisTemplate.hasKey("goodsList")){
            list= JsonUtils.jsonToList(redisTemplate.opsForHash().values("goodsList").toString(),Goods.class);
        }else{
            list=goodsMapper.selectAll();
            Map map=new HashMap<>();
            for (Goods goods:list) {
                map.put(goods.getId(),JsonUtils.objectToJson(goods));
            }
            redisTemplate.opsForHash().putAll("goodsList",map);
        }
        return list;
    }
}

相关