SSM+redis整合

ssm框架之前已经搭建过了,这里不再做代码复制工作。

这里主要是利用redis去做mybatis的二级缓存,mybaits映射文件中所有的select都会刷新已有缓存,如果不存在就会新建缓存,所有的insert,update操作都会更新缓存。

redis的好处也显而易见,可以使系统的数据访问性能更高。本节只是展示了整合方法和效果,后面会补齐redis集群、负载均衡和session共享的文章。

下面就开始整合工作:

03.redis+ssm整合(mybatis二级缓存)_第1张图片

后台首先启动redis-server(后台启动与远程连接linux服务的方法都需要改redis.conf文件),启动命令“./src/redis-server ./redis.conf”

我这里是windows系统下开发的,推荐一个可视化工具“Redis Desktop manager”,需要远程连接linux下的redis,需要linux下开启端口对外开放(具体方法是修改/etc/sysconfig/iptables文件,增加对外端口开发命令)。

以上操作都完成后,即可远程连接成功了,如图:

03.redis+ssm整合(mybatis二级缓存)_第2张图片

03.redis+ssm整合(mybatis二级缓存)_第3张图片

现在还没有缓存记录,下面进入代码阶段,首先在pom.xml中增加需要的redis jar包

 1  2             redis.clients 3             jedis 4             2.9.0 5          6          7          8             org.springframework.data 9             spring-data-redis10             1.6.2.RELEASE11         12         13         14             org.mybatis15             mybatis-ehcache16             1.0.017         18           19         20             com.alibaba21             druid22             1.0.2423         

pom.xml写好后,还需要新增两个配置文件:redis.properties

redis.host=192.168.0.109
redis.port=6379
redis.pass=123456
redis.maxIdle=200
redis.maxActive=1024
redis.maxWait=10000
redis.testOnBorrow=true

其中字段也都很好理解,再加入配置文件:spring-redis.xml

 1 19       20       21     22      23      24     25         26         27         28     29     30     31     32         33         34         35          36     37     38     39     52     53         54     55 

配置文件写好后,就开始java代码的编写:

