springboot集成redis
- 2020 年 12 月 15 日
- 筆記
- JAVA, mybatis, Redis, springboot, springboot集成系列
Springboot集成redis
redis设置:
- 修改redis服务器的配置文件
vim /usr/local/redis/bin/redis.conf
bind 0.0.0.0
protected-mode no
- 重新启动redis
systemctl restart redis.service #重新启动服务
注意:服务器的话需要设置安全组开放端口
1.导入依赖
<!-- springboot-redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.全局配置文件中配置redis信息
# 应用名称
spring:
application:
name: springboot-redis01
redis:
host: 47.93.190.68
port: 6379
database: 0
jedis:
#redis连接池信息
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
server:
servlet:
context-path: /redis01
通过以上配置后springboot就为我们提供了RedisTemplate和StringRedisTemplate(对key,value形式的都是string操作)
相关操作
StringRedisTemplate
对string类型的操作方式:
//操作string
stringRedisTemplate.opsForValue().set("string01","string");
System.out.println(stringRedisTemplate.opsForValue().get("string01"));
//操作hash类型
stringRedisTemplate.opsForHash().put("hash-user","username","name");
stringRedisTemplate.opsForHash().put("hash-user","userage","age");
//操作list
stringRedisTemplate.opsForList().rightPushAll("list","l1","l2");
//操作set
stringRedisTemplate.opsForSet().add("set01", "daaa");
//操作zset
stringRedisTemplate.opsForZSet().add("zset01", "zset", 1);
- 绑定一个键(k)进行操作:通常是对一个key进行多次的操作时使用。
//没有key就会添加key
BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps("name");
//追加的方式
boundValueOps.append("hahaha");
boundValueOps.append("hahaha");
System.out.println(boundValueOps.get());
//重新赋值
boundValueOps.set("hanwei hello");
System.out.println(boundValueOps.get());
注意: 一旦绑定key之后后续根据返回对象的操作都是基于这个key的操作
redisTemplate
- 一般操作是将对象存储在redis中。
@Test
public void testRedisTemplate(){
//通过这种方式是获取不到stringRedisTemplate方式设置的值的
System.out.println(redisTemplate.opsForValue().get("name"));//null
//设置key的序列化方式为string
redisTemplate.setKeySerializer(new StringRedisSerializer());
//以下是设置value的序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//jackson
ObjectMapper objectMapper = new ObjectMapper();
//转换json格式的时候将原始类型保留,这样在反序列化的时候就能知道对应的类型信息
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//修改存储在redis中的日期格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
User user = new User();
user.setId(22).setName("hanhan").setBir(new Date());
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user").toString());
//hash类型的是(key,(key,val)),所以需要单独设置序列化方式
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.opsForHash().put("user1","user",user);
System.out.println(redisTemplate.opsForHash().get("user1", "user"));
}
注意redistemplate默认使用的是jdk的序列化,存储到redis中会是下面的情况:,所以我们将key的序列化改为string类型的,将value改为json序列化。
mybatis中使用redis
mybatis自身缓存存在问题,本地缓存local cache
1.本地缓存存储在当前运行的jvm内存中,如果缓存数据过多会占用一定jvm内存,导致应用运行缓存。
2.不能在分布式系统中做到缓存共享。
重写mybatis cache 使用redis作分布式缓存
如果使用mybatis的二级缓存只需要在mapper文件中添加
自定义redis缓存作为mybatis的缓存
- 导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- springboot-redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
注意:mybatis的xml文件如果再java文件下的话,一定要加resources将xml发布
- 自定义RedisCache类
package com.han.cache;
import com.han.util.ApplicationContextUtils;
import org.apache.ibatis.cache.Cache;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author M.han
* @title: RedisCache
* @projectName springboot-redis
* @description: TODO
* @date 2020/12/1520:18
*/
public class RedisCache implements Cache {
private String id;
public RedisCache(String id) {
System.out.println("当前加入缓存的id==》" + id);
this.id = id;
}
@Override
public String getId() {
return id;
}
/***
* 放入缓存
* @param key
* @param val
*/
@Override
public void putObject(Object key, Object val) {
System.out.println("KEY:" + key);
System.out.println("val:" + val);
//获取对象
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
//存储在Redis中,注意上面对key使用了string序列化,所以传入的key是string类型的
redisTemplate.opsForValue().set(key.toString(), val);
}
/***
* 从缓存中获取
* @param key
* @return
*/
@Override
public Object getObject(Object key) {
System.out.println("从缓存中读取了=》" + key);
//获取对象
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate.opsForValue().get(key.toString());
}
/***
* 删除缓存中的数据
*/
@Override
public Object removeObject(Object o) {
return null;
}
/***
* 清空缓存
*/
@Override
public void clear() {
}
/***
* 缓存的命中概率
* @return
*/
@Override
public int getSize() {
return 0;
}
/***
* 读写锁,可以为空,写写互斥,读写互斥,读读共享
* @return
*/
@Override
public ReadWriteLock getReadWriteLock() {
return new ReentrantReadWriteLock();
}
}
- 因为缓存类是mybatis使用而没有交给spring容器托管(因为在mybatis执行这个的时候要传入id),但是在RedisCache类中需要注入RedisTemplate,所以自定义一个获取spring工厂中的bean的工具类。
package com.han.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author M.han
* @title: ApplicationUtils
* @projectName springboot-redis
* @description: 获取spring中的bean
* @date 2020/12/15 20:26
*/
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/***
*
* @param applicationContext 已经创建好的工厂对象
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtils.applicationContext = applicationContext;
}
//下面是自定义获取bean
/***
*根据id来获取bean
*/
public static Object getBean(String id){
return applicationContext.getBean(id);
}
/***
* 通过类型获取bean
* @param clazz
* @return
*/
public static Object getBean(Class clazz){
return applicationContext.getBean(clazz);
}
/***
* 根据id和类型同时获取bean
* @param id
* @param clazz
* @return
*/
public static Object getBean(String id,Class clazz){
return applicationContext.getBean(id,clazz);
}
}
- mapper.xml文件中指定redis缓存
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.han.dao.UserMapper">
<!--使用自定义的redis缓存实现-->
<cache type="com.han.cache.RedisCache"/>
<select id="findAll" resultType="com.han.pojo.User">
select id,username,password from user
</select>
</mapper>
- yaml文件配置信息
# 应用名称
spring:
application:
name: springboot-redis01
redis:
host:
port:
database: 0
jedis:
#redis连接池信息
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://--------/db?characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password:
server:
servlet:
context-path: /redis01
mybatis:
mapper-locations: classpath*:com/han/dao/*.xml
type-aliases-package: com.han.pojo
logging:
level:
root: info
com.han.dao: debug
注意启动文件上添加MapperScan注解扫描。
通过以上配置,只要redis缓存中有该数据,mybatis就不会执行查询,而是从缓存中取数据。