cmd命令进入redis的根目录
选择redis根据那个配置文件启动,在其根目录中有两个配置文件,
一般选择redis.windows-service.conf
redis.windows.conf以非系统服务方式启动程序使用的配置文件
启动成功如图
1.pom文件添加依赖:
4.3.3.RELEASE
1.5.0.RELEASE
2.5.0
org.springframework.data
spring-data-redis
${spring.data.redis.version}
redis.clients
jedis
${redis.clients.version}
2.配置文件:
(1.)添加redis的配置信息文件redis.properties,根据项目中redis的实际情况进行配置
(2.)在applicationContext.xml配置redis
在此处需要注意的有几点:
1. property 用于加载类时,要用ref,不能用value,否则会报错
2. 静态方法和静态属性无法通过 @Autowired 注解注入,因为静态属性和静态方法是属于类的方法,而不是实体的方法,其在类加载的过程就会创建,而 @Autowired 是从 spring 容器中加载注入
3.@Autowired 注解在方法上,实际上和注解在属性上是同理的,注解在属性上是通过属性的setter方法注入,注解在方法中,方法名也必须是setter形式,只是方法里面我们可以做其他的操作
假如我们的 RedisUtil 中的方法是静态方法,那么在该类中RedisTemplate就为静态属性,不能通过@Autowired 来注入如下xml中配置的 redisTemplate 类,就需要我们配置一个辅助类,用于注入 redisTemplate, xml中如下配置RedisHelper类
java代码如下:
@Component
public class RedisHelper {
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate){
RedisUtil.setRedisTemplate(redisTemplate);
}
}
-------------------------------------------------------------------------------------
//只写了一个方法用于测试,可以根据自己的项目情况自行修改
//假如不用静态方法的话,直接在此类的属性 RedisTemplate 上添加 @Autowried 注解即可
//上面的辅助类可不要,同时xml中也不需要配置此类
public class RedisUtil {
private static RedisTemplate redisTemplate;
public static void setRedisTemplate(RedisTemplate redisTemplate){
RedisUtil.redisTemplate = redisTemplate;
}
public static String get(String key) throws Exception{
String value = null;
try{
value = (String) redisTemplate.opsForValue().get(key);
}catch (Exception e){
e.printStackTrace();
throw new BaseException("redis获取val错误");
}
return value;
}
}
测试:
这是普通的redis应用,下面我们来看如何用redis做mybatis的二级缓存
mybatis本身也有缓存
一级缓存是sqlSession(sql会话)级别的,使用SelSession第一次查询后,MyBatis会将其放在缓存中,再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库,一级缓存是默认开启的
二级缓存是application级别的,默认是不开启的,mybatis默认的二级缓存有一个缺点,它是保存在Mapper对象中的,在有一张A表,两个Mapper文件,AMapper.xml和BMapper.xml,B通过外键修改了A表中的内容,A是感知不到的,那么再从A里查询如果用到了缓存,就是旧的数据,因此在项目中一般用redis做mybatis的二级缓存
mybatis提供了一个接口 Cache ,我们只需要继承这个接口就可以对接redis的二级缓存
package org.apache.ibatis.cache;
import java.util.concurrent.locks.ReadWriteLock;
public interface Cache {
String getId();
void putObject(Object var1, Object var2);
Object getObject(Object var1);
Object removeObject(Object var1);
void clear();
int getSize();
default ReadWriteLock getReadWriteLock() {
return null;
}
}
那么我们创建一个类 RedisMybatisCache 继承 Cache
public class RedisMybatisCache implements Cache {
private final Logger logger = LoggerFactory.getLogger(RedisMybatisCache.class);
private String id;
private static RedisTemplate redisTemplate;
private final ReadWriteLock rwl = new ReentrantReadWriteLock();
/**
* 初始化 mybatis 二级缓存
* @param id
* @throws Exception
*/
public RedisMybatisCache(String id) throws Exception{
if(id == null){
throw new BaseException("mybatis缓存初始化需要一个id");
}
this.id = id;
}
public static void setRedisTemplate(RedisTemplate redisTemplate) {
RedisMybatisCache.redisTemplate = redisTemplate;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object o, Object o1) {
try{
redisTemplate.opsForValue().set(o.toString(),o1);
}catch(Exception e){
e.printStackTrace();
logger.info("添加到mybatis缓存失败");
}
}
@Override
public Object getObject(Object o) {
try{
return redisTemplate.opsForValue().get(o.toString());
}catch(Exception e){
e.printStackTrace();
logger.info("获取mybatis缓存失败");
}
return null;
}
@Override
public Object removeObject(Object o) {
try{
redisTemplate.delete(o.toString());
}catch(Exception e){
e.printStackTrace();
logger.info("从mybatis缓存移除失败");
}
return null;
}
@Override
public void clear() {
try{
redisTemplate.delete(getId());
}catch (Exception e){
logger.info("刷新mybatis失败");
}
}
@Override
public int getSize() {
return redisTemplate.keys("*").size();
}
@Override
public ReadWriteLock getReadWriteLock() {
return rwl;
}
}
同上面讲到的一样,我们需要将redisTemplate注入到缓存类 RedisMybatisCache 中,通过 RedisMybatisCacheBridge进行静态注入
/**
* 静态注入中间类
*/
@Component
public class RedisMybatisCacheBridge {
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate){
RedisMybatisCache.setRedisTemplate(redisTemplate);
}
}
然后我们需要去mapper里面开启缓存
运行一下,然后报错,最后发现是序列化的问题,上面的applicationContext.xml文件中,我们有配redis中序列化的方式为 StringRedisSerializer,实际上它在序列化对象的时候会报错,因此我们需要修改value的序列化方式,百度了一波,全都是在java文件中配置,然后通过注解加载,我也没有找到好的在xml文件中配置的方法,只有把xml中注释掉,然后在上面所写的 RedisMybatisCache 类中的 setRedisTemplate() 方法中修改它的序列化方式,如果各位大佬有好的办法,请留言......
public static void setRedisTemplate(RedisTemplate redisTemplate) {
RedisMybatisCache.redisTemplate = redisTemplate;
// 设置key和hash的field
// 设置键(key)的序列化采用StringRedisSerializer。
StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
RedisMybatisCache.redisTemplate.setKeySerializer(stringRedisSerializer);
RedisMybatisCache.redisTemplate.setHashKeySerializer(stringRedisSerializer);
//下面这个效率低,不过可以反序列化带泛型的list数据
//GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//而这个方法,效率高,不过也要做一定的设定
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置值(value)的序列化采用FastJsonRedisSerializer。
RedisMybatisCache.redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
RedisMybatisCache.redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
RedisMybatisCache.redisTemplate.afterPropertiesSet();
//开启事务
RedisMybatisCache.redisTemplate.setEnableTransactionSupport(true);
}
最终通过测试: