欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot 2.x redis缓存

程序员文章站 2022-05-01 15:53:13
...

1.pom文件导入依赖,本项目持久层使用mybatis,springboot 版本2.1.8

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.8.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>rediscache2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>rediscache2</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<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>2.1.1</version>
		</dependency>
		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!--spring2.0集成redis所需common-pool2-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.4.2</version>
        </dependency>
<!-- redis依赖,2.0以上使用这个依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
<!-- 缓存依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
	</dependencies>

2.application.yml配置文件

#Web服务
# address           :可指定在某个IP上启动服务。空表示在所有IP上启动
# context-path      :发布的路径
# session.timeout   :超时时间,单位:秒
server:
    address:
    port: 8080
    servlet:
        context-path: 
        session:
          timeout: 1800

spring:
  #MySQL数据库
  datasource:
    url: jdbc:mysql://192.168.2.101:3306/redisTest?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
#Mybatis配置
mybatis:
  mapper-locations: classpath*:com/example/demo/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.example.demo.dao: debug

spring.redis.database: 2 
spring.redis.host: localhost 
spring.redis.port: 6379
spring.redis.password: 

# springboot2.x以上如此配置,由于2.x的客户端是lettuce
# 单位要带上
spring.redis.lettuce.pool.max-active: 8
spring.redis.lettuce.pool.min-idle: 0
spring.redis.lettuce.pool.max-idle: 8
spring.redis.lettuce.pool.max-wait: 10000ms
spring.redis.lettuce.shutdown-timeout: 100ms

3.RedisCacheConfig缓存配置文件

import java.time.Duration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

    private static final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class);

    // 自定义key生成器
    @Bean
    public KeyGenerator keyGenerator(){
        return (o, method, params) ->{
            StringBuilder sb = new StringBuilder();
            sb.append(o.getClass().getName()); // 类目
            sb.append(method.getName()); // 方法名
            for(Object param: params){
                sb.append(param.toString()); // 参数名
            }
            return sb.toString();
        };
    }

    // 配置缓存管理器
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(300)) // 60s缓存失效
                // 设置key的序列化方式
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                // 设置value的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));
                // 不缓存null值
//                .disableCachingNullValues();

        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();

        logger.info("自定义RedisCacheManager加载完成");
        return redisCacheManager;
    }

    // key键序列化方式
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    // value值序列化方式
    private GenericJackson2JsonRedisSerializer valueSerializer(){
        return new GenericJackson2JsonRedisSerializer();
    }
}

4.测试service代码