JedisClusterFactory.java

  1 package com.cjl.util;  2   3 import java.util.HashSet;  4 import java.util.Properties;  5 import java.util.Set;  6 import java.util.regex.Pattern;  7   8 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;  9 import org.springframework.beans.factory.FactoryBean; 10 import org.springframework.beans.factory.InitializingBean; 11 import org.springframework.core.io.Resource; 12  13 import redis.clients.jedis.HostAndPort; 14 import redis.clients.jedis.JedisCluster; 15  16 public class JedisClusterFactory implements FactoryBean, InitializingBean { 17  18     private Resource addressConfig; 19     private String addressKeyPrefix; 20  21     private JedisCluster jedisCluster; 22     private Integer timeout; 23     private Integer maxRedirections; 24     private GenericObjectPoolConfig genericObjectPoolConfig; 25  26     private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$"); 27  28     public JedisCluster getObject() throws Exception { 29         return jedisCluster; 30     } 31  32     public Class getObjectType() { 33         return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class); 34     } 35  36     public boolean isSingleton() { 37         return true; 38     } 39  40     private Set parseHostAndPort() throws Exception { 41         try { 42             Properties prop = new Properties(); 43             prop.load(this.addressConfig.getInputStream()); 44  45             Set haps = new HashSet(); 46             for (Object key : prop.keySet()) { 47  48                 if (!((String) key).startsWith(addressKeyPrefix)) { 49                     continue; 50                 } 51  52                 String val = (String) prop.get(key); 53  54                 boolean isIpPort = p.matcher(val).matches(); 55  56                 if (!isIpPort) { 57                     throw new IllegalArgumentException("ip 或 port 不合法"); 58                 } 59                 String[] ipAndPort = val.split(":"); 60  61                 HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1])); 62                 haps.add(hap); 63             } 64  65             return haps; 66         } catch (IllegalArgumentException ex) { 67             throw ex; 68         } catch (Exception ex) { 69             throw new Exception("解析 jedis 配置文件失败", ex); 70         } 71     } 72  73     public void afterPropertiesSet() throws Exception { 74         Set haps = this.parseHostAndPort(); 75  76         jedisCluster = new JedisCluster(haps, timeout, maxRedirections, genericObjectPoolConfig); 77  78     } 79  80     public void setAddressConfig(Resource addressConfig) { 81         this.addressConfig = addressConfig; 82     } 83  84     public void setTimeout(int timeout) { 85         this.timeout = timeout; 86     } 87  88     public void setMaxRedirections(int maxRedirections) { 89         this.maxRedirections = maxRedirections; 90     } 91  92     public void setAddressKeyPrefix(String addressKeyPrefix) { 93         this.addressKeyPrefix = addressKeyPrefix; 94     } 95  96     public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) { 97         this.genericObjectPoolConfig = genericObjectPoolConfig; 98     } 99 100 }

RedisCache.java

  1 package com.cjl.util;  2   3 import java.util.concurrent.locks.ReadWriteLock;  4 import java.util.concurrent.locks.ReentrantReadWriteLock;  5   6 import org.apache.ibatis.cache.Cache;  7 import org.slf4j.Logger;  8 import org.slf4j.LoggerFactory;  9 import org.springframework.data.redis.connection.jedis.JedisConnection; 10 import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 11 import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 12 import org.springframework.data.redis.serializer.RedisSerializer; 13  14 import redis.clients.jedis.exceptions.JedisConnectionException; 15  16 public class RedisCache implements Cache { 17     private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); 18  19     private static JedisConnectionFactory jedisConnectionFactory; 20  21     private final String id; 22  23     private final ReadWriteLock rwl = new ReentrantReadWriteLock(); 24      25  26     public RedisCache(final String id) { 27         if (id == null) { 28             throw new IllegalArgumentException("Cache instances require an ID"); 29         } 30         logger.debug("MybatisRedisCache:id=" + id); 31         this.id = id; 32     } 33  34     /** 35      * 清空所有缓存 36      */ 37     public void clear() { 38         rwl.readLock().lock(); 39         JedisConnection connection = null; 40         try { 41             connection = jedisConnectionFactory.getConnection(); 42             connection.flushDb(); 43             connection.flushAll(); 44         } catch (JedisConnectionException e) { 45             e.printStackTrace(); 46         } finally { 47             if (connection != null) { 48                 connection.close(); 49             } 50             rwl.readLock().unlock(); 51         } 52     } 53  54     public String getId() { 55         return this.id; 56     } 57  58     /** 59      * 获取缓存总数量 60      */ 61     public int getSize() { 62         int result = 0; 63         JedisConnection connection = null; 64         try { 65             connection = jedisConnectionFactory.getConnection(); 66             result = Integer.valueOf(connection.dbSize().toString()); 67             logger.info("添加mybaits二级缓存数量:" + result); 68         } catch (JedisConnectionException e) { 69             e.printStackTrace(); 70         } finally { 71             if (connection != null) { 72                 connection.close(); 73             } 74         } 75         return result; 76     } 77  78     public void putObject(Object key, Object value) { 79         rwl.writeLock().lock(); 80  81         JedisConnection connection = null; 82         try { 83             connection = jedisConnectionFactory.getConnection(); 84             RedisSerializer serializer = new JdkSerializationRedisSerializer(); 85             connection.set(SerializeUtil.serialize(key), SerializeUtil.serialize(value)); 86             logger.info("添加mybaits二级缓存key=" + key + ",value=" + value); 87         } catch (JedisConnectionException e) { 88             e.printStackTrace(); 89         } finally { 90             if (connection != null) { 91                 connection.close(); 92             } 93             rwl.writeLock().unlock(); 94         } 95     } 96  97     public Object getObject(Object key) { 98         // 先从缓存中去取数据,先加上读锁 99         rwl.readLock().lock();100         Object result = null;101         JedisConnection connection = null;102         try {103             connection = jedisConnectionFactory.getConnection();104             RedisSerializer serializer = new JdkSerializationRedisSerializer();105             result = serializer.deserialize(connection.get(serializer.serialize(key)));106             logger.info("命中mybaits二级缓存,value=" + result);107 108         } catch (JedisConnectionException e) {109             e.printStackTrace();110         } finally {111             if (connection != null) {112                 connection.close();113             }114             rwl.readLock().unlock();115         }116         return result;117     }118 119     public Object removeObject(Object key) {120         rwl.writeLock().lock();121 122         JedisConnection connection = null;123         Object result = null;124         try {125             connection = jedisConnectionFactory.getConnection();126             RedisSerializer serializer = new JdkSerializationRedisSerializer();127             result = connection.expire(serializer.serialize(key), 0);128         } catch (JedisConnectionException e) {129             e.printStackTrace();130         } finally {131             if (connection != null) {132                 connection.close();133             }134             rwl.writeLock().unlock();135         }136         return result;137     }138 139     public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {140         RedisCache.jedisConnectionFactory = jedisConnectionFactory;141     }142 143     public ReadWriteLock getReadWriteLock() {144         // TODO Auto-generated method stub145         return rwl;146     }147 148 } 
  

RedisCacheTransfer.java

 1 package com.cjl.util; 2  3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 5  6 /** 7  * 静态注入中间类 8  */ 9 public class RedisCacheTransfer {10      @Autowired11         public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {12             RedisCache.setJedisConnectionFactory(jedisConnectionFactory);13         }14 15 }

SerializeUtil.java

 1 package com.cjl.util; 2  3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7  8 /** 9  * 
10  * @author cjl11  *12  */13 public class SerializeUtil {14     /**15      * 序列化16      */17     public static byte[] serialize(Object object) {18         ObjectOutputStream oos = null;19         ByteArrayOutputStream baos = null;20         try {21             // 序列化22             baos = new ByteArrayOutputStream();23             oos = new ObjectOutputStream(baos);24             oos.writeObject(object);25             byte[] bytes = baos.toByteArray();26             return bytes;27         } catch (Exception e) {28             e.printStackTrace();29         }30         return null;31     }32 33     /**34      *反序列化35      */36     public static Object unserialize(byte[] bytes) {37         if (bytes !=null) {38             ByteArrayInputStream bais = null;39             try {40                 // 反序列化41                 bais = new ByteArrayInputStream(bytes);42                 ObjectInputStream ois = new ObjectInputStream(bais);43                 return ois.readObject();44             } catch (Exception e) {45 46             }47         } 
48         return null;49     }50 }

所有东西准备齐全后还需要修改映射文件

03.redis+ssm整合(mybatis二级缓存)_第4张图片

要使mybaits缓存生效,还需如上图这样开启二级缓存。配置文件还需要在web.xml中加载生效

03.redis+ssm整合(mybatis二级缓存)_第5张图片

一切准备就绪后,启动服务

 03.redis+ssm整合(mybatis二级缓存)_第6张图片

启动成功后,点击员工表单可以触发查询所有员工的方法,第一次进行查询语句可以看到mybatis打印了查询语句,并在redis服务器中更新了一条缓存

03.redis+ssm整合(mybatis二级缓存)_第7张图片

03.redis+ssm整合(mybatis二级缓存)_第8张图片

我们清空控制台再次点击查询员工按钮执行查询方法,可以看到没有执行查询语句,证明第二次查询直接从缓存中取值,没有连接mysql进行查询。

03.redis+ssm整合(mybatis二级缓存)_第9张图片

以上整合基本已经完成,如有不对的地方希望大家能够指出,后面会补上负载均衡和session共享。

 


你可能感兴趣的:(redis,ssm,redis)