springboot整合第三方技术:缓存

缓存

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

缓存使用

1.导入缓存技术对应的starter

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

2.启用缓存

@SpringBootApplication
//开启缓存功能
@EnableCaching
public class Springboot19CacheApplication {

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

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

@Cacheable(value="cacheSpace",key="#id")
public Book getById(Integer id) {
    return bookDao.selectById(id);
}

SpringBoot提供的缓存技术除了提供默认的缓存方案,还可以对其他缓存技术进行整合,统一接口,方便缓存技术的开发与管理:Generic、JCache、Hazelcast、Infinispan、Couchbase、Caffeine、Ehcache、Redis、memcached、simple(默认)

缓存使用案例

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

缓存供应商变更:Ehcache

1.加入Ehcache坐标

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

2.缓存设置为使用Ehcache

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
      username: root
      password: root
  cache:
    type: ehcache
    ehcache:
      config: ehcache.xml

3.提供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">
    <diskStore path="D:\ehcache" />

    <!--默认缓存策略 -->
    <!-- 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" />

    <cache
        name="smsCode" //通过name去管理不同的cache
        eternal="false"
        diskPersistent="false"
        maxElementsInMemory="1000"
        overflowToDisk="false"
        timeToIdleSeconds="10"
        timeToLiveSeconds="10"
        memoryStoreEvictionPolicy="LRU" />

</ehcache>

4.业务层方法

@Service
public class SMSCodeServiceImpl implements SMSCodeService {

    @Autowired
    private CodeUtils codeUtils;

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

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

5.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;
    }

//    public static void main(String[] args) {
//        System.out.println(new CodeUtils().generator("18866668888"));
//    }

}

缓存供应商变更:Redis

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

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

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

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
      username: root
      password: root
  cache:
    type: redis
  redis:
    host: localhost
    port: 6379

3.设置Redis相关配置

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

缓存供应商变更:memcached

安装memcached

管理员命令行下运行
memcached.exe -d isntall

运行memcached

1、启动服务
memcached.exe -d start
2、停止服务
memcached.exe -d stop

1.加入Xmemcached坐标

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

2.配置Xmemcached服务器必要属性

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

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

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

4.创建客户端配置类

@Configuration
public class XMemcachedConfig {

    @Autowired
    private XMemcachedProperties memcachedProperties;

    @Bean
    public MemcachedClient getMemcachedClient() throws IOException {
        MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(memcachedProperties.getServers());
        memcachedClientBuilder.setConnectionPoolSize(memcachedProperties.getPoolSize());
        memcachedClientBuilder.setOpTimeout(memcachedProperties.getOpTimeout());
        MemcachedClient memcachedClient = memcachedClientBuilder.build();
        return memcachedClient;
    }
}

5.配置memcached属性

@Service
public class SMSCodeServiceImpl implements SMSCodeService {

    //以下是springboot中使用xmemcached

    @Autowired
    private MemcachedClient memcachedClient;

    @Override
    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        try {
            memcachedClient.set(tele,10,code);   //
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;
    }

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

缓存供应商变更:jetcache(阿里)

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

远程缓存(remote):Redis;本地缓存(local):linkedhashmap
1.加入jetCache坐标

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

2.配置远程缓存必要的属性

jetcache:
  statIntervalMinutes: 15  
  areaInCacheName: false  
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
      limit: 100
    
  remote:
    default:          //默认的远程缓存
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50
    sms:             //自己定义的远程缓存的名字
      type: redis      
        host: localhost      
        port: 6379      
        poolConfig:       
          maxTotal: 50

3.开启jetCache注解支持

@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
public class Springboot20JetcacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot20JetcacheApplication.class, args);
    }
}

4.操作

@Service
public class SMSCodeServiceImpl implements SMSCodeService {

    @Autowired
    private CodeUtils codeUtils;

    //声明缓存对象
    @CreateCache(name="jetCache",expire = 3600)
    private Cache<String,String> jetCache;

    @Override
    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

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


}

使用方法注解操作缓存
1.开启方法注解

@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
//开启方法注解缓存,必须和@EnableCreateCacheAnnotation搭配使用
@EnableMethodCache(basePackages = "com.itheima")
public class Springboot20JetcacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot20JetcacheApplication.class, args);
    }

}

2.使用方法注解操作缓存

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;


    @Override
    @Cached(name = "book_",expire = 3600,key = "#id",cacheType = CacheType.REMOTE)
    @CacheRefresh(refresh = 5)//5分钟刷新一次缓存,因为删除数据之后再查询就只能从数据库中查询而不是走缓存
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }


    @Override
    public boolean save(Book book) {
        return bookDao.insert(book) > 0;
    }

    @Override
    @CacheUpdate(name = "book_",key = "#book.id",value = "#book")
    public boolean update(Book book) {
        return bookDao.updateById(book) > 0;
    }

    @Override
    @CacheInvalidate(name = "book_",key = "#id")//数据库缓存同步删除
    public boolean delete(Integer id) {
        return bookDao.deleteById(id) > 0;
    }

    @Override
    public List<Book> getAll() {
        return bookDao.selectList(null);
    }
}

3.缓存对象必须保障可序列化

@Data
public class Book implements Serializable {
    }
    
    
jetcache:
  statIntervalMinutes: 1
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
      valueEncode: java  //序列化转为Java对象
      valueDecode: java  
      limit: 100

  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      valueEncode: java
      valueDecode: java
      poolConfig:
        maxTotal: 50   

4.查看缓存统计报告

jetcache:
  statIntervalMinutes: 1

缓存供应商变更:j2cache

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

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

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
</dependency>

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

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

2.配置使用j2cache(application.yml)

server:
  port: 80

j2cache:
  config-location: j2cache.properties

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

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

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



#一级缓存的数据如何到达二级缓存
j2cache.broadcast =net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy

4.配置ehcache.xml(和使用ehcache缓存一样的配置)

<?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">
    <diskStore path="D:\ehcache" />

    <!--默认缓存策略 -->
    <!-- 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>

5.使用缓存

@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) {
        //取出内存中的验证码与传递过来的验证码比对,如果相同,返回true
        String code = cacheChannel.get("sms",smsCode.getTele()).asString();
        return smsCode.getCode().equals(code);
    }

}
  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值