admin 1 год назад
Родитель
Сommit
ef0f2e2477

+ 86 - 0
caffeineSpringBoot/pom.xml

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.example</groupId>
+    <artifactId>caffeineSpringBoot</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.2.RELEASE</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.gjing</groupId>
+            <artifactId>tools-common</artifactId>
+            <version>1.0.4</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.gjing</groupId>
+            <artifactId>tools-starter-swagger</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-cache</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+            <version>2.7.0</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 93 - 0
caffeineSpringBoot/src/main/java/org/example/CaffeineConfig.java

@@ -0,0 +1,93 @@
+package org.example;
+
+
+import com.github.benmanes.caffeine.cache.*;
+import lombok.NonNull;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.lang.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+public class CaffeineConfig {
+    @Bean
+    public Cache caffeineCache(){
+        return Caffeine.newBuilder()
+                //设置10秒后过期,方便后续观察现象
+                .expireAfterWrite(10, TimeUnit.SECONDS)
+                //初始容量为100
+                .initialCapacity(100)
+                //最大容量为200
+                .maximumSize(200)
+                .build();
+    }
+
+    //定义manualCaffeineCache,用来演示手动加载
+    @Bean
+    @Qualifier(value = "manualCaffeineCache")
+    public Cache manualCaffeineCache(){
+        return Caffeine.newBuilder()
+                .expireAfterWrite(10,TimeUnit.SECONDS)
+                .initialCapacity(50)
+                .maximumSize(100)
+                .build();
+    }
+
+    // LoadingCache通过关联一个CacheLoader来构建Cache,
+    // 当缓存未命中会调用CacheLoader的load方法生成V,
+    // 还可以通过LoadingCache的getAll方法批量查询,
+    // 当CacheLoader未实现loadAll方法时, 会批量调用load方法聚合会返回。
+    // 当CacheLoader实现loadAll方法时, 则直接调用loadAll返回。
+    @Bean
+    @Qualifier(value = "loadingCaffeineCache")
+    public LoadingCache<String, Object> loadingCaffeineCache(){
+        return Caffeine.newBuilder()
+                .expireAfterWrite(60, TimeUnit.SECONDS)
+                .maximumSize(500)
+                .build(new CacheLoader<String, Object>() {
+                    //缓存未命中时,使用下面的方法生成value
+                    @Override
+                    public @Nullable Object load(@NonNull String key) throws Exception {
+                        User user=new User();
+                        user.setId(-1);
+                        user.setUsername(key);
+                        user.setPassword(key);
+                        return user;
+                    }
+                    @Override
+                    public Map<String,Object> loadAll(Iterable<? extends String>keys){
+                        Map<String,Object>map=new HashMap<>();
+                        for (String key:keys){
+                            User user=new User();
+                            user.setId(-1);
+                            user.setUsername(key);
+                            user.setPassword(key);
+                            map.put(key,user);
+                        }
+                        return map;
+                    }
+                });
+    }
+
+    // 配置监听器
+    @Bean
+    @Qualifier(value = "listenerCaffeineCache")
+    public Cache listenerCaffeineCache(){
+        return Caffeine.newBuilder()
+                .expireAfterWrite(10,TimeUnit.SECONDS)
+                .initialCapacity(100)
+                .maximumSize(200)
+                .removalListener((key,value,cause)->{
+                    System.out.println("removalListener:key="+key+",value="+value+",cause="+cause);
+                })
+                .build();
+    }
+
+
+}
+

+ 15 - 0
caffeineSpringBoot/src/main/java/org/example/Main.java

@@ -0,0 +1,15 @@
+package org.example;
+
+import cn.gjing.core.EnableSwagger;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+@SpringBootApplication
+@EnableSwagger
+@EnableCaching
+public class Main {
+    public static void main(String[] args) {
+        SpringApplication.run(Main.class, args);
+    }
+}

+ 22 - 0
caffeineSpringBoot/src/main/java/org/example/User.java

@@ -0,0 +1,22 @@
+package org.example;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+
+@Data
+@TableName(value = "user")
+@ToString
+public class User implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+    private String username;
+    private String password;
+    private String sex;
+    private Integer age;
+}
+

+ 9 - 0
caffeineSpringBoot/src/main/java/org/example/UserMapper.java

@@ -0,0 +1,9 @@
+package org.example;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+}
+

+ 10 - 0
caffeineSpringBoot/src/main/java/org/example/UserService.java

@@ -0,0 +1,10 @@
+package org.example;
+
+public interface UserService {
+    Boolean saveUser(User user);
+    Boolean updateUser(User user);
+    Boolean deleteUserById(Integer id);
+    User getUserById(Integer id);
+}
+
+

+ 63 - 0
caffeineSpringBoot/src/main/java/org/example/UserServiceImpl.java

