springboot與緩存(redis,或者caffeine,guava)


1.理論介紹

Java Caching定義了5個核心接口,分別是CachingProvider, CacheManager, Cache, Entry 和 Expiry。
CachingProvider定義了創建、配置、獲取、管理和控制多個CacheManager。一個應用可以在運行期訪問多個CachingProvider。
CacheManager定義了創建、配置、獲取、管理和控制多個唯一命名的Cache,這些Cache存在於CacheManager的上下文中。一個CacheManager僅被一個CachingProvider所擁有。
Cache是一個類似Map的數據結構並臨時存儲以Key為索引的值。一個Cache僅被一個CacheManager所擁有。
Entry是一個存儲在Cache中的key-value對。
Expiry 每一個存儲在Cache中的條目有一個定義的有效期。一旦超過這個時間,條目為過期的狀態。一旦過期,條目將不可訪問、更新和刪除。緩存有效期可以通過ExpiryPolicy設置。

Spring緩存抽象

Spring從3.1開始定義了org.springframework.cache.Cache
和org.springframework.cache.CacheManager接口來統一不同的緩存技術;
並支持使用JCache(JSR-107)注解簡化我們開發;

Cache接口為緩存的組件規范定義,包含緩存的各種操作集合;
Cache接口下Spring提供了各種xxxCache的實現;如RedisCache,EhCacheCache , ConcurrentMapCache等;

每次調用需要緩存功能的方法時,Spring會檢查檢查指定參數的指定的目標方法是否已經被調用過;如果有就直接從緩存中獲取方法調用后的結果,如果沒有就調用方法並緩存結果后返回給用戶。下次調用直接從緩存中獲取。
使用Spring緩存抽象時我們需要關注以下兩點;
1、確定方法需要被緩存以及他們的緩存策略
2、從緩存中讀取之前緩存存儲的數據

 2.代碼結構及pom文件

 

<?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>com.zy</groupId>
    <artifactId>spring-boot-cache</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-cache</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.14.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <lombok.version>1.16.10</lombok.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- 引入redis的starter,這里面有jedis客戶端 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <!--<scope>test</scope>-->
        </dependency>

        <!-- 引入lombok的依賴 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

        <!-- 引入caffeine緩存Jar包 -->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.6.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

 3.啟動類

package com.zy;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/**
 * 一、搭建基本環境
 * 1、導入數據庫文件 創建出department和employee表
 * 2、創建javaBean封裝數據
 * 3、整合MyBatis操作數據庫
 *         1.配置數據源信息
 *         2.使用注解版的MyBatis;
 *             1)、@MapperScan指定需要掃描的mapper接口所在的包
 * 二、快速體驗緩存
 *         步驟:
 *             1、開啟基於注解的緩存 @EnableCaching
 *             2、標注緩存注解即可
 *                 @Cacheable
 *                 @CacheEvict
 *                 @CachePut
 * 默認使用的是ConcurrentMapCacheManager==ConcurrentMapCache;將數據保存在    ConcurrentMap<Object, Object>中
 * 開發中使用緩存中間件;redis、memcached、ehcache;
 * 三、整合redis作為緩存
 * Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。
 *     1、安裝redis:使用docker;
 *     2、引入redis的starter
 *     3、配置redis
 *     4、測試緩存
 *         原理:CacheManager===Cache 緩存組件來實際給緩存中存取數據
 *        1)、引入redis的starter,容器中保存的是 RedisCacheManager;
 *        2)、RedisCacheManager 幫我們創建 RedisCache 來作為緩存組件;RedisCache通過操作redis緩存數據的
 *        3)、默認保存數據 k-v 都是Object;利用序列化保存;如何保存為json
 *               1、引入了redis的starter,cacheManager變為 RedisCacheManager;
 *               2、默認創建的 RedisCacheManager 操作redis的時候使用的是 RedisTemplate<Object, Object>
 *               3、RedisTemplate<Object, Object> 是 默認使用jdk的序列化機制
 *      4)、自定義CacheManager;
 *
 */
@SpringBootApplication
// 掃描mapper,支持mybatis
@MapperScan("com.zy.mapper")
// 開啟緩存注解,此外,還要在service層加上緩存注解@Cacheable才能生效
@EnableCaching
public class SpringBootCacheApplication {

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

4.model層對象

package com.zy.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class Employee implements Serializable {

    private Integer id;

    private String lastName;

    private String email;

    //1 male, 0 female
    private Integer gender;

    private Integer dId;


}


package com.zy.model;
/**
 *
 * 部門的實體類
 */

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class Department implements Serializable {

    private Integer id;

    private String departmentName;

}

5.mapper層

package com.zy.mapper;

import com.zy.model.Employee;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
 *
 * employee是xml配置文件版的mapper
 */
// 此處@Mapper也可以不寫,但是要在springboot啟動類出加上注解@MapperScan
// @Mapper
public interface EmployeeMapper {

