SSM之Redis自动/手动设置缓存

Redis Spring配置(供参考!)

1添加redis自动操作配置

1可以通过设置相关类的mapper.xml加入<cache type="com.xxx.util.RedisCache"></cache>用来调用一个工具类并实现Cache接口,从而在实现业务SQL时,自动使用redis存入对应的SQL返回的内容,达到提高性能的效果

具体代码部分:

对应需要使用redis的mapperXML文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.lzx.mapper.ClassesMapper" >
  <cache type="com.lzx.util.RedisCache"></cache><!-- 这里 -->
  <resultMap id="BaseResultMap" type="com.lzx.entity.Classes" >
    <id column="cid" property="cid" jdbcType="INTEGER" />
    <result column="classname" property="classname" jdbcType="VARCHAR" />
    <result column="classaddress" property="classaddress" jdbcType="VARCHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    cid, classname, classaddress
  </sql>
<!-- 这里后面的省略。。-->

工具类

//工具类

@Component
public class RedisCache implements Cache {

	private static JedisConnectionFactory jcf;

	public void setJcf(JedisConnectionFactory jcf) {
		RedisCache.jcf = jcf;
	}

	private String id;

    private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public RedisCache(String id) {
        if (id == null) {
            throw new IllegalArgumentException("id is null");
        }
        this.id = id;
    }

