Spring+Mybatis+redis整合(用注解的方式)

23 篇文章 1 订阅

手动的操作缓存自己解决了,原本想着以后就用手动的方式,可是不研究研究注解感觉自己错过了什么,现在弄完了,感觉真是简单,比手动的方式简单太多了,可能是我直接用的别人的工具类可能简单,如果手动的方式中redisDao命令全了,可能会感觉差不多,不过还是有点区别的,不是很大,看你的需求了

手动方式操作redis请看这:https://blog.csdn.net/weixin_43113679/article/details/90413124

现在先看目录结构

在这里插入图片描述
特别解释一下:cn.qlq.util是redis的工具包,里面的基本不需要改变
      目前就算要修改也就有两个地方需要修改
      1、修改key的生命周期
      2、修改key的格式
现在直接开始部署xml

使用的java类

RedisCacheConfig.java
package cn.qlq.util;

import java.lang.reflect.Method;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
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.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
    private volatile JedisConnectionFactory jedisConnectionFactory;
    private volatile RedisTemplate<String, String> redisTemplate;
    private volatile RedisCacheManager redisCacheManager;

    public RedisCacheConfig() {
        super();
    }

    /**
     * 带参数的构造方法 初始化所有的成员变量
     * 
     * @param jedisConnectionFactory
     * @param redisTemplate
     * @param redisCacheManager
     */
    public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
            RedisCacheManager redisCacheManager) {
        this.jedisConnectionFactory = jedisConnectionFactory;
        this.redisTemplate = redisTemplate;
        this.redisCacheManager = redisCacheManager;
    }

    public JedisConnectionFactory getJedisConnecionFactory() {
        return jedisConnectionFactory;
    }

    public RedisTemplate<String, String> getRedisTemplate() {
        return redisTemplate;
    }

    public RedisCacheManager getRedisCacheManager() {
        return redisCacheManager;
    }
    @Bean
    public KeyGenerator keyGenerator() {
      return new KeyGenerator() {
    	//规定  本类名-方法名-参数名 为key(这个是没有自己指定key的时候,自己默认生成的)
        @Override
        public Object generate(Object o, Method method, Object... params) {
          StringBuilder sb = new StringBuilder();
          sb.append(o.getClass().getName());
          sb.append("-");
          sb.append(method.getName());
          sb.append("-");
          for (Object param : params) {
            sb.append(param.toString());
          }
          return sb.toString();
        }
      };
    }
   
}

KeyGenerator的generate是当你没有指定key的时候,它会根据规则进行自己生成,redis用的好,有一个关键就是key要设置的强大

RedisUtil.java
package cn.qlq.util;

import java.util.List;  
import java.util.Map;  
import java.util.Set;  
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;  
  
  
/** 
 *  
 * @author QLQ
 * 基于spring和redis的redisTemplate工具类 
 * 针对所有的hash 都是以h开头的方法 
 * 针对所有的Set 都是以s开头的方法                    不含通用方法 
 * 针对所有的List 都是以l开头的方法 
 */  
@Component//交给Spring管理(在需要缓存的地方自动注入即可使用)
public class RedisUtil {  
  
