1.引入redis的jar包
<!--redis客户端:jedis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2.redis.properties配置文件
redis.hostname=127.0.0.1 redis.port=6379 redis.database=0 redis.pool.maxActive=100 redis.pool.maxIdle=20 redis.pool.maxWait=3000 redis.pool.testOnBorrow=true
3.在spring-dao.xml下引入redis.properties配置文件中相关的key-value
<!-- 1.配置数据库相关参数properties的属性:${url} --> <!--<context:property-placeholder location="classpath:jdbc.properties"/>--> <bean class="com.shop.util.EncryptPropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:redis.properties</value> </list> </property> <property name="fileEncoding" value="utf-8"/> </bean>
4.编写JedisPoolWriper类
/** * 强指定redis的JedisPool接口构造函数,这样才能在centos成功创建jedispool * Created by Skye on 2018/5/13. */ public class JedisPoolWriper { //Redis连接池对象 private JedisPool jedisPool; public JedisPoolWriper(final JedisPoolConfig jedisPoolConfig, final String host, final int port){ jedisPool = new JedisPool( jedisPoolConfig, host, port ); } public JedisPool getJedisPool() { return jedisPool; } public void setJedisPool(JedisPool jedisPool) { this.jedisPool = jedisPool; } }
5.编写JedisUtil工具类
6.sprins-redis.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!--redis连接池设置--> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!--控制一个连接池可分配多少个jedis实例--> <property name="maxTotal" value="${redis.pool.maxActive}" /> <!--连接池中最多可空闲maxIdle个连接,--> <property name="maxIdle" value="${redis.pool.maxIdle}" /> <!--最大等待时间--> <property name="maxWaitMillis" value="${redis.pool.maxWait}" /> <!--在获取连接时候检查有效性--> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /> </bean> <!--创建redis连接池,并做相关配置--> <bean id="jedisWritePool" class="com.shop.cache.JedisPoolWriper" depends-on="jedisPoolConfig"> <constructor-arg index="0" ref="jedisPoolConfig" /> <constructor-arg index="1" value="${redis.hostname}" /> <constructor-arg index="2" value="${redis.port}" type="int" /> </bean> <!--创建Redis工具类,封装好Redis的连接以进行相关的操作--> <bean id="jedisUtil" class="com.shop.cache.JedisUtil" scope="singleton"> <property name="jedisPool"> <ref bean="jedisWritePool" /> </property> </bean> <!--Redis的key操作--> <bean id="jedisKeys" class="com.shop.cache.JedisUtil$KEYS" scope="singleton"> <constructor-arg ref="jedisUtil"></constructor-arg> </bean> <!--Redis的String操作--> <bean id="jedisStrings" class="com.shop.cache.JedisUtil$STRINGS" scope="singleton"> <constructor-arg ref="jedisUtil"></constructor-arg> </bean> <bean id="jedisLists" class="com.shop.cache.JedisUtil$LISTS" scope="singleton"> <constructor-arg ref="jedisUtil"></constructor-arg> </bean> <bean id="jedisSets" class="com.shop.cache.JedisUtil$SETS" scope="singleton"> <constructor-arg ref="jedisUtil"></constructor-arg> </bean> <bean id="jedisHash" class="com.shop.cache.JedisUtil$HASH" scope="singleton"> <constructor-arg ref="jedisUtil"></constructor-arg> </bean> </beans>
7.在项目中引入redis缓存技术
在需要进行redis缓存的service层中先@Autowired引入jedis的Keys和Strings
AreaServiceImpl中将之前getAreaList()方法只是简单的从AreaDao中获取AreaList改为从缓存中获取,如果不存在的话,在重新从数据库获取,并加入到redis的key-value中去
为了使得数据库内容修改后redis中的值也进行修改,所以将保存区域列表的关键字常量值放在AreaService的接口中,并且重新写一个Cache的Service将之前保存的该关键字相关的key-value都删掉
AreaService接口
public interface AreaService { //保存区域列表信息的key public static final String AREALISTKEY = "arealist"; /** * 获取区域列表 * @return */ List<Area> getAreaList(); }
AreaServiceImpl
@Service public class AreaServiceImpl implements AreaService { @Autowired private AreaDao areaDao; @Autowired private JedisUtil.Keys jedisKeys; @Autowired private JedisUtil.Strings jedisStrings; @Override @Transactional public List<Area> getAreaList() { String key = AREALISTKEY; List<Area> areaList = null; ObjectMapper objectMapper = new ObjectMapper(); if(!jedisKeys.exists( key )){ areaList = areaDao.queryArea(); String jsonString = null; try { jsonString = objectMapper.writeValueAsString( areaList ); } catch (JsonProcessingException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } jedisStrings.set( key, jsonString ); } else{ String jsonString = jedisStrings.get( key ); JavaType javaType = objectMapper.getTypeFactory().constructParametricType( ArrayList.class, Area.class ); try { areaList = objectMapper.readValue(jsonString, javaType); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } } return areaList; } }
ShopCategoryService接口
public interface ShopCategoryService { public static final String SCLISTKEY = "shopcategorylist"; /** * 根据查询条件获取店铺类别列表 * @param shopCategoryCondition * @return */ List<ShopCategory>getShopCategoryList(ShopCategory shopCategoryCondition); }
ShopCategoryImpl
@Service public class ShopCategoryServiceImpl implements ShopCategoryService { @Autowired private ShopCategoryDao shopCategoryDao; @Autowired private JedisUtil.Keys jedisKeys; @Autowired private JedisUtil.Strings jedisStrings; @Override @Transactional public List<ShopCategory> getShopCategoryList(ShopCategory shopCategoryCondition) { String key = SCLISTKEY; List<ShopCategory> shopCategoryList = null; ObjectMapper objectMapper = new ObjectMapper( ); if(shopCategoryCondition == null){ //若查询条件为空,则拼接出所有首页大类,即parentId为空的店铺类别 key = key + "_allfirstlevel"; } else if(shopCategoryCondition != null && shopCategoryCondition.getParent() != null && shopCategoryCondition.getParent().getShopCategoryId() != null){ //若parentId不为空,则列出parentId不为空的所有子类 key = key + "_parent" + shopCategoryCondition.getParent().getShopCategoryId(); } else if(shopCategoryCondition.getShopCategoryId() != null){ //列出所有子类,不管属于哪个类别 key = key + "_allsecondlevel"; } if(!jedisKeys.exists( key )){ shopCategoryList = shopCategoryDao.queryShopCategory( shopCategoryCondition ); String jsonString; try { jsonString = objectMapper.writeValueAsString( shopCategoryList ); } catch (JsonProcessingException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } jedisStrings.set( key, jsonString); } else{ String jsonString = jedisStrings.get( key ); JavaType javaType = objectMapper.getTypeFactory().constructParametricType( ArrayList.class, ShopCategory.class ); try { shopCategoryList = objectMapper.readValue(jsonString, javaType); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } } return shopCategoryList; } }
HeadLineService接口
public interface HeadLineService { public static final String HEADLINELISTKEY = "headlinelist"; /** * 根据查询条件返回头条列表 * @param headLineCondition * @return */ List<HeadLine> getHeadLineList(HeadLine headLineCondition); }
HeadLineImpl
@Service public class HeadLineServiceImpl implements HeadLineService { @Autowired HeadLineDao headLineDao; @Autowired private JedisUtil.Keys jedisKeys; @Autowired private JedisUtil.Strings jedisStrings; @Override @Transactional public List<HeadLine> getHeadLineList(HeadLine headLineCondition) { String key = HEADLINELISTKEY; List<HeadLine> headLineList = null; ObjectMapper objectMapper = new ObjectMapper( ); if(headLineCondition != null && headLineCondition.getStatus() != null){ key = key + "_" + headLineCondition.getStatus(); } if(!jedisKeys.exists( key )){ headLineList = headLineDao.queryHeadLine( headLineCondition ); String jsonString; try { jsonString = objectMapper.writeValueAsString( headLineList ); } catch (JsonProcessingException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } jedisStrings.set( key, jsonString); } else{ String jsonString = jedisStrings.get( key ); JavaType javaType = objectMapper.getTypeFactory().constructParametricType( ArrayList.class, HeadLine.class ); try { headLineList = objectMapper.readValue(jsonString, javaType); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException( e.getMessage() ); } } return headLineList; } }
在数据库修改之后,要将Redis中存储的缓存删除掉
CacheService接口
public interface CacheService { /** * 依据key前缀,删除匹配该模式下的所有key-value * 如传入shopcategory,则shopcategory_allfirstlevel等以shopcategory开头的key_value都会被清空 * @param keyPrefix */ void removeFromCache(String keyPrefix); }
CacheServiceImpl
@Service public class CacheServiceImpl implements CacheService { @Autowired JedisUtil.Keys jedisKeys; @Override public void removeFromCache(String keyPrefix) { Set<String> keySet = jedisKeys.keys( keyPrefix + "*" ); for(String key : keySet){ jedisKeys.del( key ); } } }