springboot与缓存cache笔记

x33g5p2x  于2022-03-17 转载在 Spring  
字(9.6k)|赞(0)|评价(0)|浏览(382)

springboot与缓存cache

1.原始硬编码的方式

1.查询利用缓存

在业务层中编码:
    @Autowired
    private UserMapper userMapper;
    private HashMap<Integer,User> cache = new HashMap<Integer,User>();
    @Override
    public User findById(Integer id) {
        User user1 = cache.get(id);
        //如果cache中即缓存中有user1
        if (user1==null){
            User user = userMapper.selectById(id);
            cache.put(id,user);
            return user;
        }
        return user1;
    }

2.临时文件利用缓存

@Service
public class MsgServiceImpl implements MsgService {
    private HashMap<String,String> cache = new HashMap<>();
    @Override
    public String set(String tele) {
        String code = tele.substring(tele.length() - 6);
        return cache.put(tele,code );
    }

    @Override
    public boolean check(String tele, String code) {
        String querycode = cache.get(tele);
        return querycode.equals(code);
    }
}

//controller层

@RestController
@RequestMapping("msg")
public class MsgController {
    @Autowired
    private MsgService msgService;

    @GetMapping("{tele}")
    public String set(@PathVariable String tele){
    return msgService.set(tele);
    }
    @PostMapping
    public boolean get(String tele,String code){
        boolean check = msgService.check(tele, code);
        return check;
    }
}

2.springboot与缓存cache整合

1.临时文件的缓存

导入坐标
 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
     
加入注解
@EanbleCaching 在启动类上  //开启缓存功能
@cacheable  在要存入缓存和读缓存的方法上加入  //操作数据结果进入缓存
@cacheput 只存不读

工具类获取验证码:@Component
public class SMSCodeUntiles {
    private String[] str = {"00000", "0000", "000", "00", "0", ""};

    public String generator(String tele) {
        //以下是电话验证码的加密
        int hash = tele.hashCode();
        int end = 2022315;
        long result = hash ^ end;
        Long nowTime = System.currentTimeMillis();
        result = nowTime ^ result;
        long code = result % 1000000;
        code = code > 0 ? code : -code;
        String codeStr = code + "";
        if (codeStr.length() < 6) {
            codeStr = str[codeStr.length() - 1] + codeStr;
        }
        return codeStr;
    }
    
	//从缓存中读取数据要放到spring能读取到的地方
    @Cacheable(value = "SMSSpace", key = "#tele")
    public String get(String tele) {
        return null;
    }
业务层:
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @Autowired
    private SMSCodeUntiles sms;

