• springBoot cache操作2


    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxd1435513775/article/details/85091793
    一、基本项目搭建
    测试项目是基于SpringBoot+Mybatis+Maven;

    1、搭建基本环境,具体步骤如下:
    (1)、新建数据库,导入数据库文件,创建出department和employee表;

    (2)、创建SpringBoot-cache工程,选择具体模块,如下图;


    (3)、在pom.xml文件中,加入cache依赖

    <!-- https://mvnrepository.com/artifact/javax.cache/cache-api -->
    <dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.0.0</version>
    </dependency>
    1
    2
    3
    4
    5
    6
    (4)、创建JavaBean封装数据,以Employee表为例;

    public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender; //性别 1男 0女
    private Integer dId;

    //setter、getter方法略
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (5)、在配置文件中,配置数据库;

    //配置项目对外访问路径
    server.servlet.context-path=/cache

    //配置数据源
    spring.datasource.url=jdbc:mysql://192.168.1.106:3307/mybatis
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver

    //开启驼峰命名
    mybatis.configuration.map-underscore-to-camel-case=true

    //打开操作数据库的日志
    logging.level.com.scorpios.cache.mapper=debug
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (6)、整合Mybatis操作数据;

    @Mapper
    public interface EmployeeMapper {

    //查
    @Select("select * from employee where id = #{id}")
    public Employee getEmpById(Integer id);

    //增
    @Insert("insert into employee (lastName,email,gender,did) values ( #{lastName},#{email},#{gender},#{dId})")
    public void addEmp(Employee emp);

    //删
    @Delete("delete from employee where id = #{id}")
    public void delEmpById(Integer id);

    //改
    @Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},did=#{dId} where id=#{id}")
    public void updateEmp(Employee emp);
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    (7)、配置扫描Mapper包;

    @MapperScan("com.scorpios.cache.mapper") //配置扫描mapper包
    @SpringBootApplication
    public class SpringbootCacheApplication {

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

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    (8)、测试访问:http://localhost:8080/cache/emp/1


    多次访问,控制台输出:


    二、快速体验Cache使用
    1、想要使用Cache缓存,首先了解关于Cache的注解,并需要开启缓存注解:@EnableCaching

    开启缓存功能的注解

    @EnableCaching //开启缓存注解
    @MapperScan("com.scorpios.cache.mapper")
    @SpringBootApplication
    public class SpringbootCacheApplication {

    public static void main(String[] args) {
    SpringApplication.run(SpringbootCacheApplication.class, args);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    2、@Cacheable注解使用和说明
    编写Service层,调用Dao层,并在Service层,对操作Dao层的数据进行缓存

    @Service
    public class EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;

    @Cacheable(cacheNames = "emp",key = "#root.args[0]")
    public Employee getEmpById(Integer id){
    System.out.println("查询"+id+"号员工");
    Employee emp = employeeMapper.getEmpById(id);
    System.out.println(emp);
    return emp;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (1)、测试结果
    多次发送请求,控制台只显示查询了一次数据库操作,缓存成功。


    (2)、@Cacheable参数具体说明
    @Cacheable:将方法的运行结果缓存,以后再要相同的数据,直接从缓存中获取,不用调用方法;

    cacheNames/value:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
    例如:@Cacheable(cacheNames = {}"emp","dept"},key = "#root.args[0]")

    key:可以用它来指定缓存数据使用的key,默认是使用方法参数的值;(也可以指定自己的生成策略)

    keyGenerator:key的生成器;可以自己指定key的生成器的组件id;key/keyGenerator:二选一使用;

    cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器;

    condition:指定符合条件的情况下才缓存;
    例如:@Cacheable(cacheNames = {}"emp","dept"},key = "#root.args[0]",condition="#root.args[0]>0")

    unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断;

    sync:是否使用异步模式;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    (3)、指定自己的key生成策略和key的SPEL表达式的说明:


    @Cacheable(cacheNames = "emp",keyGenerator = "myKeyGenerator")
    public Employee getEmpById(Integer id){
    System.out.println("查询"+id+"号员工");
    Employee emp = employeeMapper.getEmpById(id);
    System.out.println(emp);
    return emp;
    }
    1
    2
    3
    4
    5
    6
    7
    自定义自己的key生成策略

    @Configuration
    public class MyCacheConfig {

    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(){

    return new KeyGenerator() {
    @Override
    public Object generate(Object target, Method method, Object... params) {

    return method.getName()+Arrays.asList(params).toString();
    }
    };

    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    (4)、@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、将目标方法返回的结果,放进缓存中;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    3、@CachePut注解使用和说明
    作用:在目标方法调用之后,将目标方法的执行结果放入缓存,既调用方法,又更新缓存数据;

    (1)、测试代码:


    @CachePut(cacheNames = "emp",key = "#result.id")//key需要注意
    public Employee updateEmp(Employee employee){
    System.out.println("更新的员工信息:"+employee);
    employeeMapper.updateEmp(employee);
    return employee;
    }
    1
    2
    3
    4
    5
    6
    7
    (2)、测试结果:
    发送更新用户信息请求:


    控制台输出:


    发送查询请求后,控制台并没有任何输出,说明是从缓存中拿的数据:


    (3)、重要说明:

    @CachePut(cacheNames = "emp",key = "#result.id")//key需要注意
    1
    如果我们在使用@CachePut注解时,不指定key,这会使用方法的默认参数,这样的话,与@Cacheable注解的key不一致,导致,我们更新过后,再次查询信息时,并不会得到缓存信息。这主要是以为key不一致导致的,需要注意。

    4、@CacheEvit注解使用和说明
    作用:缓存清除
    (1)、测试代码:

    @CacheEvict(cacheNames = "emp",key ="#root.args[0]")
    public void deleteEmp(Integer id){

    //模拟删除
    System.out.println("删除数据,员工id为:" +id );

    }
    1
    2
    3
    4
    5
    6
    7
    (2)、测试结果:
    第一次查询id为1的员工,控制台打印查询数据库请求,第二次查询则不会去查询数据库;
    然后发送删除id为1的员工请求,控制台打印,删除信息;
    最后再次发送查询id为1的员工,控制台再次打印查询数据库的SQL。
    表明之前的缓存已清除


    (3)、@CachePut参数说明:

    key:指定要清除的数据;

    allEntries=true;指定清除这个缓存中所有的数据;

    beforeInvocation=false;缓存的清除是否在方法之前执行
    默认代表缓存清除操作是在方法之后执行;如果出现异常缓存就不会清除

    beforeInvocation=true:
    代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
    1
    2
    3
    4
    5
    6
    7
    8
    9
    4、@Caching注解使用和说明
    可以指定多个缓存规则,下面是@Caching的源码

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Caching {

    Cacheable[] cacheable() default {};

    CachePut[] put() default {};

    CacheEvict[] evict() default {};

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    示例代码:

    @Caching(
    cacheable = {
    @Cacheable(cacheNames = "emp",key = "#lastName")
    },

    put = {
    @CachePut(cacheNames = "emp",key="#result.id"),
    @CachePut(cacheNames = "emp",key="#result.email")
    }
    )
    public Employee getEmpByNames(String lastName){

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    4、@CacheConfig注解使用和说明
    可以在类上加上次注解,用于指定类级别的公共缓存属性,例如使用公共缓存名字和id的生成策略

    @CacheConfig(cacheNames = "emp")
    @Service
    public class EmployeeService {

    }

    1
    2
    3
    4
    5
    6
    7
    三、SpringBoot整合Redis作为缓存
    在我们没有配置使用其他缓存中间件时,SpringBoot默认使用的是ConcurrentMapCacheManager,然后用这个Manager来创建ConcurrentMapCache,并将数据保存在ConcurrentMap<Object,Object>中;下图是SpringBoot支持的缓存配置。


    但在实际的开发中,我们经常会使用一些缓存中间件,如:Redis、MemCached、eheache等;

    1、安装Redis:安装Redis可以参考前面文章的RabbitMQ和ElasticSearch,用Docker安装比较方便,启动起来后,用客户端连接上Redis,如下图:


    2、Redis整合步骤:
    (1)、引入Redis的starter

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    1
    2
    3
    4
    (2)、在application.properties文件中配置Redis

    spring.redis.host=192.168.1.106
    1
    (3)、启动Redis,并用客户端连接:


    3、测试普通字符串代码:

    RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringbootCacheApplicationTests {

    @Autowired
    RedisTemplate redisTemplate; //k-v都是对象

    @Autowired
    StringRedisTemplate stringRedisTemplate; //操作k-v都是字符串

    @Test
    public void testRedis(){
    //给Redis中保存数据
    stringRedisTemplate.opsForValue().append("msg","helloworld");

    //从Redis中取数据
    String msg = stringRedisTemplate.opsForValue().get("msg");
    System.out.println("msg from redis:"+msg);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    (1)、测试结果:
    往Redis中写数据


    从Redis中读数据:


    (2)、说明:
    Redis常见的五大数据类型:String(字符串)、list(列表)、set(集合)、hash(散列)、ZSet(有序集合)

    stringRedisTemplate.opsForValue() 操作String字符串
    stringRedisTemplate.opsForList() 操作list列表
    stringRedisTemplate.opsForSet() 操作Set集合
    stringRedisTemplate.opsForHash() 操作Hash散列
    stringRedisTemplate.opsForZSet 操作Zset有序集合
    1
    2
    3
    4
    5
    4、测试存储对象:

    @Test
    public void testRedis(){
    //给Redis中保存数据
    redisTemplate.opsForValue().set("emp",employeeMapper.getEmpById(1));
    }
    1
    2
    3
    4
    5
    (1)、测试结果:
    往Redis中写数据,会发现是一堆字节码


    (2)、自定义序列化器

    @Configuration
    public class MyRedisConfig {

    @Bean
    public RedisTemplate<Object, Employee> myRedisTemplate(
    RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    RedisTemplate<Object, Employee> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    //设置自定义序列化器
    Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);

    template.setDefaultSerializer(serializer);
    return template;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    (3)、测试代码,需要自动注入自己的序列化器:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringbootCacheApplicationTests {

    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    RedisTemplate myRedisTemplate; //自定义的序列化器

    @Test
    public void testRedis(){
    //给Redis中保存数据
    myRedisTemplate.opsForValue().set("emp",employeeMapper.getEmpById(1));
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    (4)、测试结果:


    四、小结
    1、想要使用缓存,需要先开启缓存注解@EnableCaching;

    2、熟练对@Cacheable、@CachePut、@CacheEvict、@Caching注解的使用,特别是属性的使用;
    3、SpringBoot整合Redis作为缓存;
    ---------------------
    作者:止步前行
    来源:CSDN
    原文:https://blog.csdn.net/zxd1435513775/article/details/85091793
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    5.3 java虚拟机的体系结构
    5.2 java虚拟机的生命周期
    3.11.5 doPrivileged()方法
    3.11.1 implies方法
    MT【178】平移不变性
    MT【177】三个乘积和
    MT【176】两两乘积
    MT【175】刚刚凑巧
    MT【174】凹凸无妨
    MT【173】齐次消元单变量
  • 原文地址:https://www.cnblogs.com/leigepython/p/10495260.html
Copyright © 2020-2023  润新知