三、springboot-redis缓存使用

版权声明:转发请注明,谢谢配合 https://blog.csdn.net/qq_31289187/article/details/82971918

一、创建springboot项目

二、pom.xml添加以下依赖

            <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>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.46</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.9</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.22</version>
		</dependency>

三、使用

1、启动类添加注解@EnableCaching

2、application.properties配置redis的host、post、password

#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=tiger

3、application.properties配置mysql

#datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tiger?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&generateSimpleParameterMetadata=true
spring.datasource.username=tiger
spring.datasource.password=tiger
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.max-idle=10
spring.datasource.max-wait=60000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validationQuery=select 'x'

4、创建学生信息表

CREATE TABLE student_info (
  id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增',
  student_id bigint(20) NOT NULL COMMENT '学号',
  name varchar(64) NOT NULL COMMENT '姓名',
  age int(2) NOT NULL COMMENT '年龄',
  familly_address varchar(256) NOT NULL COMMENT '家庭地址',
  created_date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  updated_date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (student_id),
  KEY id (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4

5、创建实体类:StudentInfo

package com.dl.cn.message.bean;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

/**
 * Created by Tiger on 2018/10/8.
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentInfo implements Serializable{

    private static final long serialVersionUID = 2597547944454691103L;

    private Long id;
    private Long studentId;
    private String name;
    private Integer age;
    private String famillyAddress;
    private Date createdDate;
    private Date updatedDate;
}

6、mapper类:StudentInfoMapper

package com.dl.cn.message.mapper;

import com.dl.cn.message.bean.StudentInfo;
import org.apache.ibatis.annotations.*;

/**
 * Created by Tiger on 2018/10/8.
 */
@Mapper
public interface StudentInfoMapper {
    @Insert("insert into student_info(student_id,name,age,familly_address)" +
            " values(#{studentId},#{name},#{age},#{famillyAddress})")
    /**
     * 通过bean保存实体类是,建议不要通过@Param注解,负责实体类的属性都在@Param中找
     * */
    void saveStudentInfo(StudentInfo studentInfo);


    @Select("select * from student_info where student_id = #{studentId}")
    StudentInfo findByStudentId(@Param("studentId") Long studentId);


    @Update("update student_info set familly_address = #{famillyAddress},updated_date = now() ")
    void updateFamillyAddress(@Param("studentId") Long studentId,@Param("famillyAddress") String famillyAddress);
}

7、service类:StudentInfoService

package com.dl.cn.message.service;

import com.dl.cn.message.bean.StudentInfo;
import com.dl.cn.message.mapper.StudentInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created by Tiger on 2018/10/8.
 */
@Service
public class StudentInfoService {

    @Autowired
    StudentInfoMapper studentInfoMapper;

    /**
     * 保存学生信息
     * @param studentInfo
     * */
    public void saveStudentInfo(StudentInfo studentInfo){
        studentInfoMapper.saveStudentInfo(studentInfo);
    }

    /**
     * 根据学号查学生信息
     * @param studentId
     * @return
     * */
    public StudentInfo findByStudentId(Long studentId){
        return studentInfoMapper.findByStudentId(studentId);
    }

    /**
     * 根据学号更新家庭地址
     * @param studentId
     * @param famillyAddress
     * */
    public void updateFamillyAddress(Long studentId,String famillyAddress){
        studentInfoMapper.updateFamillyAddress(studentId,famillyAddress);
    }
}

8、controller类:StudentInofController

package com.dl.cn.message.controller;

import com.dl.cn.message.service.StudentInfoService;
import com.dl.cn.message.bean.StudentInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by Tiger on 2018/10/8.
 */
@RestController
@RequestMapping("/student")
@CacheConfig(cacheNames = "studentInfo")
@Slf4j
public class StudentInofController {
    @Autowired
    StudentInfoService studentInfoService;

    /**
     * 保存学生信息
     * @param studentId
     * @param name
     * @param age
     * @param famillyAddress
     * */
    @PostMapping("/save")
    public void saveStudentInfo(@RequestParam("student_id") Long studentId,
                                @RequestParam("name") String name,
                                @RequestParam("age") Integer age,
                                @RequestParam("familly_address") String famillyAddress){
        StudentInfo studentInfo = StudentInfo.builder()
                .studentId(studentId)
                .name(name)
                .age(age)
                .famillyAddress(famillyAddress)
                .build();
        studentInfoService.saveStudentInfo(studentInfo);
    }

    /**
     * 根据学号查学生信息
     * @param studentId
     * @return
     * */
    @PostMapping("/findByStudentId")
    @Cacheable(key = "#studentId")
    public StudentInfo findByStudentId(@RequestParam("student_id") Long studentId){
        log.info("Get student information based on student number:{}",studentId);
        System.out.println("查询信息>>>"+studentId);
        return studentInfoService.findByStudentId(studentId);
    }

    @PostMapping("/updateFamillyAddress")
    //删除对应key的缓存
    @CacheEvict(key = "#studentId")
    public void updateFamillyAddress(@RequestParam("student_id") Long studentId,
                                     @RequestParam("familly_address") String famillyAddress){
        studentInfoService.updateFamillyAddress(studentId,famillyAddress);
    }

}

四、说明

1、缓存的实体类必须序列号,IDEA可以安装serialVersionUID插件,然后自己定义快捷键

2、@Cacheable注解,缓存到redis

cacheNames:指定缓存的名称

key:定义组成的key值,如果不定义,则使用全部的参数计算一个key值。可以使用spring El表达式

condition:在执行方法之前条件判断,满足条件缓存,负责不缓存

unless:在执行方法之后条件判断,不满足条件返回true,满足条件返回false

key 的值可以指定没固定值,也可以取方法参数,例如:key = "#studentId"

sync:redis中有值时,多个线程可以同时访问,如果没有值,只允许一个线程查询

3、@CacheEvict注解,删除指定的key

cacheNames:指定缓存的名称

key:定义组成的key值,如果不定义,则使用全部的参数计算一个key值。可以使用spring El表达式

4、@cachePut注解,更新数据之后,更新redis对应key的值,和@Cacheable配套使用,但是添加这两个注解的方法,返回必须一样

5、@CacheConfig注解,作用域是当前类,这样不需要每个类设置cacheName的值

五、测试结果

1、在方法findByStudentId添加@Cacheable注解,预期结果是第一次查询从mysql获取信息,此后从redis获取信息

第一次进入了方法体:

第二次、第三次之后没有进入方法体,说明缓存成功了,查看redis,找到对应的key

2、在方法updateFamillyAddress上添加了注解@CacheEvict,预期结果是根据学号修改学生家庭住址,在redis删除对应key的值,然后重新从mysql获取信息

将13240115对应的学生家庭地址修改为北京,redis对应的key被删除

再次获取13240115学生的信息,从mysql获取信息

六、问题

1、从mysql查询的字段,student_id,created_date,update_date,familly_address值为null,因为在application.properties没有开启mybatis驼峰命名

#mybatis
#开启mybatis驼峰命名,这样可以将mysql中带有下划线的映射成驼峰命名的字段
mybatis.configuration.map-underscore-to-camel-case=true

2、redis缓存的key没有过期时间,如何给对应缓存设置过期时间

springboot2.0以后的配置方法

 @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        //生成一个默认配置,通过config对象即可对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 设置缓存的默认过期时间,也是使用Duration设置
        config = config.entryTtl(Duration.ofSeconds(60*2))
                .disableCachingNullValues();// 不缓存空值
        //设置一个初始化的缓存空间set集合
        Set<String> cacheNames =  new HashSet<>();
        cacheNames.add("studentInfo");

        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("studentInfo", config);

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)     // 使用自定义的缓存配置初始化一个cacheManager
                .initialCacheNames(cacheNames)  // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
                .withInitialCacheConfigurations(configMap)
                .build();
        return cacheManager;
    }
cacheNames中可以设置代码中多个缓存名,然后分别给设置过期时间,这里设置了2分钟!

猜你喜欢

转载自blog.csdn.net/qq_31289187/article/details/82971918