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就不會執行查詢,而是從快取中取數據。