    @Select("SELECT * FROM employee WHERE id = #{id}")
    public Employee getEmpById(Integer id);

    @Update("UPDATE employee SET lastName=#{lastName},email=#{email},gender=#{gender},dId=#{dId} WHERE id=#{id}")
    public void updateEmp(Employee employee);

    @Delete("DELETE FROM employee WHERE id=#{id}")
    public void deleteEmpById(Integer id);

    @Insert("INSERT INTO employee(lastName,email,gender,dId) VALUES(#{lastName},#{email},#{gender},#{dId})")
    public void insertEmployee(Employee employee);

    @Select("SELECT * FROM employee WHERE lastName = #{lastName}")
    Employee getEmpByLastName(String lastName);

}





package com.zy.mapper;
/**
 *
 * department是注解版的mybatis
 */

import com.zy.model.Department;
import org.apache.ibatis.annotations.*;

// 此處@Mapper也可以不寫,但是要在springboot啟動類出加上注解@MapperScan
// @Mapper
public interface DepartmentMapper {

    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("insert into department(departmentName) values(#{departmentName})")
    public int addDept(Department department);

    @Delete("delete from department where id=#{id}")
    public void deleteDeptById(Integer id);

    @Update("update department set departmentName=#{departmentName} where id=#{id}")
    public void updateDeptById(Integer id);

    @Select("select * from department where id=#{id}")
    public Department getDeptById(Integer id);
}

6.service層實現類

package com.zy.service;

import com.zy.mapper.EmployeeMapper;
import com.zy.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

// 抽取公共配置-->到類上
@CacheConfig(cacheNames="emp")
@Service("employeeService")
public class EmployeeServiceImpl {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 將方法的運行結果進行緩存;以后再要相同的數據,直接從緩存中獲取,不用調用方法;
     * CacheManager管理多個Cache組件的,對緩存的真正CRUD操作在Cache組件中,每一個緩存組件有自己唯一一個名字;
     *

     *
     * 原理:
     *   1、自動配置類;CacheAutoConfiguration
     *   2、緩存的配置類
     *   org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
     *   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默認】
     *   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
     *   3、哪個配置類默認生效:SimpleCacheConfiguration;
     *
     *   4、給容器中注冊了一個CacheManager:ConcurrentMapCacheManager
     *   5、可以獲取和創建ConcurrentMapCache類型的緩存組件;他的作用將數據保存在ConcurrentMap中;
     *
     *   運行流程:
     *   @Cacheable:
     *   1、方法運行之前,先去查詢Cache(緩存組件),按照cacheNames指定的名字獲取;
     *      (CacheManager先獲取相應的緩存),第一次獲取緩存如果沒有Cache組件會自動創建。
     *   2、去Cache中查找緩存的內容,使用一個key,默認就是方法的參數;
     *      key是按照某種策略生成的;默認是使用keyGenerator生成的,默認使用SimpleKeyGenerator生成key;
     *          SimpleKeyGenerator生成key的默認策略;
     *                  如果沒有參數;key=new SimpleKey();
     *                  如果有一個參數:key=參數的值
     *                  如果有多個參數:key=new SimpleKey(params);
     *   3、沒有查到緩存就調用目標方法;
     *   4、將目標方法返回的結果,放進緩存中
     *
     *   @Cacheable標注的方法執行之前先來檢查緩存中有沒有這個數據,默認按照參數的值作為key去查詢緩存,
     *   如果沒有就運行方法並將結果放入緩存;以后再來調用就可以直接使用緩存中的數據;
     *
     *   核心:
     *      1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】組件
     *      2)、key使用keyGenerator生成的,默認是SimpleKeyGenerator
     *
     *
     *   幾個屬性:
     *      cacheNames或者value:指定緩存組件的名字;將方法的返回結果放在哪個緩存中,是數組的方式,可以指定多個緩存;
     *
     *      key:緩存數據使用的key;可以用它來指定。默認是使用方法參數的值  1-方法的返回值
     *              編寫SpEL; #id;參數id的值   #a0  #p0  #root.args[0]
     *              getEmp[2]
     *
     *      keyGenerator:key的生成器;可以自己指定key的生成器的組件id
     *              key和keyGenerator:二選一使用;
     *
     *
     *      cacheManager:指定緩存管理器;或者cacheResolver指定獲取解析器;二選一使用;
     *
     *      condition:指定符合條件的情況下才緩存;
     *              ,condition = "#id>0"
     *          condition = "#a0>1":第一個參數的值》1的時候才進行緩存
     *
     *      unless:否定緩存;當unless指定的條件為true,方法的返回值就不會被緩存;可以獲取到結果進行判斷
     *              unless = "#result == null"
     *              unless = "#a0==2":如果第一個參數的值是2,結果不緩存;
     *      sync:是否使用異步模式
     * @param id
     * @return
     *
     */
    // 此處與啟動類的@EnableCaching注解連用才能生效
    @Cacheable(value = "{emp}")
    public Employee getEmpById(Integer id){
        Employee employee = employeeMapper.getEmpById(id);
        return employee;
    }



