1. 程式人生 > >Redis中在程序中的應用

Redis中在程序中的應用

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中在程序中的應用