    @Override
    @CachePut(value = "SMSSpace",key = "#tele")//将操作结果数据存入数据
    public String sendCodeSMS(String tele) {
        //获取验证码
        return sms.generator(tele);
    }
//写入的验证码与生成的验证码(在缓存中)进行对比
    @Override
    public boolean checkCode(SMSCode smsCode) {
        String code = smsCode.getCode();
        //从缓存中取出数据
        String checkCode = sms.get(smsCode.getTele());
        return checkCode.equals(code);
    }

3.变更缓存供应商

1.Ehcache

首先导入坐标:
		<dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
      
在yml配置文件中加入
spring.cache.type: ehcache     //是缓存供应商有simple变成ehcache 
spring.ehcache.config: ehcache.xml  //设置配置文件
配置文件: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"
        eternal="false"
        diskPersistent="false"
        maxElementsInMemory="1000"
        overflowToDisk="false"
        timeToIdleSeconds="10"
        timeToLiveSeconds="10"
        memoryStoreEvictionPolicy="LRU" />

</ehcache>

2.Redis供应商

导入坐标:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
       
spring:       
 cache:
    type: ehcache
    ehcache:
      config: ehcache.xml
    redis:
      use-key-prefix: true #是否显示前缀
      cache-null-values: false #是否缓存空值
      key-prefix: aaa  #设置redis中的键前缀为aaa
      time-to-live: 10 #设置生命周期为10秒
  redis:
    host: localhost
    port: 6379
    当然还有很多配置...以后学习慢慢补充

3.memcached缓存供应商

springboot对memcached没有整合需要使用硬编码方式实现客户端初始化管理
客户端:Xmemcached : 并发处理更好
导入坐标:
    <dependency>
        <groupId>com.googlecode.xmemcached</groupId>
        <artifactId>xmemcached</artifactId>
        <version>2.4.7</version>
    </dependency>
进行配置:
@Configuration
public class MemcachedConfig {
    @Bean
    public MemcachedClient getMemcachedClient() throws IOException {
        MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
        MemcachedClient memcachedClient =memcachedClientBuilder.build();
        return memcachedClient;
    }
}

业务层代码更改:
    @Autowired
    private MemcachedClient memcachedClient;
    @Autowired
    private SMSCodeUntiles sms;
    //以下是memcached供应商处理
    @Override
    @CachePut(value = "SMSSpace", key = "#tele")//将操作结果数据存入数据
    public String sendCodeSMS(String tele) {
        String code = sms.generator(tele);//生成验证码
        try {
            memcachedClient.set(tele, 0, code);//将生成的验证码以tele为键值存入缓存中,0代表永不过时
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (MemcachedException e) {
            e.printStackTrace();
        }
        return code;
    }

    @Override
    public boolean checkCode(SMSCode smsCode) {
        String code = null;
        try {
            code = memcachedClient.get(smsCode.getTele().toString());//根据电话从缓存中获取中
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (MemcachedException e) {
            e.printStackTrace();
        }
        //获取输入的验证码
        String checkCode = smsCode.getCode();
        return checkCode.equals(code);
    }

4.Jetcache

​ 定义:是对SpringCache进行封装,在原有的功能上实现了多级缓存,缓存统计,自动刷新,异步调用,数据报表等等…

多级缓存方案

本地缓存:(local)

​ ●LinkedHashMap

​ ●Caffeine

远程缓存:(remote)

​ ●Redis

​ ●Tair

首先要导入坐标:

<dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-starter-redis</artifactId>
            <version>2.6.2</version>
        </dependency>//这个坐标springboot没有整合,所以需要导入版本号

在启动类上加入一个注解@EnableCreateCacheAnnotation 这是jetcache启用注解缓存的开关

远程缓存:(remote) 默认的缓存方式

在yml配置文件中写入:

jetcache:
  remote:
    default:      #默认的配置
      type: redis
      host: localhost
      port: 6379
      poolConfig:    #配置必须要写,如果不写将报一个初始化错误
        maxTotal: 50   #最大连接数

在需要添加缓存的类中加入:

@CreateCache(name = "jetcache" 
                ,expire = 3600 //定义超时时间
                ,timeUnit = TimeUnit.MINUTES //定超时时间单位
                 )
    private Cache<String,String> cache;

将获取的值存入到缓存中:

cache.put(tele,code); //存入缓存

从缓存中取值:

String code = cache.get(smsCode.getTele()); //从缓存中取出数据

重要:

当springboot版本>=2.6版本时则会报一个循环依赖的错误,则需要在配置文件中写入即可:
	spring:
		  main:
   			 allow-circular-references: true //默认为false
本地缓存(local):linkedhashmap

在yml文件中:

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson #类型转换

@CreateCache(name = "jetScape"
                ,expire = 3600 //定义超时时间
                ,timeUnit = TimeUnit.MINUTES //定超时时间单位
                ,cacheType = CacheType.LOCAL //确定使用什么缓存,使用本地缓存 默认是使用远程,本地都要缓存
            )
    private Cache<String,String> cache;
jetcache方法缓存

启用方法注解

@SpringBootApplication
@EnableCreateCacheAnnotation
@EnableMethodCache(basePackages = "cn.itcast") //开启方法注解缓存 这两个注解是共存的
public class Spring0108Jetcache2Application {

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

}

使用方法注解操作缓存

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Cached(name = "book",key = "#id",expire = 3600,timeUnit = TimeUnit.MINUTES

            ,cacheType = CacheType.REMOTE
    )
    @CacheRefresh(refresh = 10) //经过一段时间后刷新一次缓存
    @Override
    public User findById(Integer id) {
        User user = userMapper.selectById(id);
        return user;
    }
    @CacheUpdate(name = "user_",key = "#user.id",value="#user") //一旦更新之后就会把更新的数据放入到内存中
    @Override
    public boolean update(User user) {
        return userMapper.updateById(user) > 0;
    }
    @CacheInvalidate(name = "user_",key = "#id")
    @Override
    public boolean delete(Integer id) {
        return userMapper.deleteById(id) > 0;
    }

缓存对象必须保证可序列化

public class User implements Serializable //实现序列化功能

jetcache:
  statIntervalMinutes: 1 #查看缓存统计报告 1min
  remote:
    default:      #默认的配置
      type: redis
      host: localhost
      port: 6379
      keyConvertor: fastjson
      valueEncode: java #序列化存
      valueDecode: java #取得时候转换成java
      poolConfig:    #配置必须要写
        maxTotal: 50   #最大连接数

5.j2cache是一个缓存框架,可以和各种缓存搭配使用,实现一级,二级缓存

redis+ehcache整合

导入坐标:

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
</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>

在yml文件中设置配置文件

j2cache:
  config-location: j2cache.properties

在j2cache.properties中配置一级缓存,二级缓存以及一级缓存到二级缓存的发送方式(以下的配置是最简单的配置,是必不可少的,只可补充,不可删除)

#一级缓存
# 一级缓存使用什么技术
j2cache.L1.provider_class = ehcache 

#设置是否启用二级缓存
j2cache.l2-cache-open = false

#加载ehcache的配置文件
ehcache.configXml = ehcache.xml

#二级缓存
#配置类
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.cofig_section = redis
redis.host = localhost:6379

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

redis.mode = single

#配置前置名
redis.namespace = user_

设置使用缓存

@Autowired
    private CacheChannel cacheChannel;

    @Override
    public String sendCodeSMS(String tele) {
        String code =sms.generator(tele);
        cacheChannel.set("sms",tele,code); //存入缓存数据
        return code;
    }

    @Override
    public boolean checkCode(SMSCode smsCode) {
        String code = cacheChannel.get("sms", smsCode.getCode()).asString(); //从缓存中读取,
        return smsCode.getCode().equals(code);
    }

6.总结

1.spring-cache

●simple(默认)

●ehcache(需要有一个ehcache.xml文件)

●redis

​ ●memcached

2.jetcache

3.j2cache(要有一个j2cache.properties文件)

相关文章