SSM+redis integration
The ssm framework has been built before, so no code copying is done here.
Here we mainly use redis to make mybatis' secondary cache. All selects in the mybaits mapping file will refresh the existing cache. If it does not exist, a new cache will be created. All insert and update operations will update the cache.
The benefits of redis are also obvious, which can make the system's data access performance higher. This section only shows the integration methods and effects, and will be supplemented later on by articles sharing redis clusters, load balancing and sessions.
Let’s start the integration work:
The backend starts first (the method of starting and remotely connecting to linux services requires changing the redis.conf file), and start the command "./src/redis-server ./redis.conf"
I developed it under Windows system. I recommend a visual tool "Redis Desktop Manager". It requires remote connection to redis in Linux, and the port needs to be opened to the public under Linux (the specific method is to modify the /etc/sysconfig/iptables file and add external port development commands).
After all the above operations are completed, the remote connection will be successful, as shown in the figure:
There is no cache record yet. Let’s enter the code stage. First, add the required redis jar package to pom.xml.
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version> </dependency> <!-- Add druid connection pool package--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.24</version> </dependency>
After the pom.xml is written, two new configuration files need to be added: redis.properties
redis.host=192.168.0.109redis.port=6379redis.pass=123456redis.maxIdle=200redis.maxActive=1024redis.maxWait=10000redis.testOnBorrow=true
The fields are also easy to understand, and then add the configuration file: spring-redis.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- Basic parameter configuration of connection pool, similar to database connection pool--> <context:property-placeholder location="classpath*:redis.properties" /> <bean id="poolConfig"> <property name="maxTotal" value="${redis.maxActive}"/> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}"/> </bean> <!-- Connection pool configuration, similar to database connection pool--> <bean id="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> <!-- Call connection pool factory configuration--> <!-- <bean id="redisTemplate"> <property name="jedisConnectionFactory" ref="jedisConnectionFactory"></property> If Serializer is not configured, then use String intelligently when storing. If you use the User type to store, it will prompt an error User can't cast to String! ! ! <property name="keySerializer"> <bean /> </property> <property name="valueSerializer"> <bean /> </property> </bean> --> <bean id="redisCacheTransfer"> <property name="jedisConnectionFactory" ref="jedisConnectionFactory" /> </bean></beans>After the configuration file is written, start writing the java code:
JedisClusterFactory.java
package com.cjl.util;import java.util.HashSet;import java.util.Properties;import java.util.Set;import java.util.regex.Pattern;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.springframework.beans.factory.FactoryBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.core.io.Resource;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;public class JedisClusterFactory implements FactoryBean<JedisCluster>, InitializingBean { private Resource addressConfig; private String addressKeyPrefix; private JedisCluster jedisCluster; private Integer timeout; private Integer maxRedirections; private GenericObjectPoolConfig genericObjectPoolConfig; private Pattern p = Pattern.compile("^.+[:]//d{1,5}//s*$"); public JedisCluster getObject() throws Exception { return jedisCluster; } public Class<? extends JedisCluster> getObjectType() { return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class); } public boolean isSingleton() { return true; } private Set<HostAndPort> parseHostAndPort() throws Exception { try { Properties prop = new Properties(); prop.load(this.addressConfig.getInputStream()); Set<HostAndPort> hasps = new HashSet<HostAndPort>(); for (Object key : prop.keySet()) { if (!((String) key).startsWith(addressKeyPrefix)) { continue; } String val = (String) prop.get(key); boolean isIpPort = p.matcher(val).matches(); if (!isIpPort) { throw new IllegalArgumentException("ip or port is illegal"); } String[] ipAndPort = val.split(":"); HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1])); haps.add(hap); } return hasps; } catch (IllegalArgumentException ex) { throw ex; } catch (Exception ex) { throw new Exception("Parse jedis configuration file failed", ex); } } public void afterPropertiesSet() throws Exception { Set<HostAndPort> hasps = this.parseHostAndPort(); jedisCluster = new JedisCluster(haps, timeout, maxRedirections, genericObjectPoolConfig); } public void setAddressConfig(Resource addressConfig) { this.addressConfig = addressConfig; } public void setTimeout(int timeout) { this.timeout = timeout; } public void setMaxRedirections(int maxRedirections) { this.maxRedirections = maxRedirections; } public void setAddressKeyPrefix(String addressKeyPrefix) { this.addressKeyPrefix = addressKeyPrefix; } public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) { this.genericObjectPoolConfig = genericObjectPoolConfig; }}RedisCache.java
package com.cjl.util;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;import org.apache.ibatis.cache.Cache;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.data.redis.connection.jedis.JedisConnection;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializer;import redis.clients.jedis.exceptions.JedisConnectionException;public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private static JedisConnectionFactory jedisConnectionFactory; private final String id; private final ReadWriteLock rwl = new ReentrantReadWriteLock(); public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } logger.debug("MybatisRedisCache:id=" + id); this.id = id; } /** * Clear all caches*/ public void clear() { rwl.readLock().lock(); JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); connection.flushDb(); connection.flushAll(); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } rwl.readLock().unlock(); } } public String getId() { return this.id; } /** * Get the total number of caches*/ public int getSize() { int result = 0; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); result = Integer.valueOf(connection.dbSize().toString()); logger.info("Add mybaits secondary cache number: " + result); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } return result; } public void putObject(Object key, Object value) { rwl.writeLock().lock(); JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); connection.set(SerializeUtil.serialize(key), SerializeUtil.serialize(value)); logger.info("Add mybaits secondary cache key=" + key + ",value=" + value); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } rwl.writeLock().unlock(); } } public Object getObject(Object key) { // Get data from the cache first, add the read lock rwl.readLock().lock(); Object result = null; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = serializer.deserialize(connection.get(serializer.serialize(key))); logger.info("hit mybaits level 2 cache, value=" + result); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } rwl.readLock().unlock(); } return result; } public Object removeObject(Object key) { rwl.writeLock().lock(); JedisConnection connection = null; Object result = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = connection.expire(serializer.serialize(key), 0); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } rwl.writeLock().unlock(); } return result; } public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.jedisConnectionFactory = jedisConnectionFactory; } public ReadWriteLock getReadWriteLock() { // TODO Auto-generated method stub return rwl; }}RedisCacheTransfer.java
package com.cjl.util;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;/** * Static injection of intermediate classes*/public class RedisCacheTransfer { @Autowired public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.setJedisConnectionFactory(jedisConnectionFactory); }}SerializeUtil.java
package com.cjl.util;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;/** * * @author cjl * */public class SerializeUtil { /** * Serialization*/ public static byte[] serialize(Object object) { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { // Serialization baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); byte[] bytes = baos.toByteArray(); return bytes; } catch (Exception e) { e.printStackTrace(); } return null; } /** *Deserialization*/ public static Object unserialize(byte[] bytes) { if (bytes !=null) { ByteArrayInputStream bais = null; try { // Deserialize bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception e) { } } return null; }}After everything is ready, you need to modify the mapping file
To make the mybaits cache effective, you also need to enable the secondary cache as shown in the above figure. The configuration file also needs to be loaded in web.xml to take effect
When everything is ready, start the service
After the startup is successful, clicking the employee form can trigger the method of querying all employees. When the query statement is performed for the first time, you can see that mybatis has printed the query statement and updated a cache in the redis server.
We clear the console and click the Query Employee button to execute the query method. We can see that no query statement is executed, proving that the second query directly takes the value from the cache, and there is no connection to mysql for query.
Summarize
The above is the integration method of redis and ssm (mybatis level 2 cache) introduced to you by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!