@@ -0,0 +1,63 @@
+package org.example;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class UserServiceImpl implements UserService {
+    @Autowired
+    private UserMapper userMapper;
+    @Resource
+    private Cache<String,Object>caffeineCache;
+
+    @Override
+    public Boolean saveUser(User user) {
+        return userMapper.insert(user)>0;
+    }
+
+    @Override
+    public Boolean updateUser(User user) {
+        if (user.getId()==null){
+            return false;
+        }
+        if(userMapper.updateById(user)>0){
+            //删除缓存
+            caffeineCache.asMap().remove(user.getId()+"");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean deleteUserById(Integer id) {
+        if (userMapper.deleteById(id)>0){
+            //删除缓存
+            caffeineCache.asMap().remove(id+"");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public User getUserById(Integer id) {
+        User user=(User)caffeineCache.asMap().get(id+"");
+        if (user!=null){
+            log.info("从缓存中获取==============");
+            return user;
+        }
+        log.info("从数据库中获取===============");
+        user=userMapper.selectById(id);
+        if (user==null){
+            log.info("数据为空===========");
+            return null;
+        }
+        caffeineCache.put(id+"",user);
+        return user;
+    }
+}
+

+ 32 - 0
caffeineSpringBoot/src/main/resources/application.yaml

@@ -0,0 +1,32 @@
+server:
+  port: 8080
+spring:
+  application:
+    name: springboot-cache-demo
+  # 配置数据库信息和连接池
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/cacheCaffeine?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
+    password: 5608095liyukun
+    username: root
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    type: com.zaxxer.hikari.HikariDataSource
+    hikari:
+      minimum-idle: 1
+      maximum-pool-size: 15
+      idle-timeout: 30000
+      connection-timeout: 20000
+  # 开启jpa自动建表
+  jpa:
+    database: mysql
+    hibernate:
+      ddl-auto: update
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+  # 配置缓存,初始缓存容量,最大容量,过期时间(这里配置写入后过期时间)
+  cache:
+    type: caffeine
+    caffeine:
+      spec: initialCapacity=10,maximumSize=200,expireAfterWrite=3s
+# 配置controller路径
+swagger:
+  base-package: org.example
+  title: springboot使用caffeine缓存

+ 113 - 0
caffeineSpringBoot/src/test/java/Caffine02ApplicationTest.java

@@ -0,0 +1,113 @@
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+import org.example.Main;
+import org.example.User;
+import org.example.UserService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest(classes = Main.class)
+@Slf4j
+public class Caffine02ApplicationTest {
+    @Autowired
+    private UserService userService;
+
+    @Resource
+    @Qualifier(value = "manualCaffeineCache")
+    private Cache<String,String> manualCaffineCache;
+
+    @Resource
+    @Qualifier(value = "loadingCaffeineCache")
+    private LoadingCache<String,Object> loadingCaffeineCache;
+
+    @Resource
+    @Qualifier(value = "listenerCaffeineCache")
+    private Cache<String,Object>listenerCaffeineCache;
+
+    @Test
+    public void testCache(){
+        //获取缓存
+        User user = userService.getUserById(1);
+        log.info("第一次从数据库获取缓存:{}",user);
+        user=userService.getUserById(1);
+        log.info("第二次从缓存中获取:{}",user);
+        //过期时间为10秒,我们10秒后再获取
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        user=userService.getUserById(1);
+        log.info("10秒后再次获取user:{}",user);
+    }
+
+    @Test
+    public void testManualCaffeineCache(){
+        //将数据放入缓存
+        manualCaffineCache.put("The best language","java");
+        //获取key对应的value,如果不存在,返回null
+        String the_best_language = manualCaffineCache.getIfPresent("The best language");
+        System.out.println(the_best_language);
+        //删除entry
+        manualCaffineCache.invalidate("The best language");
+        the_best_language= manualCaffineCache.getIfPresent("The best language");
+        System.out.println(the_best_language);
+
+        //以map的形式进行增删改查==================
+        manualCaffineCache.asMap().put("best","java");
+        manualCaffineCache.asMap().put("best1","SpringBoot");
+        String best = manualCaffineCache.asMap().get("best");
+        String best1 = manualCaffineCache.asMap().get("best1");
+        System.out.println("best:"+best);
+        System.out.println("best1:"+best1);
+        //删除entry
+        manualCaffineCache.asMap().remove("best");
+        manualCaffineCache.asMap().remove("best1");
+        best = manualCaffineCache.asMap().get("best");
+        best1 = manualCaffineCache.asMap().get("best1");
+        System.out.println("best:"+best);
+        System.out.println("best1:"+best1);
+    }
+
+    @Test
+    public void testLoadingCaffeineCache(){
+        User user=new User();
+        user.setId(1);
+        user.setUsername("cxy");
+        user.setPassword("123456");
+        user.setAge(20);
+        user.setSex("男");
+        loadingCaffeineCache.put("1",user);
+        User res=(User)loadingCaffeineCache.getIfPresent("1");
+        System.out.println("res:"+res);
+        res=(User)loadingCaffeineCache.getIfPresent("2");
+        System.out.println("res:"+res);
+        List<String> list= Arrays.asList("1","2","3");
+        Map<@NonNull String, @NonNull Object> resMap = loadingCaffeineCache.getAllPresent(list);
+        System.out.println("resMap:"+resMap);
+        System.out.println("上面调用的都是IfPresent(),即存在才返回,因此不会触发我们刚才的两个load函数==========");
+        res=(User)loadingCaffeineCache.get("2");
+        System.out.println("res:"+res);
+        resMap= loadingCaffeineCache.getAll(list);
+        System.out.println("resMap:"+resMap);
+    }
+
+    @Test
+    public void testListenerCaffeineCache() throws InterruptedException {
+        listenerCaffeineCache.put("cxy","程序员");
+        listenerCaffeineCache.put("best","java");
+        listenerCaffeineCache.invalidate("cxy");
+        listenerCaffeineCache.asMap().remove("best");
+    }
+}
+