Spring集成Redis步骤
来源:互联网 发布:明源软件怎么样 编辑:程序博客网 时间:2024/06/02 03:02
redis简介
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
本文介绍在Spring中使用Jedis做缓存,将部分db中的数据缓存在redis中,优先从redis中获取,以提高性能。
Spring集成
1、pom.xml引入相关jar包
<!--spring redis--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </exclusion> </exclusions> <version>1.7.1.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.1</version> </dependency>
2、redis链接配置参数
配置在setting.properties文件中,在spring.xml中通过<context:property-placeholder location="classpath:setting.properties"/>
引入。
##redis连接配置redis.host=127.0.0.1redis.port=6379redis.pass=admineapredis.database=0redis.maxIdle=300redis.maxActive=600redis.maxWait=1000redis.testOnBorrow=true#当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能redis.timeout=10000
3、spring-redis.xml配置
这部分配置了redis的基本配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}"/> <!-- <property name="maxActive" value="${redis.maxActive}"/> <property name="maxWait" value="${redis.maxWait}"/>--> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}"/> </bean> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}"/> <property name="port" value="${redis.port}"/> <property name="password" value="${redis.pass}"/> <property name="database" value="${redis.database}"/> <property name="timeout" value="${redis.timeout}"/> <property name="poolConfig" ref="poolConfig"/> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> </bean></beans>
4、redis通用操作(redisDao与redisDaoImpl)
- redisDao接口实现代码
package com.cnpc.framework.base.dao;import java.util.List;import java.util.Set;/** * Created by billJiang on 2017/4/10. * e-mail:475572229@qq.com qq:475572229 */public interface RedisDao { <T> boolean add(final String key, final T obj); /** * setNx * * @param key * @param value * @return */ boolean add(final String key, final String value); <T> boolean add(final String key, final List<T> list); void delete(final String key); void delete(final List<String> keys); <T> boolean update(final String key, final T obj); boolean update(final String key, final String value); /** * 保存 不存在则新建,存在则更新 * * @param key * @param value * @return */ boolean save(final String key, final String value); <T> boolean save(final String key, final T obj); <T> T get(final String key, final Class clazz); <T> List<T> getList(final String key, final Class<T> clazz); byte[] getByte(final String key); String get(final String key); <T> void add(final String key, final long timeout, final T obj); void add(final String key, final long timeout, final byte[] object); Set<String> keys(String pattern); boolean exist(final String key); boolean set(final String key,final byte[] value); boolean flushDB(); long dbSize();}
- redisDaoImpl的代码
package com.cnpc.framework.base.dao.impl;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.BooleanCodec;import com.cnpc.framework.base.dao.RedisDao;import com.cnpc.framework.utils.StrUtil;import org.springframework.dao.DataAccessException;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.io.Serializable;import java.util.ArrayList;import java.util.List;import java.util.Set;/** * Created by billJiang on 2017/4/10. * e-mail:475572229@qq.com qq:475572229 * redis操作实体类 */@Service("redisDao")public class RedisDaoImpl implements RedisDao { @Resource protected RedisTemplate<String, Serializable> redisTemplate; /** * 设置redisTemplate * * @param redisTemplate the redisTemplate to set */ public void setRedisTemplate(RedisTemplate<String, Serializable> redisTemplate) { this.redisTemplate = redisTemplate; } public RedisTemplate<String, Serializable> getRedisTemplate() { return redisTemplate; } /** * 获取 RedisSerializer */ private RedisSerializer<String> getRedisSerializer() { return redisTemplate.getStringSerializer(); } @Override public <T> boolean add(final String key, final T obj) { return add(key, JSON.toJSONString(obj)); } @Override public <T> void add(final String key, final long timeout, final T obj) { redisTemplate.execute(new RedisCallback() { public Object doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); final byte[] object = serializer.serialize(JSON.toJSONString(obj)); add(key,timeout,object); return null; } }); } @Override public void add(final String key, final long timeout,final byte[] object) { redisTemplate.execute(new RedisCallback() { public Object doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); connection.setEx(keyStr, timeout, object); return null; } }); } @Override public boolean add(final String key, final String value) { boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] object = serializer.serialize(value); return connection.setNX(keyStr, object); } }); return result; } @Override public <T> boolean add(final String key, final List<T> list) { return this.add(key, JSON.toJSONString(list)); } @Override public void delete(final String key) { List<String> list = new ArrayList<>(); list.add(key); this.delete(list); } @Override public void delete(final List<String> keys) { redisTemplate.delete(keys); } @Override public <T> boolean update(final String key, final T obj) { return this.update(key, JSON.toJSONString(obj)); } @Override public boolean update(final String key, final String value) { if (get(key) == null) { throw new NullPointerException("数据行不存在, key = " + key); } boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] valueStr = serializer.serialize(value); connection.set(keyStr, valueStr); return true; } }); return result; } @Override public boolean save(String key, String value) { if (StrUtil.isEmpty(get(key))) { return this.add(key, value); } else { return this.update(key, value); } } @Override public <T> boolean save(String key, T obj) { if (get(key, obj.getClass()) == null) { return this.add(key, obj); } else { return this.update(key, obj); } } @Override public <T> T get(final String key, final Class clazz) { T result = redisTemplate.execute(new RedisCallback<T>() { public T doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] value = connection.get(keyStr); if (value == null) { return null; } String valueStr = serializer.deserialize(value); return (T) JSON.parseObject(valueStr, clazz); } }); return result; } @Override public <T> List<T> getList(final String key, final Class<T> clazz) { List<T> result = redisTemplate.execute(new RedisCallback<List<T>>() { public List<T> doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] value = connection.get(keyStr); if (value == null) { return null; } String valueStr = serializer.deserialize(value); return JSON.parseArray(valueStr, clazz); } }); return result; } @Override public String get(final String key) { String result = redisTemplate.execute(new RedisCallback<String>() { public String doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] value = connection.get(keyStr); if (value == null) { return null; } String valueStr = serializer.deserialize(value); return valueStr; } }); return result; } @Override public byte[] getByte(final String key) { byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() { public byte[] doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); byte[] value = connection.get(keyStr); return value; } }); return result; } @Override public Set<String> keys(final String pattern) { return redisTemplate.keys(pattern); } @Override public boolean exist(final String key){ boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); return connection.exists(keyStr); } }); return result; } @Override public boolean set(final String key,final byte[] value){ boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> serializer = getRedisSerializer(); byte[] keyStr = serializer.serialize(key); connection.set(keyStr, value); return true; } }); return result; } public boolean flushDB(){ boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { connection.flushDb(); return true; } }); return result; } public long dbSize(){ long result = redisTemplate.execute(new RedisCallback<Long>() { public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.dbSize(); } }); return result; }}
使用实例
比如,在如下场景中,我的文件夹每个栏目右侧显示的是当前类目的数量,可以将这些数据存放在redis缓存中,只要缓存中存在就从缓存中取,否则从数据库中读取。
在相关业务导致数据变化的时候,则可强制缓存失效(设置缓存过期或删除缓存),则下次再读取数据的时候因为缓存无法命中而会从数据库中读取,从而拿到最新的数据。
相关代码
@Override public Map getMessageCount() { //优先从redis中读取,不存在,则从数据库中读取,因为本数据与个人用户相关,缓存名加上用户标识 Map<String, Integer> retMap =redisDao.get(RedisConstant.MESSAGE_PRE+"count:"+SecurityUtil.getUserId(),Map.class); if(retMap==null) { retMap = new HashMap<>(); //发件箱 String hql_sent = "select count(id) from Message where sendUserID='" + SecurityUtil.getUserId() + "'"; Long count_sent = this.get(hql_sent); retMap.put("sent", count_sent.intValue()); //草稿箱 String hql_draft = "select count(id) from Message where sendUserID='" + SecurityUtil.getUserId() + "' and messageStatus='0'"; Long count_draft = this.get(hql_draft); retMap.put("draft", count_draft.intValue()); //收件箱 String hql_inbox = "select count(id) from MessageReceiver where receiveUserID='" + SecurityUtil.getUserId() + "' and deleted=0"; Long count_inbox = this.get(hql_inbox); retMap.put("inbox", count_inbox.intValue()); //回收站 String hql_trash = "select count(id) from MessageReceiver where receiveUserID='" + SecurityUtil.getUserId() + "' and deleted=1 "; Long count_trash = this.get(hql_trash); retMap.put("trash", count_trash.intValue()); //将结果存入缓存 redisDao.add(RedisConstant.MESSAGE_PRE+"count:"+SecurityUtil.getUserId(), retMap); return retMap; }else { return retMap; } } @Override public void deleteCacheForMsgCount(){ redisDao.delete(RedisConstant.MESSAGE_PRE+"count:"+SecurityUtil.getUserId()); }
数据变化将缓存删除或设置为过期
@RequestMapping(value = "/save") @ResponseBody public Result save(String message) { Message msgobj = JSON.parseObject(message, Message.class); //保存为草稿或保存并直接发送 messageService.deleteCacheForMsgCount(); return messageService.saveMessage(msgobj); } @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST) @ResponseBody public Result delete(@PathVariable("id") String id) { Message message = this.get(id); if (!MessageConstant.SEND_STATUS_DRAFT.equals(message.getMessageStatus())) { return new Result(false, "该消息不是草稿状态,不能删除"); } try { messageService.delete(message); messageService.deleteCacheForMsgCount(); return new Result(); } catch (Exception e) { return new Result(false, "该数据已经被引用,不可删除"); } }
使用缓存后,性能对比
下面对比了请求,上面是通过redis缓存读取,下面是通过数据库读取,两次用时差别很多,说明使用redis缓存可以显著提高性能。
- Spring集成Redis步骤
- spring redis 集成 详细步骤
- Spring Struts2集成步骤
- Spring Struts2集成步骤
- Spring 集成步骤
- redis与Spring集成
- Spring与redis集成
- redis与spring集成
- Spring Cache集成redis
- Spring 集成 Redis
- spring-data集成redis
- redis spring 集成
- spring集成redis详解
- Spring Cache集成redis
- spring redis集成
- spring redis集成
- Spring集成Redis示例
- Spring session redis集成
- 欢迎使用CSDN-markdown编辑器
- 使用mybatis-generator自动生成Dao,Model,Mapping
- Oracle常见问题记载
- 3.《MySQL必知必会》函数与汇总
- 翻煎饼问题(代码及解析)
- Spring集成Redis步骤
- PAT乙级(Basic Level)练习题 >分解因数
- 例题6-13 古代象形符号 UVa1103
- 微信开发 一 接入篇
- Codeforces Round #410 (Div. 2) C. Mike and gcd problem 贪心
- Tomcat项目部署shell脚本
- 批处理 自动关闭若干进程,以备关机
- ubuntu 更改wifi的mac地址
- 【IMWeb训练营作业】