项目需求:电商项目中的广告位数据和商品类目数据量比较大,内容变化小,每次查询消耗时间长,所以可以添加缓存,提高访问首页的速度。
实现:
使用Redis实现缓存。
Redis是一款高性能的NOSQL数据库,功能强大。
一:使用sprig-data-redis和jedis进行整合
1:maven依赖
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.4.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2:reids.properties
redis.host = 114.225.83.3 redis.port = 6379 redis.passwd = 123456 #最大能够保持idle状态的对象数 redis.maxIdle=300 #最大分配的对象数 注意:低版本的jedis该属性名称是 maxActive redis.maxTotal=600 #当池内没有返回对象时,最大等待时间 注意:低版本的jedis该属性名称是 maxWait redis.maxWaitMillis=1000 #当调用borrow Object方法时,是否进行有效性检查 redis.testOnBorrow=true #超时时间 redis.timeout=100000
3:applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- redis配置文件 --> <context:property-placeholder location="classpath:/redis.properties" ignore-unresolvable="true" /> <!-- 配置连接池参数 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxTotal" value="${redis.maxTotal}" /> <property name="maxWaitMillis" value="${redis.maxWaitMillis}" /> <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}" /> <!-- 如果redis没有开启验证,password不需要配置 --> <property name="password" value="${redis.passwd}"></property> <property name="timeout" value="${redis.timeout}"></property> <property name="poolConfig" ref="poolConfig" /> </bean> <!-- 配置模版 --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <!-- key的序列化策略 --> <property name="keySerializer"> <!-- 字符串编码,数据以string存储 --> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean> </property> <!-- value的序列化策略 --> <property name="valueSerializer"> <!-- 使用JDK的序列化手段(serializable接口,ObjectInputStrean,ObjectOutputStream),数据以字节流存储 --> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean> </property> </bean> </beans>
3:定义模版-BaseRedis
package com.debo.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; public abstract class BaseRedis<K, V> { @Autowired protected RedisTemplate<K, V> redisTemplate; public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) { this.redisTemplate = redisTemplate; } protected RedisSerializer<String> getRedisSerializer() { return redisTemplate.getStringSerializer(); } }
4:定义一个序列化对象-pojo
package com.mote.entity; import java.io.Serializable; public class Pojo implements Serializable{ private static final long serialVersionUID = 6703029746128139046L; private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
5:redis操作接口类 -RedisService
package com.debo.redis; import java.util.List; import java.util.Set; import com.mote.entity.Pojo; public interface RedisService { //添加 boolean add(Pojo pojo); //批量添加 boolean add(List<Pojo> list); //删除 void delete(String key); //批量删除 void delete(List<String> keys); //更新 boolean update(Pojo pojo); //查询 Pojo get(String keyId); //获取所有key Set<String> getKeys(); //清空 boolean flushDB(); }
6:redis操作类-RedisServiceImpl
package com.debo.redis; import java.io.Serializable; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; 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.ValueOperations; import org.springframework.stereotype.Service; import com.mote.entity.Pojo; @Service("redisService") public class RedisServiceImpl extends BaseRedis<String, Serializable> implements RedisService { public boolean add(final Pojo pojo) { ValueOperations<String, Serializable> valueOper = redisTemplate.opsForValue(); //设值,并且过期时间设为3分钟 valueOper.set(pojo.getId(), pojo, 3, TimeUnit.MINUTES); return true; } public boolean add(final List<Pojo> list) { ValueOperations<String, Serializable> valueOper = redisTemplate.opsForValue(); for (Pojo trli : list) { valueOper.set(trli.getId(), trli); } return true; } public void delete(String key) { redisTemplate.delete(key); } public void delete(List<String> keys) { redisTemplate.delete(keys); } public boolean update(Pojo pojo) { String id = pojo.getId(); if (get(id) == null) { throw new NullPointerException("数据行不存在, key = " + id); } ValueOperations<String, Serializable> valueOper = redisTemplate.opsForValue(); valueOper.set(pojo.getId(), pojo); return true; } public Pojo get(String keyId) { ValueOperations<String, Serializable> operations = redisTemplate.opsForValue(); Pojo pojo = null; try{ pojo = (Pojo)operations.get(keyId); }catch(Exception e) { e.printStackTrace(); } return pojo; } public Set<String> getKeys() { return redisTemplate.keys("*"); } public boolean flushDB() { boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { connection.flushDb(); return true; } }); return result; } }
二:不使用spring-data-redis
1:maven依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2:redis.properties
redis.host = 114.225.83.3 redis.port = 6379 redis.passwd = 123456 #最大能够保持idle状态的对象数 redis.maxIdle=300 #最大分配的对象数 注意:低版本的jedis该属性名称是 maxActive redis.maxTotal=600 #当池内没有返回对象时,最大等待时间 注意:低版本的jedis该属性名称是 maxWait redis.maxWaitMillis=1000 #当调用borrow Object方法时,是否进行有效性检查 redis.testOnBorrow=true #超时时间 redis.timeout=100000
3:applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 加载redis配置文件 --> <context:property-placeholder location="classpath:/redis.properties" ignore-unresolvable="true" /> <!-- 配置池参数 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.maxTotal}" /> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="MaxWaitMillis" value="${redis.MaxWaitMillis}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}"/> </bean> <!-- 连接池 --> <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" scope="singleton"> <constructor-arg index="0" ref="jedisPoolConfig" /> <constructor-arg index="1"> <list> <bean class="redis.clients.jedis.JedisShardInfo"> <constructor-arg name="host" value="${redis.host}" /> <constructor-arg name="port" value="${redis.port}" /> <constructor-arg name="timeout" value="${redis.timeout}" /> <!-- 配置redis认证密码 --> <property name="password" value="${redis.passwd}"></property> </bean> <!-- TODO : 这里可以配置多个redis节点 --> </list> </constructor-arg> </bean> </beans>
4:redis操作实现类
package com.debo.redis; public interface Function <T,E>{ public T callback(E e); }
package com.debo.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool; @Service public class RedisService { @Autowired private ShardedJedisPool shardedJedisPool; private <T> T execute(Function<T, ShardedJedis> fun) { ShardedJedis shardedJedis = null; try { // 从连接池中获取到jedis分片对象 shardedJedis = shardedJedisPool.getResource(); return fun.callback(shardedJedis); } catch (Exception e) { e.printStackTrace(); } finally { if (null != shardedJedis) { // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态 shardedJedis.close(); } } return null; } /** * 执行set操作 * * @param key * @param value * @return */ public String set(final String key, final String value) { return this.execute(new Function<String, ShardedJedis>() { @Override public String callback(ShardedJedis e) { return e.set(key, value); } }); } /** * 执行GET操作 * * @param key * @return */ public String get(final String key) { return this.execute(new Function<String, ShardedJedis>() { @Override public String callback(ShardedJedis e) { return e.get(key); } }); } /** * 执行DEL操作 * * @param key * @return */ public Long del(final String key) { return this.execute(new Function<Long, ShardedJedis>() { @Override public Long callback(ShardedJedis e) { return e.del(key); } }); } /** * 设置生存时间,单位为秒 * * @param key * @param seconds * @return */ public Long expire(final String key, final Integer seconds) { return this.execute(new Function<Long, ShardedJedis>() { @Override public Long callback(ShardedJedis e) { return e.expire(key, seconds); } }); } /** * 执行set操作并且设置生存时间,单位为秒 * * @param key * @param value * @return */ public String set(final String key, final String value, final Integer seconds) { return this.execute(new Function<String, ShardedJedis>() { @Override public String callback(ShardedJedis e) { String str = e.set(key, value); e.expire(key, seconds); return str; } }); } }