SpringBoot第六天 Redis的集成及如何通过Redis实现Mybatis的二级缓存

xiaoxiao2025-07-19  9

本文默认Redis已经安装完成,并且可以使用。这里不做Redis的安装等说明

第一步,创建一个基本的SpringBoot应用。我们需要在pom.xml加入Redis的相关依赖。redis的依赖为spring-boot-starter-data-redis和spring-boot-starter-jetty。如下面代码所示:

<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.qlys</groupId> <artifactId>spring-learn</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.15.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> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- springboot 1.4之后开始支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies> </project>

我这里另外还使用Mybatis,Mysql,druid等依赖。因为我们下一步需要配置Mybatis的二级缓存。

下一步,修改appliation.yml文件,设置相关的参数。如:

server: port: 8888 logging: level: com.qlys.dao: debug spring: datasource: password: 123456 username: qlys url: jdbc:mysql://127.0.0.1:3306/bjx-test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: validation-query: select '*' initial-size: 1 max-active: 20 max-wait: 1000 filters: stat pool-prepared-statements: true mybatis: mapper-locations: classpath*:com/qlys/dao/xml/*.xml type-aliases-package: com.qlys.dao.mapper --- spring: redis: database: 9 host: 127.0.0.1 port: 6379 password: 123456 pool: max-idle: 20 max-active: 20 max-wait: -1 min-idle: 0 timeout: 1000

第三步 增加Redis的操作类,我把这个类建立的com.qlys.service包下面,代码如下:

package com.qlys.service; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; @Component public class RedisUtils { @Autowired private RedisTemplate<Object, Object> redis; /* * 读取 */ public Object read(final Object key) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); return ops.get(key); } /* * 写入 */ public boolean set(final Object key,Object val) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); return true; } /* * 设置过期时间 */ public boolean expire(final Object key,Object val,int expireTime) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); this.redis.expire(key, expireTime, TimeUnit.SECONDS); return true; } }

其中的RedisTemplate就是SpringBoot为我们封装好的操作Reids的工具类,我们常用的操作都是通过这个对象来完成的。在这个方法中,对于需要设置参数的存储时间是没有直接的方法的。因此我们需要先设置这个参数,然后设置这个参数的时间,即expire方法,先通过ops.set将数据写入redis,然后通过redis.expire方法设置过期时间。

第四步 然后我们就可以写一个代码来测试我们的Redis是否配置成功了,我建立了一个com.qlys.controller来编写界面的测试代码,代码如下:

package com.qlys.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.qlys.service.RedisUtils; @RestController public class TestController { @Autowired private RedisUtils redis; @RequestMapping("/save") public String writeRedis(String key) { redis.set("key", key); return "true"; } @RequestMapping("/read") public Object readRedis() { System.out.println(redis.read("key")); return redis.read("key"); } }

 其中save方法用于将我们传的参数存入redis中,而read方法用于将我们存的值取出来,显示于界面上。

最后修改启动类,来测试我们是否配置成功,代码如下:

import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan(basePackages="com.qlys") @MapperScan("com.qlys.dao.mapper") public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { logger.info("系统启动"); SpringApplication.run(Application.class, args); } }

访问我们save和read功能,查看是否成功。如果成功,我们这可以开始我们的redis同mybatis整合操作。

既然要访问数据库,我们当然要写编写数据库相关的代码,由于集成mybatis前面已经讲过,这里我不详细说明,只针对Cache来进行说明

首先建立一个类,实现Cache接口,如下面代码所示:

package com.qlys.bean; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private final ReadWriteLock lock = new ReentrantReadWriteLock(true); private static RedisTemplate<Object, Object> temp; public static void setRedisTemplate(RedisTemplate<Object, Object> temp) { RedisCache.temp = temp; logger.info("设置缓存对象--{}",temp); } private String id; @Override public String getId() { return id; } public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; } @Override public void putObject(final Object key,final Object value) { logger.info("写入缓存"); lock.writeLock().lock(); temp.opsForValue().set(key, value); lock.writeLock().unlock(); } @Override public Object getObject(final Object key) { logger.info("读取缓存"); return temp.opsForValue().get(key); } @Override public Object removeObject(final Object key) { logger.info("删除缓存"); Object val = temp.opsForValue().get(key); temp.delete(key); return val; } @Override public void clear() { logger.info("清除缓存"); temp.execute((RedisCallback<Boolean>)(conn)->{ conn.flushDb(); return true; }); } @Override public int getSize() { logger.info("redis大小"); return temp.execute((RedisCallback<Integer>)(conn)->{ return conn.dbSize().intValue(); }); } @Override public ReadWriteLock getReadWriteLock() { return lock; } }

修改上面的RedisUtils类,加入如下代码:

@Bean public RedisCache redisCache() { RedisCache.setRedisTemplate(redis); return null; }

这个代码是用于将Reids操作类存入到Cache操作类中,由于Cache是通过new创建的,无法通过注入完成。加入完成后,RedisUtils应该是这样的:

package com.qlys.service; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import com.qlys.bean.RedisCache; @Component public class RedisUtils { @Autowired private RedisTemplate<Object, Object> redis; @Bean public RedisCache redisCache() { RedisCache.setRedisTemplate(redis); return null; } /* * 读取 */ public Object read(final Object key) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); return ops.get(key); } /* * 写入 */ public boolean set(final Object key,Object val) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); return true; } /* * 设置过期时间 */ public boolean expire(final Object key,Object val,int expireTime) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); this.redis.expire(key, expireTime, TimeUnit.SECONDS); return true; } }

最后在我们配置Mybatis语句的mapper.xml文件中加入缓存配置就可以了,代码如下:

<cache eviction="FIFO" flushInterval="1" readOnly="false" type="com.qlys.bean.RedisCache

加入完成后,形成的代码如下:

<?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.qlys.dao.mapper.SystemMapper"> <cache eviction="FIFO" flushInterval="1" readOnly="false" type="com.qlys.bean.RedisCache"></cache> <select id="select" resultType="map"> SELECT * FROM a_table <where> <if test="id!=null"> and a_id=#{id} </if> </where> </select> <insert id="insert" parameterType="map"> INSERT INTO a_table(a_id,a_name,a_part) VALUES(#{id},#{name},#{part}) </insert> <delete id="delete" parameterType="map"> delete from a_table where a_id=#{id} </delete> </mapper>

至此一个简单的Redis同mybatis集合方案算是完成了。

附:

由于我们有可能会对SpringBoot提供的RedisTemplate的key解析方案做一些改造,这里贴上一个我写的一个序列化方案,方便知道以后怎么修改RedisTemplate这个对象的相关参数。仅供参考:

package com.qlys.bean; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; @Configuration @EnableCaching public class RedisCacheConfig { private static final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class); @Bean public CacheManager cacheManager(RedisTemplate<Object, Object> redis) { return new RedisCacheManager(redis); } @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object,Object>(); redisTemplate.setConnectionFactory(factory); RedisSerializer<Object> redisSerializer = new ByteRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); return redisTemplate; } private class ByteRedisSerializer implements RedisSerializer<Object>{ @Override public byte[] serialize(Object t) throws SerializationException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { // 序列化 oos.writeObject(t); return baos.toByteArray(); } catch (Exception e) { logger.error(e.getMessage(),e); } return null; } @Override public Object deserialize(byte[] bytes) throws SerializationException { if (bytes == null) { return null; } try (InputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais)) { // 反序列化 return ois.readObject(); } catch (Exception e) { logger.error(e.getMessage(),e); } return null; } } }

 

转载请注明原文地址: https://www.6miu.com/read-5033367.html

最新回复(0)