redis设置:
- 修改redis服务器的配置文件
vim /usr/local/redis/bin/redis.confbind 0.0.0.0 protected-mode no
- 重新启动redis
systemctl restart redis.service #重新启动服务
注意:服务器的话需要设置安全组开放端口
1.导入依赖
org.springframework.boot spring-boot-starter-data-redis
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: -1server: servlet: context-path: /redis01
通过以上配置后springboot就为我们提供了RedisTemplate和StringRedisTemplate(对key,value形式的都是string操作)
相关操作
StringRedisTemplate
对string类型的操作方式:
//操作stringstringRedisTemplate.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");//操作liststringRedisTemplate.opsForList().rightPushAll("list","l1","l2");//操作setstringRedisTemplate.opsForSet().add("set01", "daaa");//操作zsetstringRedisTemplate.opsForZSet().add("zset01", "zset", 1);
- 绑定一个键(k)进行操作:通常是对一个key进行多次的操作时使用。
//没有key就会添加keyBoundValueOperations 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文件中添加,二级缓存的作用范围是每个maper。
自定义redis缓存作为mybatis的缓存
- 导入依赖
org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-data-redis org.projectlombok lombok org.springframework.boot spring-boot-starter-test testjunit junit testcom.fasterxml.jackson.core jackson-databind org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.1com.alibaba druid 1.1.21mysql mysql-connector-java
注意: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 */@Componentpublic 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" ?> select id,username,password from user
- 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: /redis01mybatis: mapper-locations: classpath*:com/han/dao/*.xml type-aliases-package: com.han.pojologging: level: root: info com.han.dao: debug
注意启动文件上添加MapperScan注解扫描。
通过以上配置,只要redis缓存中有该数据,mybatis就不会执行查询,而是从缓存中取数据。
作者|MrHanhan|博客园