Redis中在程序中的應用
阿新 • • 發佈:2017-08-05
dtree tcollect base 條件 mil style mon ins print
1、導入redis的配置文件,因為要交給web容器管理,所以直接命名為ApplicationContext-redis.xml,具體配置如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 構建連接池配置信息 --><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大連接數 --> <property name="maxTotal" value="${redis.maxTotal}" /> </bean> <bean id="jedisShardInfo1" class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis.node1.ip}" /> <constructor-arg index="1" value="${redis.node1.port}" type="int" /> </bean> <bean id="jedisShardInfo2" class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis.node2.ip}" /> <constructor-arg index="1" value="${redis.node2.port}" type="int" /> <!-- 端口必須為int類型,如果不寫的話,默認是字符串類型,這是時候不起作用,所以端口就是默認端口,會造成分片失敗 --></bean> <bean id="jedisShardInfo3" class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis.node3.ip}" /> <constructor-arg index="1" value="${redis.node3.port}" type="int" /> </bean> <!-- 定義集群連接池 --> <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" destroy-method="close"> <constructor-arg index="0" ref="jedisPoolConfig" /> <constructor-arg index="1"> <list> <ref bean="jedisShardInfo1" /> <ref bean="jedisShardInfo2" /> <ref bean="jedisShardInfo3"/> </list> </constructor-arg> </bean> </beans>
需要說明的是,這裏是通過jedis進行操作的(jedis即java版的redis)
2、寫偽service工具類
偽service--封裝一個新的技術,融合進業務,而不是真正的業務層需要,但是本質還是service,目的是為了在controller中註入方便。經過偽service封裝可以屏蔽掉底層的api
package com.jt.common.service; 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 { //有的工程需要,有的工程不需要。設置required=false,有就註入,沒有就不註入。 @Autowired(required = false) private ShardedJedisPool shardedJedisPool; private <T> T execute(Function<ShardedJedis, T> function) { ShardedJedis shardedJedis = null; try { // 從連接池中獲取到jedis分片對象 shardedJedis = shardedJedisPool.getResource(); return function.execute(shardedJedis); } catch (Exception e) { e.printStackTrace(); } finally { if (null != shardedJedis) { // 關閉,檢測連接是否有效,有效則放回到連接池中,無效則重置狀態 shardedJedis.close(); } } return null; } /** * 保存數據到redis中 * * @param key * @param value * @return */ public String set(final String key, final String value) { return this.execute(new Function<ShardedJedis, String>() { @Override public String execute(ShardedJedis shardedJedis) { return shardedJedis.set(key, value); } }); } /** * 保存數據到redis中,生存時間單位是:秒 * * @param key * @param value * @param seconds * @return */ public String set(final String key, final String value, final Integer seconds) { return this.execute(new Function<ShardedJedis, String>() { @Override public String execute(ShardedJedis shardedJedis) { String result = shardedJedis.set(key, value); shardedJedis.expire(key, seconds);//設置生存時間 return result; } }); } /** * 從redis中獲取數據 * * @param key * @return */ public String get(final String key) { return this.execute(new Function<ShardedJedis, String>() { @Override public String execute(ShardedJedis shardedJedis) { return shardedJedis.get(key); } }); } /** * 設置key生存時間,單位:秒 * * @param key * @param seconds * @return */ public Long expire(final String key, final Integer seconds) { return this.execute(new Function<ShardedJedis, Long>() { @Override public Long execute(ShardedJedis shardedJedis) { return shardedJedis.expire(key, seconds); } }); } /** * 從redis中刪除數據 * * @param key * @return */ public Long del(final String key) { return this.execute(new Function<ShardedJedis, Long>() { @Override public Long execute(ShardedJedis shardedJedis) { return shardedJedis.del(key); } }); } }
3、在對應的執行業務的service中添加緩存方法
我這裏因為是要做的查詢的一個三級樹目錄,通過點擊前臺頁面的父選項,傳遞父ID給後臺,查詢對應的子類,並將子類集合返回
原代碼如下:
package com.jt.manage.service;
import java.io.IOException;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.common.service.BaseService;
import com.jt.common.service.RedisService;
import com.jt.manage.mapper.ItemCatMapper;
import com.jt.manage.pojo.ItemCat;
@Service
public class ItemCatService extends BaseService<ItemCat> {
@Autowired
private ItemCatMapper itemCatMapper;
public List<ItemCat> findItemCarList(Long parentId) {
itemCat.setParentId(parentId);
<!--這裏采用的是JPA的方式,自動構建sql語句,查詢的時候如果傳入的是對象,那麽會根據對象的屬性當做where條件進行對應的匹配-->
return itemCatMapper.select(itemCat);
}
修改後的代碼如下:
package com.jt.manage.service; import java.io.IOException; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.jt.common.service.BaseService; import com.jt.common.service.RedisService; import com.jt.manage.mapper.ItemCatMapper; import com.jt.manage.pojo.ItemCat; @Service public class ItemCatService extends BaseService<ItemCat> { @Autowired private ItemCatMapper itemCatMapper; @Autowired private RedisService redisService; private static final ObjectMapper MAPPER = new ObjectMapper(); public List<ItemCat> findItemCarList(Long parentId) { /* * 如果傳入的是對象,查詢時就會根據對象的屬性值添加where條件 寫null表示不需要where條件 */ ItemCat itemCat = new ItemCat(); /* * 1、在執行業務前判斷緩存總是否所有數據,如果有數據,就獲取數據,直接返回結果 * 2、如果沒有數據,繼續執行業務,訪問數據庫,獲取返回的值 * 3、再返回業務之前,把獲取的數據在緩存中存放一份,然後再返回 * 4、放緩存:kv(String) 把java對象變成json字符串 * 5、拿緩存:把字符串轉換成java對象List<ItemCat> */ itemCat.setParentId(parentId); // 判斷緩存中有無數據 // 定義鍵 String ITEM_CAT_KEY = "ITEM_CAT_" + parentId; // 根據鍵獲取數據 String jsonData = redisService.get(ITEM_CAT_KEY); if (StringUtils.isNotEmpty(jsonData)) { // 緩存中有數據 try { // 直接從緩存中獲取數據,把json串轉換為java對象 JsonNode jsonNode = MAPPER.readTree(jsonData); Object obj = null; if (jsonNode.isArray() && jsonNode.size() > 0) { obj = MAPPER.readValue(jsonNode.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class, ItemCat.class)); return (List<ItemCat>) obj; } } catch (Exception e) { e.printStackTrace(); } } else {//如果緩存中沒有數據,執行業務 try { //從數據庫中獲取數據 List<ItemCat> itemCatList = itemCatMapper.select(itemCat); //將數據保存一份在緩存中 //將數據轉換成json對象 String json = MAPPER.writeValueAsString(itemCatList); //將對象保存進緩存 redisService.set(ITEM_CAT_KEY, json); //返回需要的對象 return itemCatList; } catch (JsonProcessingException e) { e.printStackTrace(); } } return null; } }
Redis中在程序中的應用