    /**
     * @CachePut:既調用方法,又更新緩存數據;同步更新緩存
     * 修改了數據庫的某個數據,同時更新緩存;
     * 運行時機:
     *  1、先調用目標方法
     *  2、將目標方法的結果緩存起來
     *
     * 測試步驟:
     *  1、查詢1號員工;查到的結果會放在緩存中;
     *          key:1  value:lastName:張三
     *  2、以后查詢還是之前的結果
     *  3、更新1號員工;【lastName:zhangsan;gender:0】
     *          將方法的返回值也放進緩存了;
     *          key:傳入的employee對象  值:返回的employee對象;
     *  4、查詢1號員工?
     *      應該是更新后的員工;
     *          key = "#employee.id":使用傳入的參數的員工id;
     *          key = "#result.id":使用返回后的id
     *             @Cacheable的key是不能用#result
     *      為什么是沒更新前的?【1號員工沒有在緩存中更新】
     *
     */
    @CachePut(/*value = "emp",*/key = "#result.id")
    public void updateEmp(Employee employee){
        employeeMapper.updateEmp(employee);
    }


    /**
     * @CacheEvict:緩存清除
     *  key:指定要清除的數據
     *  allEntries = true:指定清除這個緩存中所有的數據
     *  beforeInvocation = false:緩存的清除是否在方法之前執行
     *      默認代表緩存清除操作是在方法執行之后執行;如果出現異常緩存就不會清除
     *
     *  beforeInvocation = true:
     *      代表清除緩存操作是在方法運行之前執行,無論方法是否出現異常,緩存都清除
     */
    @CacheEvict
    public void deleteEmp(Integer id){
        employeeMapper.deleteEmpById(id);
    }

    // @Caching 定義復雜的緩存規則
    @Caching(
            cacheable = {
                    @Cacheable(/*value="emp",*/key = "#lastName")
            },
            put = {
                    @CachePut(/*value="emp",*/key = "#result.id"),
                    @CachePut(/*value="emp",*/key = "#result.email")
            }
    )
    public Employee getEmpByLastName(String lastName){
        return employeeMapper.getEmpByLastName(lastName);
    }
}

7.controller層

package com.zy.controller;

import com.zy.model.Employee;
import com.zy.service.EmployeeServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/emps")
public class EmployeeController {

    @Autowired
    private EmployeeServiceImpl employeeService;

    @GetMapping("/getEmpById/{id}")
    public Employee getEmpById(@PathVariable("id") Integer id){
        Employee employee = employeeService.getEmpById(id);
        return employee;
    }

    @GetMapping("/updateEmp")
    public void updateEmp(Employee employee){
        employeeService.updateEmp(employee);
    }

    @GetMapping("/delemp")
    public String deleteEmp(Integer id){
        employeeService.deleteEmp(id);
        return "success";
    }

    @GetMapping("/emp/lastname/{lastName}")
    public Employee getEmpByLastName(@PathVariable("lastName") String lastName){
        return employeeService.getEmpByLastName(lastName);
    }


}

8.application.yml文件

spring:
#  這里指定數據源即配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/spring_boot
    username: root
    password: 123456
#    這里指定cache的類型即配置
  cache:
    type: caffeine
    caffeine:
      spec: initialCapacity=100,maximumSize=500,expireAfterWrite=30s
#      Caffeine配置說明:
#      initialCapacity=[integer]: 初始的緩存空間大小
#      maximumSize=[long]: 緩存的最大條數
#      maximumWeight=[long]: 緩存的最大權重
#      expireAfterAccess=[duration]: 最后一次寫入或訪問后經過固定時間過期
#      expireAfterWrite=[duration]: 最后一次寫入后經過固定時間過期
#      refreshAfterWrite=[duration]: 創建緩存或者最近一次更新緩存后經過固定的時間間隔,刷新緩存
#      weakKeys: 打開key的弱引用
#      weakValues:打開value的弱引用
#      softValues:打開value的軟引用
#      recordStats:開發統計功能