    public RedisCache() {

    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public void putObject(Object key, Object value) {
        JedisConnection connection = null;
        try {
        	System.out.println("abc:"+jcf);
            connection = jcf.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            connection.set(serializer.serialize(key), serializer.serialize(value));
            connection.lPush(serializer.serialize(id),serializer.serialize(key));
            System.out.println("写入缓存:" + key + "," + value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public Object getObject(Object key) {
        Object res = null;
        JedisConnection connection = null;
        try {
            connection = jcf.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            res = serializer.deserialize(connection.get(serializer.serialize(key)));
            if (res != null) {
                System.out.println("获取缓存数据:" + res.toString());
            } else {
                System.out.println("当前没有缓存:" + key);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return res;
    }

    @Override
    public Object removeObject(Object key) {
        Object res = null;
        JedisConnection connection = null;
        try {
            connection = jcf.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            res = connection.expire(serializer.serialize(key), 0);
            connection.lRem(serializer.serialize(id),0,serializer.serialize(key));
            System.out.println("删除缓存:" + key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return res;
    }

    @Override
    public void clear() {
        JedisConnection connection = null;
        try {
            connection = jcf.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
//            connection.flushDb();
//            connection.flushAll();
            Long length = connection.lLen(serializer.serialize(id));
            if (0 == length) {
                return;
            }
            List<byte[]> keys = connection.lRange(serializer.serialize(id),0,length-1);
            for (byte[] key :keys) {
                connection.expireAt(key,0);
                System.out.println("删除缓存:"+serializer.deserialize(key).toString());
            }
            connection.expireAt(serializer.serialize(id),0);
            keys.clear();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public int getSize() {
        int result = 0;
        JedisConnection connection = null;
        try {
            connection = jcf.getConnection();
            result = Integer.valueOf(connection.dbSize().toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return this.readWriteLock;
    }


}

局限性:但仅仅用于小型项目中,若业务中需要不断修改查询数据,则redis起不到效果反而成为累赘。

这里就需要用到手动添加redis调用。也是普遍用的最多的方法。

2手动配置Redis缓存

   a) 万事第一步,检查包pom.xml的依赖是否正确导入,这里是我使用到的依赖

<!-- redis -->
	    <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
      	</dependency>
	    <!-- redis-spring -->
	    <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.2.RELEASE</version>
		</dependency>

   b) 在Spring的配置文件applicationContext.xml中添加配置

<!-- redis配置 -->
	<bean id="PoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="600"/>
		<property name="maxIdle" value="300"/>
		<property name="maxWaitMillis" value="1000"/>
		<property name="testOnBorrow" value="true"/>
	</bean>
	
	<bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="localhost"/>
		<property name="port" value="6379"/>
		<property name="password" value=""/>
		<property name="poolConfig" ref="PoolConfig"/>
	</bean>
	<!-- 使用字符串进行序列化 -->
	<bean id="StringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer">
	</bean>
	<!-- 使用JDK的序列化进行转化 -->
	<bean id="JdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer">
	</bean>
	<!-- 配置Spring RedisTemplate -->
	<bean id="RedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="JedisConnectionFactory"/>
		<property name="keySerializer" ref="StringRedisSerializer"/>
		<property name="valueSerializer" ref="JdkSerializationRedisSerializer"/>
	</bean>
	<!-- 注册Redis工具类 -->
	<bean id="redisCeche" class="com.lzx.util.RedisCeche"></bean>

   c) 创建对应工具类手动创建调用方法

<context:component-scan base-package="xxx"></context:component-scan>

           因为注册了bean,注意使用@Componet,然后私有化一个RedisTemplate 类自动注入一个redisTemplate类(注意spring配置文件的包扫描,不然无法找到该bean)然后给setter redisTemplate方法,接着就是创建需要的关于Redis的set、get、delete等方法,具体看以下代码:

@Component
public class RedisCeche {
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
	public boolean set(final String key, Object value) {
		 boolean result = false;
		 try {
			 ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			 operations.set(key, value);
			 System.out.println("set data:"+key+","+value+" to redis");
			 result = true;
		 } catch (Exception e) {
			 System.out.println("set cache error");
		 }
		 return result;
		 }	
	public Object get(final String key) {
		Object result = null;
		try {
			 ValueOperations<String,Object> operations = redisTemplate.opsForValue();
			 result = operations.get(key);
			 System.out.println("get data:"+key+" from redis");
		}
		catch (Exception e) {
			System.out.println("get cache error");
			// TODO: handle exception
		}
		return result;
	}
//	通过key删除
	public boolean deletebykey(final String key) {
		boolean result = false;
		try {
			System.out.println("找关于 Key:"+key+"并删除,或者key本身不存在");
			redisTemplate.delete(key);
			
			if (get(key)==null) {
				System.out.println("已删除 Key:"+key);
				result = true;
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("error delete by key from redis ,check your correct key!");
		}
		return result;
		
	}
//	通过key的 模糊查询 并根据对应key批量删除
	@SuppressWarnings("unused")
//	@SuppressWarnings("unused") 表示该属性在方法或类中没有使用。添加此注解可以去除属性上的黄色警告!!!
	public boolean deletebypattern(final String pattern) {
		boolean result = false;
		List<Object> strsList = new ArrayList<Object>();
		try {
			Set<String> keys = redisTemplate.keys(pattern);
			if(keys.size()>0) {
				redisTemplate.delete(keys);
				for (String s : keys) {
					strsList.add((Object) get(s));
				}
			}		
			if(strsList.size()==0) {
				result = true;
				System.out.println("Find keys pattern:"+pattern+"from redis and it has been deleted!");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("error delete by keypattern from redis ,check your correct pattern!");
		}
		return result;
		
	}

}

不仅仅这是这些还有的可以通过查看redisTemplate的源代码进行合理调用就可!,我的代码可能不完全最优,仅供参考!

   d) 然后就是实现与调用工具类的方法进行Redis的真正操作了

      1 我这里就做了查询students所有的操作

      我的Studentsservice interface 代码如下:

public interface StudentService {
	public List<Students> getAllstu();
	public void dropdatafromRedisbykey(String key);
	public void dropdatafromRedisbyPattern(String Pattern);
}

      2 然后在StudentServiceImpl文件中如下操作:(这里用到applicationContext.xml中注册的Bean,因此用来自动注入方便使用)

	<!-- 注册Redis工具类 -->
	<bean id="redisCeche" class="com.lzx.util.RedisCeche"></bean>
@Service
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED,noRollbackFor = Exception.class)
public class StudentsImpl implements StudentService {
	@Autowired
	private StudentsMapper sm;
	@Autowired
	private RedisCeche rc;
	@Override
	public List<Students> getAllstu() {
		List<Students> stuList = new ArrayList<Students>();
		try {
			stuList = (List<Students>) rc.get("stu");
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("error get from redis!");
		}
		if(stuList==null) {
			stuList = sm.selectAll();
			rc.set("stu", stuList);
		}
		return stuList;
		// TODO Auto-generated method stub
		
	}
	@Override
	public void dropdatafromRedisbykey(String key) {
		// TODO Auto-generated method stub
		rc.deletebykey(key);
	}
	@Override
	public void dropdatafromRedisbyPattern(String Pattern) {
		// TODO Auto-generated method stub
		rc.deletebypattern(Pattern);
	}

}

 e) 然后回到StudentController中,调用service的实现方法,我这里使用了Resetful风格的url以及,使用json的格式返回前端(具体需要配置xml以即maven依赖),我没有使用视图返回,我使用了postman测试可行!

   

@Controller
public class StudentsController{
	@Autowired
	private StudentService studentService;
	Map<String, Object> map = new HashMap<String, Object>();
	@GetMapping(value = "/Student/getall")
	@ResponseBody
	public Object getall() {
		map.clear();
		List<Students> stulist= studentService.getAllstu();
		map.put("stulist", stulist);
		return map;
	}
	@PostMapping(value ="/Student/dropredisbykey/{key}")
	@ResponseBody
	public Object dodrop(@PathVariable(name = "key") String key) {
		map.clear();
		studentService.dropdatafromRedisbykey(key);
		map.put("dropkey", key);
		return map;
	}
	@PostMapping(value ="/Student/dropredisbypattern/{pattern}")
	@ResponseBody
	public Object dodrops(@PathVariable(name = "pattern") String pattern) {
		map.clear();
		studentService.dropdatafromRedisbyPattern(pattern);
		map.put("dropkeys", pattern);
		return map;
	}
}

   f) 测试结果:

      1 首先测试删除功能,先cmd运行,开启Redis服务,添加测试数据

     2 其次,使用postman 测试pattern

使用postman 测试key

使用postman 测试业务逻辑,调用redis作为缓存使用

  大致原理是:从数据库中获得数据,然后存入redis中,第二次使用时,先去redis查询有没有此key,若无则从数据库查询,再存入redis,

注意请求方式是post 还是get。

到此,完成基本的手动添加redis缓存写入的方法,用于记录学习过程,希望对大家有帮助!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值