    @Autowired//(自动注入redisTemplet)
    private RedisTemplate<String, Object> redisTemplate;  
      
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {  
        this.redisTemplate = redisTemplate;  
    }  
    //=============================common============================  
    /** 
     * 指定缓存失效时间 
     * @param key 键 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean expire(String key,long time){  
        try {  
            if(time>0){  
                redisTemplate.expire(key, time, TimeUnit.SECONDS);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 根据key 获取过期时间 
     * @param key 键 不能为null 
     * @return 时间(秒) 返回0代表为永久有效 
     */  
    public long getExpire(String key){  
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);  
    }  
      
    /** 
     * 判断key是否存在 
     * @param key 键 
     * @return true 存在 false不存在 
     */  
    public boolean hasKey(String key){  
        try {  
            return redisTemplate.hasKey(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 删除缓存 
     * @param key 可以传一个值 或多个 
     */  
    @SuppressWarnings("unchecked")  
    public void del(String ... key){  
        if(key!=null&&key.length>0){  
            if(key.length==1){  
                redisTemplate.delete(key[0]);  
            }else{  
                redisTemplate.delete(CollectionUtils.arrayToList(key));  
            }  
        }  
    }  
      
    //============================String=============================  
    /** 
     * 普通缓存获取 
     * @param key 键 
     * @return 值 
     */  
    public Object get(String key){  
        return key==null?null:redisTemplate.opsForValue().get(key);  
    }  
      
    /** 
     * 普通缓存放入 
     * @param key 键 
     * @param value 值 
     * @return true成功 false失败 
     */  
    public boolean set(String key,Object value) {  
         try {  
            redisTemplate.opsForValue().set(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
          
    }  
      
    /** 
     * 普通缓存放入并设置时间 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 
     * @return true成功 false 失败 
     */  
    public boolean set(String key,Object value,long time){  
        try {  
            if(time>0){  
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);  
            }else{  
                set(key, value);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 递增 
     * @param key 键 
     * @param by 要增加几(大于0) 
     * @return 
     */  
    public long incr(String key, long delta){    
        if(delta<0){  
            throw new RuntimeException("递增因子必须大于0");  
        }  
        return redisTemplate.opsForValue().increment(key, delta);  
    }  
      
    /** 
     * 递减 
     * @param key 键 
     * @param by 要减少几(小于0) 
     * @return 
     */  
    public long decr(String key, long delta){    
        if(delta<0){  
            throw new RuntimeException("递减因子必须大于0");  
        }  
        return redisTemplate.opsForValue().increment(key, -delta);    
    }    
      
    //================================Map=================================  
    /** 
     * HashGet 
     * @param key 键 不能为null 
     * @param item 项 不能为null 
     * @return 值 
     */  
    public Object hget(String key,String item){  
        return redisTemplate.opsForHash().get(key, item);  
    }  
      
    /** 
     * 获取hashKey对应的所有键值 
     * @param key 键 
     * @return 对应的多个键值 
     */  
    public Map<Object,Object> hmget(String key){  
        return redisTemplate.opsForHash().entries(key);  
    }  
      
    /** 
     * HashSet 
     * @param key 键 
     * @param map 对应多个键值 
     * @return true 成功 false 失败 
     */  
    public boolean hmset(String key, Map<String,Object> map){    
        try {  
            redisTemplate.opsForHash().putAll(key, map);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * HashSet 并设置时间 
     * @param key 键 
     * @param map 对应多个键值 
     * @param time 时间(秒) 
     * @return true成功 false失败 
     */  
    public boolean hmset(String key, Map<String,Object> map, long time){    
        try {  
            redisTemplate.opsForHash().putAll(key, map);  
            if(time>0){  
                expire(key, time);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 向一张hash表中放入数据,如果不存在将创建 
     * @param key 键 
     * @param item 项 
     * @param value 值 
     * @return true 成功 false失败 
     */  
    public boolean hset(String key,String item,Object value) {  
         try {  
            redisTemplate.opsForHash().put(key, item, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 向一张hash表中放入数据,如果不存在将创建 
     * @param key 键 
     * @param item 项 
     * @param value 值 
     * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间 
     * @return true 成功 false失败 
     */  
    public boolean hset(String key,String item,Object value,long time) {  
         try {  
            redisTemplate.opsForHash().put(key, item, value);  
            if(time>0){  
                expire(key, time);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 删除hash表中的值 
     * @param key 键 不能为null 
     * @param item 项 可以使多个 不能为null 
     */  
    public void hdel(String key, Object... item){    
        redisTemplate.opsForHash().delete(key,item);  
    }   
      
    /** 
     * 判断hash表中是否有该项的值 
     * @param key 键 不能为null 
     * @param item 项 不能为null 
     * @return true 存在 false不存在 
     */  
    public boolean hHasKey(String key, String item){  
        return redisTemplate.opsForHash().hasKey(key, item);  
    }   
      
    /** 
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回 
     * @param key 键 
     * @param item 项 
     * @param by 要增加几(大于0) 
     * @return 
     */  
    public double hincr(String key, String item,double by){    
        return redisTemplate.opsForHash().increment(key, item, by);  
    }  
      
    /** 
     * hash递减 
     * @param key 键 
     * @param item 项 
     * @param by 要减少记(小于0) 
     * @return 
     */  
    public double hdecr(String key, String item,double by){    
        return redisTemplate.opsForHash().increment(key, item,-by);    
    }    
      
    //============================set=============================  
    /** 
     * 根据key获取Set中的所有值 
     * @param key 键 
     * @return 
     */  
    public Set<Object> sGet(String key){  
        try {  
            return redisTemplate.opsForSet().members(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
      
    /** 
     * 根据value从一个set中查询,是否存在 
     * @param key 键 
     * @param value 值 
     * @return true 存在 false不存在 
     */  
    public boolean sHasKey(String key,Object value){  
        try {  
            return redisTemplate.opsForSet().isMember(key, value);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 将数据放入set缓存 
     * @param key 键 
     * @param values 值 可以是多个 
     * @return 成功个数 
     */  
    public long sSet(String key, Object...values) {  
        try {  
            return redisTemplate.opsForSet().add(key, values);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
      
    /** 
     * 将set数据放入缓存 
     * @param key 键 
     * @param time 时间(秒) 
     * @param values 值 可以是多个 
     * @return 成功个数 
     */  
    public long sSetAndTime(String key,long time,Object...values) {  
        try {  
            Long count = redisTemplate.opsForSet().add(key, values);  
            if(time>0) expire(key, time);  
            return count;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
      
    /** 
     * 获取set缓存的长度 
     * @param key 键 
     * @return 
     */  
    public long sGetSetSize(String key){  
        try {  
            return redisTemplate.opsForSet().size(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
      
    /** 
     * 移除值为value的 
     * @param key 键 
     * @param values 值 可以是多个 
     * @return 移除的个数 
     */  
    public long setRemove(String key, Object ...values) {  
        try {  
            Long count = redisTemplate.opsForSet().remove(key, values);  
            return count;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
    //===============================list=================================  
      
    /** 
     * 获取list缓存的内容 
     * @param key 键 
     * @param start 开始 
     * @param end 结束  0 到 -1代表所有值 
     * @return 
     */  
    public List<Object> lGet(String key,long start, long end){  
        try {  
            return redisTemplate.opsForList().range(key, start, end);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
      
    /** 
     * 获取list缓存的长度 
     * @param key 键 
     * @return 
     */  
    public long lGetListSize(String key){  
        try {  
            return redisTemplate.opsForList().size(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
      
    /** 
     * 通过索引 获取list中的值 
     * @param key 键 
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 
     * @return 
     */  
    public Object lGetIndex(String key,long index){  
        try {  
            return redisTemplate.opsForList().index(key, index);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
      
    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, Object value) {  
        try {  
            redisTemplate.opsForList().rightPush(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, Object value, long time) {  
        try {  
            redisTemplate.opsForList().rightPush(key, value);  
            if (time > 0) expire(key, time);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, List<Object> value) {  
        try {  
            redisTemplate.opsForList().rightPushAll(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, List<Object> value, long time) {  
        try {  
            redisTemplate.opsForList().rightPushAll(key, value);  
            if (time > 0) expire(key, time);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  
      
    /** 
     * 根据索引修改list中的某条数据 
     * @param key 键 
     * @param index 索引 
     * @param value 值 
     * @return 
     */  
    public boolean lUpdateIndex(String key, long index,Object value) {  
        try {  
            redisTemplate.opsForList().set(key, index, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }   
      
    /** 
     * 移除N个值为value  
     * @param key 键 
     * @param count 移除多少个 
     * @param value 值 
     * @return 移除的个数 
     */  
    public long lRemove(String key,long count,Object value) {  
        try {  
            Long remove = redisTemplate.opsForList().remove(key, count, value);  
            return remove;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
      
}
UserServiceimpl.java
/**
 * 
 */
package service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import bean.User;
import cn.qlq.util.RedisUtil;
import mapper.UserMapper;

@Transactional(rollbackFor=Exception.class)
@Service(value="userService")
public class UserServiceImpl implements UserService{
	//用于手动添加缓存
	@Autowired
	private RedisUtil redisUtil = null;
	@Autowired
	private UserMapper userMapper = null;
	
	//查询出来的时候添加单个缓存
	@Cacheable(value="user",key="'user'+#id.toString()")
	@Override
	public User getUserById(int id) throws Exception {
		//结果出来不用自己主动去添加,交给Spring去管理添加
		return  userMapper.getUserById(id);
				
	}
	//删除数据库的时候删除redis的缓存
	@CacheEvict(value="user",key="'user'+#id.toString()")
	@Override
	public void deleteById(int id) throws Exception {
		 
		 try {
			 userMapper.deleteById(id);
         } catch (Exception ex) {
         	System.out.println("删除信息失败,强制回滚");
         	TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
             throw ex;
         }		
	}
	//添加缓存
    @Cacheable(value="Alluser")
    @Override
    public List<User> getUserList() throws Exception { 
        return  userMapper.getUserList();
    }
    //清除上面的缓存,同时手动的添加一个缓存看能否实现
    //答案:不能清除上面的缓存,但是手动添加一个缓存实现了,后面就会知道原因了
    @CacheEvict(value="Alluser")
    @Override
    public User addUser(int id) throws Exception {
        redisUtil.set("mykey", "myvalue");
        return userMapper.getUserById(id);
    }
		
}
测试类
/**
 * 
 */
package test;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import bean.User;
import service.UserService;



/**
 * @author 作者
 * @data 2019年5月29日 
 */
public class ServiceTest {
	@Autowired
	 private ApplicationContext ctx = null;
	 @Autowired
    private UserService userService = null;
	 
	//根据用户 的id
	@Test
	public void getUser() throws Exception {
		ctx = new ClassPathXmlApplicationContext("spring/spring-service.xml");
        userService = ctx.getBean(UserService.class);
		int id =1;		 
	     User user = userService.getUserById(id);  
	     System.out.println(user.toString());
	    
	 }
	//根据用户id删除缓存
	@Test
	public void delete() throws Exception {
		ctx = new ClassPathXmlApplicationContext("spring/spring-service.xml");
        userService = ctx.getBean(UserService.class);
		int id =1;
	      userService.deleteById(id);
	 }
	 //查询所有对象
	@Test
	public void getUserList() throws Exception {
		ctx = new ClassPathXmlApplicationContext("spring/spring-service.xml");
        userService = ctx.getBean(UserService.class);
	      List<User> list=userService.getUserList();
	     for(int i=0;i<list.size();i++) {
	    	 System.out.println(list.get(i).toString());
	     }
	    
	 }
	 //删除上面查询的所有对象的缓存,
	 //再自己手动添加一个缓存,
	 //再去数据库返回一个对象看看是否能自动添为缓存
	@Test
	public void deleteUser() throws Exception {
		ctx = new ClassPathXmlApplicationContext("spring/spring-service.xml");
        userService = ctx.getBean(UserService.class);
		int id =2;	 
	     User user = userService.addUser(id);
	     System.out.println(user.toString());

	 }
}

类就差不多可,但是需要注意的一点
在这里插入图片描述
存进缓存里的对象一定要有Serializable(序列化)接口,我们就可以直接存对象,有Spring容器把对象转成json字符串,不需要我们自己去转了
pom.xml必须有下面的包

 <!-- json配置-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0.pr3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0.pr3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0.pr3</version>
    </dependency>
    <dependency>

配置文件

redis.properties
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.dbIndex=0
redis.expiration=3000
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
spring-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:cache="http://www.springframework.org/schema/cache" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    					http://www.springframework.org/schema/beans/spring-beans.xsd 
    					http://www.springframework.org/schema/context 
    					http://www.springframework.org/schema/context/spring-context.xsd
    					http://www.springframework.org/schema/cache 
    					http://www.springframework.org/schema/cache/spring-cache.xsd 
    					http://www.springframework.org/schema/aop 
    					http://www.springframework.org/schema/aop/spring-aop.xsd 
    					http://www.springframework.org/schema/tx 
    					http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 连接池基本参数配置,类似数据库连接池 -->
    <context:property-placeholder location="classpath:redis/redis.properties" ignore-unresolvable="true" />
    <!-- 缓存注解开启 -->
    <cache:annotation-driven cache-manager="redisCacheManager" key-generator="keyGenerator"/>
    <!-- redis连接池 -->  
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- 连接池配置,类似数据库连接池 -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"></property>
        <property name="port" value="${redis.port}"></property>
        <!-- <property name="password" value="${redis.pass}"></property> -->
        <property name="poolConfig" ref="poolConfig"></property>
    </bean>

    <!--redis操作模版,使用该对象可以操作redis  -->  
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >    
        <property name="connectionFactory" ref="jedisConnectionFactory" />    
        <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!!  -->    
        <property name="keySerializer" >    
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />    
        </property>    
        <property name="valueSerializer" >    
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />    
        </property>    
        <property name="hashKeySerializer">    
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>    
        </property>    
        <property name="hashValueSerializer">    
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>    
        </property>    
        <!--开启事务  -->  
        <property name="enableTransactionSupport" value="true"></property>  
    </bean >   


      <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="${redis.expiration}" />
    </bean>
	<!-- 下面就需要自己去写java类去实现 -->
    <!-- 配置RedisCacheConfig -->
    <bean id="redisCacheConfig" class="cn.qlq.util.RedisCacheConfig">
        <constructor-arg ref="jedisConnectionFactory"/>
        <constructor-arg ref="redisTemplate"/>
        <constructor-arg ref="redisCacheManager"/>
    </bean>
	
	 <!--自定义redis工具类,在需要缓存的地方注入此类  -->  
    <bean id="redisUtil" class="cn.qlq.util.RedisUtil">  
        <property name="redisTemplate" ref="redisTemplate" />  
    </bean>  
    <!-- 下面这个是整合Mybatis的二级缓存使用的 -->
 <!--    <bean id="redisCacheTransfer" class="cn.qlq.jedis.RedisCacheTransfer">
        <property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
    </bean>
--> 
</beans>
sqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
					"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- MyBatis的全局参数设置,基本用来进行MyBatis的优化处理 -->
	<settings>
		<!-- 开启二级缓存,这个需要开启 -->
		<setting name="cacheEnabled" value="true"/>
		<!-- 下面的是延迟加载 -->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!-- 是否开启延迟加载 -->
		<setting name="aggressiveLazyLoading" value="false"/>
		<!-- 缓冲加载 -->
		<setting name="cacheEnabled" value="true"/>
	</settings>
	
	<typeAliases>
		<package name="bean.User"/>
	</typeAliases>
	
</configuration>
spring-service
<import resource="spring-dao.xml"/>
<import resource="classpath*:/redis/spring-redis.xml"/>

加上上面两个,因为测试,所以需要,当生成项目时就用web.xml扫描了,就可以把上面的这两行删除
其他配置文件就是ssm的配置文件,基本上没什么需要修改

测试结果

1、测试类的第一个测试:根据id查询对象

在这里插入图片描述
在这里插入图片描述
spring-data-redis设置缓存的时候是将value的值加上~keys 存为一个zset,值就是每个具体的缓存的key,另一个具体的缓存的key注解里因为有key="‘user’+#id.toString()",所以存储在缓存里的key就是自己注解里的key,下面第三个测试将说明注解的key不写会怎么生成缓存的key
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面这个图说明了自己用注解存在缓存里的都有生命周期,这个可以修改,在redis.properties的redis.expiration配置上,单位是秒
建议缓存里的键的生命周期为6到9个小时,可以缓解缓存压力

2、测试类的第二个测试:删除缓存里的数据

在这里插入图片描述

3、测试类的第三个测试:获取数据库的所有对象,返回list集合(注解上专门不写key尝试)

在这里插入图片描述
在这里插入图片描述
上面图那一长串就是注解不写key,所以Spring容器自己生成key添加缓存里,用的是RedisCacheConfig.java里的
在这里插入图片描述
上面重新书写了默认生成key的规则类名-方法名-参数名。但是上图还是有区别的,因为我没有添加参数,所以最后是 - 结尾
在这里插入图片描述
在这里插入图片描述
这个也是,会自动添加生命周期自己需要去修改生命周期,现在生命周期为3000s

4、测试类的第四个测试:测验删除第三个测试的缓存数据,并手动添加数据(用RedisUtil.java),

在这里插入图片描述
上图有了mykey,说明手动添加缓存没有任何问题,
但是第三个测试的那两个key没有删除,说明删除失败:其实从没有key时生成默认key的生成规则就知道**,最后一个测试生成的 key第三个测试 默认生成的key根部就不可能相同,因为他们的方法名就不相同

总结:

如果在注解里注明了key的具体值,那么在缓存里会生成两个键

  1. 一个是zset,里面存的是具体的key,命名规则是value+~keys
  2. 一个是String,里面存的是数据库返回的对象(集合/字符串),对象和集合需要转成json
    例子:
@CacheEvict(value="user",key="'user'+#id.toString()")

如果不在注解里注明key的具体值,就是不写,那么Spring会根据KeyGeneratorgenerate(需要自己重写)的规则自己生成一个默认的key代替注解里没写的key执行生成上面那两个键
例子:

@Cacheable(value="Alluser")

最后说一下手动和注解实现redis当缓存的区别(个人感觉)

手动:会有小一些麻烦,在service层必须考虑redis的实现,很像顺序结构,到service 层 先考虑缓存再考虑数据库再考虑缓存(这三步都必须要考虑到,因为要时刻想到最坏的结果,缓存里没有)。比较自由,可以自己设定key的值,可以没有任何规则可言,自己设定生命周期(可以有的key就是很长,有的可以就是很短),还可以实现发布/订阅模式,实现消息队列,这些都可以用手动的方式解决
注解:比较简单,不过我感觉不如手动的功能多,如果用注解方式,redis就是用的它缓存的功能(没错,redis大部分情况下都是用它的缓存),用注解肯定要多生成一个zset,在逻辑上不用操心,只要在service的方法上写上注解valuekey…的该写的都写上,就没问题了,方法里的逻辑结构可以就不用考虑redis缓存的问题了,思维更加简单。

算法上有时间换空间或者空间换时间,根据不同的情况用不同的换法
redis实现缓存功能是灵活换简单,要想redis灵活运用就不要嫌麻烦嫌麻烦用注解就不要嫌弃它不够灵活(死板)
再次强调,注解方式尽量自己一定要写上key,要不注解运用起来特别的难用

下面摘抄自

https://www.cnblogs.com/qlqwjy/p/8574121.html

@Cacheable 作用和配置方法

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@Cacheable 主要的参数
value缓存的名称,缓存中具体哪个数据库,在 spring 配置文件中定义,必须指定至少一个例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合,或者方法参数列表中的任意一个参数,或者字符串+参数组合例如:@Cacheable(value=”testcache”,key=”#userName”) @Cacheable(value=”testcache”,key=” ‘字符串’+#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
@CachePut 作用和配置方法

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable不同的是,它每次都会触发真实方法的调用

@CachePut 主要的参数
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
@CacheEvict 作用和配置方法

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空

@CacheEvict 主要的参数
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:@CachEvict(value=”mycache”) 或者 @CachEvict(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:@CachEvict(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存例如:@CachEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存例如:@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存例如:@CachEvict(value=”testcache”,beforeInvocation=true)


spEL表达式的使用方法http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/expressions.html
关于缓存注解更详细的使用方法参考:http://www.cnblogs.com/qlqwjy/p/8559119.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值