package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.example.demo.dao.FilmBaseMapper;
@Service
public class TestService {
	@Autowired
	private FilmBaseMapper filmBaseMapper;
	//指定id作为redis的key,"film::9"为key
	@Cacheable(cacheNames="film",key="#id")
	public FilmBase getFilmById(int id) {
		FilmBase film = filmBaseMapper.selectByPrimaryKey(id);
		return film;
	}
	//方法全名为key,"films::com.example.demo.TestServicegetAll"为key
	@Cacheable(cacheNames="films")
	public List<FilmBase> getAll() {
		List<FilmBase> selectAll = filmBaseMapper.selectAll();
		return selectAll;
	}
	//方法必定执行一次,同时修改缓存 "film::9"为key
	@CachePut(cacheNames = "film", key = "#filmBase.id")
	public FilmBase updateFilm(FilmBase filmBase){
		Integer i;
		try {
			i = filmBaseMapper.updateByPrimaryKey(filmBase);
			return filmBase;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return filmBase;
	}
	//删除cacheNames 为film和films开头的缓存,allEntries =false只删除指定 "film::9"或"films::9"为key的缓存,allEntries =true删除两种cacheNames 缓存
	@CacheEvict(cacheNames = {"film","films"}, key ="#filmId",allEntries = false, beforeInvocation = true
		   )
    public Integer delFilm(Integer filmId) {
        return filmBaseMapper.deleteByPrimaryKey(filmId);
    }
}

5.测试FilmBaseMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.FilmBaseMapper">
	<resultMap id="BaseResultMap" type="com.example.demo.FilmBase">
		<id column="id" jdbcType="INTEGER" property="id" />
		<result column="film_name" jdbcType="VARCHAR" property="filmName" />
		<result column="user_id" jdbcType="INTEGER" property="userId" />
		<result column="year" jdbcType="INTEGER" property="year" />
		<result column="release_date" jdbcType="TIMESTAMP" property="releaseDate" />
		<result column="note" jdbcType="VARCHAR" property="note" />
		<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
	</resultMap>
	<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
		delete from film_base
		where id = #{id,jdbcType=INTEGER}
	</delete>
	<insert id="insert" parameterType="com.example.demo.FilmBase">
	 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
			SELECT LAST_INSERT_ID()
 	</selectKey>
		insert into film_base (id, film_name, user_id,
		year, release_date, note
		)
		values (#{id,jdbcType=INTEGER}, #{filmName,jdbcType=VARCHAR},
		#{userId,jdbcType=INTEGER},
		#{year,jdbcType=INTEGER}, #{releaseDate,jdbcType=TIMESTAMP}, #{note,jdbcType=VARCHAR}
		)
	</insert>
	<update id="updateByPrimaryKey" parameterType="com.example.demo.FilmBase">
		update film_base
		set film_name = #{filmName,jdbcType=VARCHAR},
		user_id = #{userId,jdbcType=INTEGER},
		year = #{year,jdbcType=INTEGER},
		release_date = #{releaseDate,jdbcType=TIMESTAMP},
		note = #{note,jdbcType=VARCHAR}
		where id = #{id,jdbcType=INTEGER}
	</update>
	<select id="selectByPrimaryKey" parameterType="java.lang.Integer"
		resultMap="BaseResultMap">
		select id, film_name, user_id, year, release_date, note
		from film_base
		where id = #{id,jdbcType=INTEGER}
	</select>
	<select id="selectByUserIdAndFilmName" resultMap="BaseResultMap">
		select id, film_name, user_id, year, release_date, note
		from film_base
		where user_id = #{userId,jdbcType=INTEGER} and film_name =
		#{filmName,jdbcType=VARCHAR}
	</select>
	<select id="selectByUserId" resultMap="BaseResultMap">
		select id, film_name, user_id, year, release_date, note,create_time
		from film_base
		where user_id = #{userId,jdbcType=INTEGER}
	</select>
	<select id="selectAll" resultMap="BaseResultMap">
		select id, film_name, user_id, year, release_date, note
		from film_base
	</select>
</mapper>

6.dao文件FilmBaseMapper

public interface FilmBaseMapper {
	int deleteByPrimaryKey(Integer id);

	int insert(FilmBase record);

	FilmBase selectByPrimaryKey(Integer id);

	List<FilmBase> selectAll();

	Integer updateFilm(FilmBase filmBase);

	Integer updateByPrimaryKey(FilmBase filmBase);
}

7.entity文件FilmBase

public class FilmBase implements Serializable {
    private Integer id;

    private String filmName;

    private Integer userId;

    private Integer year;

    private Date releaseDate;

    private String note;

    private Date createTime;
    private static final long serialVersionUID = 1L;
	//省略getset
}

8.测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
	@Autowired
	private TestService testService;
	@Test
	public void getAll() {
		List<FilmBase> all = testService.getAll();
		System.out.println(all.size());
		for (FilmBase filmBase : all) {
			System.out.println(filmBase.getFilmName());
		}
	}
	@Test
	public void getFilmById() {
		try {
			FilmBase all = testService.getFilmById(9);
			System.out.println(all.getFilmName());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void updateFilm() {
		FilmBase fb =new FilmBase();
		fb.setId(8);
		fb.setFilmName("中国记账");
		fb = testService.updateFilm(fb);
		System.out.println(fb.getFilmName());
	}
	@Test
	public void delFilm() {
		int i = testService.delFilm(14);
		System.out.println(i);
	}
}

9.sql文件



SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `film_base`
-- ----------------------------
DROP TABLE IF EXISTS `film_base`;
CREATE TABLE `film_base` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `film_name` varchar(255) DEFAULT NULL COMMENT '电影名称',
  `user_id` int(11) DEFAULT NULL COMMENT '用户id',
  `year` int(11) DEFAULT NULL COMMENT '年份',
  `release_date` datetime DEFAULT NULL COMMENT '发行日期',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `filmName_user_unique` (`film_name`,`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of film_base
-- ----------------------------
INSERT INTO `film_base` VALUES ('9', '建党伟业', '17', '2017', '2018-10-24 00:00:00', '2019-10-31 16:31:51', null);
INSERT INTO `film_base` VALUES ('20', '战狼', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 19:18:47', null);
INSERT INTO `film_base` VALUES ('21', '哪吒', '4', '2018', '2019-10-01 00:00:00', '2019-10-31 19:57:58', null);
INSERT INTO `film_base` VALUES ('22', '齐天大圣', '2', '2017', '2019-10-07 00:00:00', '2019-10-31 20:13:25', null);
INSERT INTO `film_base` VALUES ('23', '神龙教', '17', '2017', '2018-09-04 00:00:00', '2019-10-31 20:53:23', null);
INSERT INTO `film_base` VALUES ('24', '太极张三丰', '17', '2018', '2019-02-01 00:00:00', '2019-10-31 21:08:57', null);
INSERT INTO `film_base` VALUES ('25', '战狼2', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 21:11:33', null);
INSERT INTO `film_base` VALUES ('26', '战狼3', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 21:11:41', null);
INSERT INTO `film_base` VALUES ('27', '上甘岭', '1', '1955', '1955-10-12 00:00:00', '2019-10-31 21:20:18', null);
INSERT INTO `film_base` VALUES ('28', '上甘岭2', '1', '1956', '1957-05-12 00:00:00', '2019-10-31 21:31:43', null);
INSERT INTO `film_base` VALUES ('29', '上甘岭4', '1', '1960', '1960-08-18 00:00:00', '2019-10-31 21:39:17', null);
INSERT INTO `film_base` VALUES ('30', '飒飒飒飒多所', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:40:17', null);
INSERT INTO `film_base` VALUES ('31', '死亡骑士无', '1', '2018', '2018-10-31 00:00:00', '2019-10-31 21:41:45', null);
INSERT INTO `film_base` VALUES ('32', '读完读完群', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:42:37', null);
INSERT INTO `film_base` VALUES ('33', '大萨达', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:43:57', null);
INSERT INTO `film_base` VALUES ('34', '额滴神哒', '1', '2017', '2017-10-31 00:00:00', '2019-10-31 21:45:05', null);
INSERT INTO `film_base` VALUES ('35', '落花流水', '17', '2018', '2019-10-01 00:00:00', '2019-10-31 21:48:39', null);
INSERT INTO `film_base` VALUES ('36', '灵魂摆渡·黄泉', '4', null, null, '2019-11-01 09:30:29', null);
INSERT INTO `film_base` VALUES ('37', '死亡骑士', '1', '2016', '2016-11-15 00:00:00', '2019-11-01 10:12:34', null);
INSERT INTO `film_base` VALUES ('38', '死亡骑士1', '1', '2017', '2017-06-14 00:00:00', '2019-11-01 10:14:24', null);
INSERT INTO `film_base` VALUES ('39', 'test2', '2', '2019', '2019-11-19 00:00:00', '2019-11-01 10:31:16', null);
INSERT INTO `film_base` VALUES ('40', '九门提督', '4', '2019', '2019-11-13 00:00:00', '2019-11-01 10:33:34', null);
INSERT INTO `film_base` VALUES ('41', '唐山大地震', '17', '2017', '2017-07-03 00:00:00', '2019-11-01 10:44:59', null);
INSERT INTO `film_base` VALUES ('42', '超时空救援', '4', '2019', '2019-11-19 00:00:00', '2019-11-01 11:14:52', null);

10.测试方法,打印sql为走数据库,不打印为走缓存
a.执行getFilmById()方法,第一次走数据库
springboot 2.x redis缓存
b.再次执行getFilmById()方法,第二次走缓存
springboot 2.x redis缓存
c.执行getAll()方法,第一次走数据库
springboot 2.x redis缓存
d.再次执行getAll()方法,第二次走缓存
springboot 2.x redis缓存
e.redis数据库内容
springboot 2.x redis缓存
f.执行delFilm()方法allEntries = false,指定id我传的9,将id为9的数据删除
springboot 2.x redis缓存
g.执行delFilm()方法allEntries = true,指定id我传的20,将id为9的数据删除,同时删除film和films两个cacheNames缓存区域
springboot 2.x redis缓存
h.补充。执行 getFilmById方法后,再执行updateFilm()方法,可以修改缓存和数据库