#      連接redis緩存主機:這里是redis的配置
#  redis:
#    host: 192.168.0.100
logging:
  level:
    com.zy.mapper: debug
#    打印所有詳情
debug: true

9.當使用redis進行緩存時,若需要更改默認的序列化規則,則可以添加:

# docker中國鏡像加速http://www.docker-cn.com/registry-mirror
# docker安裝redis

docker pull registry.docker-cn.com/library/redis

# docker 運行redis

docker run --name redis01 -p 6379:6379 -d --rm registry.docker-cn.com/library/redis

 

報錯解決:

報錯1:  WARNING: IPv4 forwarding is disabled. Networking will not work.

解決辦法:

# vi /etc/sysctl.conf


或者

# vi /usr/lib/sysctl.d/00-system.conf


添加如下代碼:

    net.ipv4.ip_forward=1

重啟network服務

# systemctl restart network

查看是否修改成功

# sysctl net.ipv4.ip_forward


如果返回為“net.ipv4.ip_forward = 1”則表示成功了


報錯2:  /usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint redis01 (19c4784b08511fa716aea4d0eb3da402e648f409afa3e532b178ff3c2d95a92d): exec: "docker-proxy": executable file not found in $PATH.

ln -s /usr/libexec/docker/docker-proxy-current /usr/bin/docker-proxy

報錯3:  /usr/bin/docker-current: Error response from daemon: shim error: docker-runc not installed on system.

ln -s /usr/libexec/docker/docker-runc-current /usr/libexec/docker/docker-runc

 

9.1MyRedisConfig

package com.zy.config;


import com.zy.model.Department;
import com.zy.model.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.net.UnknownHostException;
@Configuration
public class MyRedisConfig {

    @Bean
    public RedisTemplate<Object, Employee> empRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
        template.setDefaultSerializer(ser);
        return template;
    }
    @Bean
    public RedisTemplate<Object, Department> deptRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
        template.setDefaultSerializer(ser);
        return template;
    }



    //CacheManagerCustomizers可以來定制緩存的一些規則
    @Primary  //將某個緩存管理器作為默認的
    @Bean
    public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
        RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
        //key多了一個前綴

        //使用前綴,默認會將CacheName作為key的前綴
        cacheManager.setUsePrefix(true);

        return cacheManager;
    }

    @Bean
    public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate){
        RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
        //key多了一個前綴

        //使用前綴,默認會將CacheName作為key的前綴
        cacheManager.setUsePrefix(true);

        return cacheManager;
    }
}

9.2RedisDemo

 
         
package com.zy;

import com.zy.mapper.EmployeeMapper;
import com.zy.model.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Set;

/**
* Redis常見的五大數據類型
* String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
* stringRedisTemplate.opsForValue()[String(字符串)]
* stringRedisTemplate.opsForList()[List(列表)]
* stringRedisTemplate.opsForSet()[Set(集合)]
* stringRedisTemplate.opsForHash()[Hash(散列)]
* stringRedisTemplate.opsForZSet()[ZSet(有序集合)]
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootCacheApplicationTests {

@Autowired
private EmployeeMapper employeeMapper;

@Autowired
private RedisTemplate redisTemplate;

@Autowired
private StringRedisTemplate stringRedisTemplate;

// 自定義的redisTemplate;
@Autowired
private RedisTemplate<Object, Employee> empRedisTemplate;

@Test
public void contextLoads() {
/*employeeMapper*/
System.out.println(employeeMapper.getEmpById(2));
}

@Test
public void fn01(){
// 1.向redis中放置數據,並取出
stringRedisTemplate.opsForValue().append("good", "morning");
String good = stringRedisTemplate.opsForValue().get("good");
System.out.println(good);
// 2.放置其他類型的數據
stringRedisTemplate.opsForList().leftPush("mylist", "zx");
RedisOperations<String, String> operations = stringRedisTemplate.opsForList().getOperations();
Set<String> mylist = operations.keys("mylist");
}

@Test
// 測試保存對象
public void fn02(){
Employee employee = employeeMapper.getEmpById(1);
/*
官方自帶的方式
redisTemplate.opsForValue().set("emp01", employee);
*/
//1、將數據以json的方式保存
//(1)自己將對象轉為json
//(2)redisTemplate默認的序列化規則;改變默認的序列化規則;
empRedisTemplate.opsForValue().set("emp01", employee);
}

}
 

9.3分別在對應的service實現類上加上對應的cacheManager

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM