1. 程式人生 > >SSM(Spring + Spring MVC +Mybatis)的Redis快取,JedisPool配置

SSM(Spring + Spring MVC +Mybatis)的Redis快取,JedisPool配置

在SSM(Spring + Spring MVC +Mybatis)專案中使用到Redis快取,在網上查找了一些方法和文件後總結出自己可用的一些配置如下:

1、pom.xml檔案中引入需要的依賴

<!-- redis客戶端:jedis -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.7.3</version>
    </dependency>

    <!-- 物件序列化依賴 -->
    <dependency>
      <groupId>com.dyuproject.protostuff</groupId>
      <artifactId>protostuff-core</artifactId>
      <version>1.0.8</version>
    </dependency>
    <dependency>
      <groupId>com.dyuproject.protostuff</groupId>
      <artifactId>protostuff-runtime </artifactId>
      <version>1.0.8</version>
    </dependency>
2、在spring配置檔案中配置新增如下配置,配置檔案中配置
<!-- redis資料來源 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- redis連線池 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy"  depends-on="poolConfig">
        <constructor-arg name="poolConfig" ref="poolConfig" /> <!-- 載入jedisPool配置資訊 -->
        <constructor-arg name="host" value="${redis.host}" /><!-- redis主機地址 -->
        <constructor-arg name="port" value="${redis.port}"/> <!-- redis連線埠 -->
        <!-- <constructor-arg name="password" value="${redis.pass}"/> 密碼 -->
        <!--<constructor-arg name="database" value="${redis.database}"/> 資料庫 -->
        <!--<constructor-arg name="timeout" value="${redis.timeout}"/> 連線超時 -->
    </bean>
#redis快取配置
redis.host=你的地址
redis.port=你的埠
redis.pass=你的密碼
redis.database=2
redis.timeout=2000

#redis連線池配置
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true


3、在DAO層中新建redis包,新建RedisApplicationsDao.java(需要快取的物件)
package com.mvc.dao.redis;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import com.mvc.common.Config;
import com.mvc.entity.Applications;
import com.mvc.enums.SSOEnum;
import com.mvc.exception.RedisException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yuyu on 2017/4/17.
 * 使用者快取使用者可作業系統的redis
 */
public class RedisApplicationsDao {

    //日誌記錄物件
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //redis連線池
    @Autowired
    public JedisPool jedisPool;
    //將要序列化的類轉換成圖
    private RuntimeSchema<Applications> schema = RuntimeSchema.createFrom(Applications.class);

    //根據使用者id獲取當前使用者可登入的系統
    public List<Applications> getListApplications(String userId) throws Exception {
        //返回資料初始化
        List<Applications> list=new ArrayList<Applications>();
        try {
            //獲取redis操作物件
            Jedis jedis = jedisPool.getResource();
            try {
                //選擇redis的db2
                jedis.select(2);
                //redis的key
                String key = "ListApplications:" + userId+":";
                String keySize = "ListApplicationsSize:" + userId;
                //取得byte[]反序列取得相應的物件
                //獲取list長度遍歷獲取list
                String listSize=jedis.get(keySize);

                if(null!=listSize){
                    int size=Integer.parseInt(listSize);
                    if(size>0){
                        //獲取對應的例項物件
                        for(int x=0;x<size;x++){
                            byte[] bytes=jedis.get((key+x).getBytes());
                            //獲取快取,操作
                            if(null!=bytes){
                                //空物件
                                Applications applications=schema.newMessage();
                                //空物件被反序列
                                ProtobufIOUtil.mergeFrom(bytes,applications,schema);
                                //新增返回list
                                list.add(applications);
                            }else{
                                //丟擲一個自定義的異常
                                throw new RedisException(SSOEnum.NOT_REDIS_EMPTY.getInfo()+key+x);
                            }
                        }
                    }else{
                        //使用者配置為空
                        throw new RedisException(userId+SSOEnum.NOT_APP_CANT_USE.getInfo());
                    }
                }else{
                    throw new RedisException(SSOEnum.NOT_REDIS_EMPTY.getInfo()+keySize);
                }
            } finally {
                //關閉連線
                jedis.close();
            }
        } catch (Exception e) {
            //記錄錯誤日誌
            logger.error(e.getMessage(), e);
            //redis。連線失敗,不用redis
            throw new RedisException(e.getMessage());
        }
        return list;
    }

    //將資料庫生成的查詢快取到redis
    public void putListApplications(List<Applications> list,String userId) throws Exception{
        //獲取list的長度儲存起來
        try{
            //獲取redis操作物件
            Jedis jedis=jedisPool.getResource();
            try {
                jedis.select(2);
                //redis的key
                String key = "ListApplications:" + userId + ":";
                String keySize = "ListApplicationsSize:" + userId;
                //儲存list的長度
                String back=jedis.setex(keySize,Config.REDIS_TIMEOUT,Integer.toString(list.size()));

                if("OK".equals(back)){
                    //儲存例項物件
                    int x=0;
                    for(Applications data:list){
                        //將物件序列化
                        byte[] bytes=ProtobufIOUtil.toByteArray(data,schema,
                                LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));

                        //儲存相應的資料
                        back=jedis.setex((key+x).getBytes(),Config.REDIS_TIMEOUT,bytes);

                        //判斷是否成功
                        if(!"OK".equals(back)){
                            throw new RedisException(SSOEnum.NOT_REDIS_CACHE_ERROR.getInfo()+key+x);
                        }
                        x++;
                    }
                }else{
                    throw new RedisException(SSOEnum.NOT_REDIS_CACHE_ERROR.getInfo()+keySize);
                }
            }finally {
                //關閉redis連線
                jedis.close();
            }
        }catch (Exception e){
            //記錄錯誤資訊到日誌
            logger.error(e.getMessage(),e);
            //redis。連線失敗,不用redis
            throw new RedisException(e.getMessage());
        }
    }

    //根據查詢到的單條例項進行快取
    public Applications getApplications(String id,String code)throws Exception{

        try{
            //獲取redis操作物件
            Jedis jedis = jedisPool.getResource();
            try {
                jedis.select(2);
                //設定去得的key
                String key="Applications:"+id+":"+code;

                //取得快取資訊
                byte[] bytes=jedis.get(key.getBytes());
                //判斷取得的資料
                if(null!=bytes){
                    //新建空物件
                    Applications applications=schema.newMessage();
                    //取得快取物件
                    ProtobufIOUtil.mergeFrom(bytes,applications,schema);
                    //返回物件
                    return applications;
                }else{
                    throw new RedisException(SSOEnum.NOT_REDIS_EMPTY.getInfo()+key);
                }
            }finally {
                jedis.close();
            }
        }catch (Exception e){
            //記錄錯誤資訊到日誌
            logger.error(e.getMessage(),e);
            //redis。連線失敗,不用redis
            throw new RedisException(e.getMessage());
        }
    }

    //獲取單條資料的快取
    public void putApplications(Applications data,String id,String code)throws Exception{
        try{
            //獲取redis連線物件
            Jedis jedis=jedisPool.getResource();
            try{
                //選擇資料庫
                jedis.select(2);
                //建立key
                String key="Applications:"+id+":"+code;

                //將物件序列化
                byte[] bytes=ProtobufIOUtil.toByteArray(data,schema,
                        LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
                //將資料快取
                String back=jedis.setex(key.getBytes(),Config.REDIS_TIMEOUT,bytes);
                //判斷是否快取成功
                if(!"OK".equals(back)){
                    throw new RedisException(SSOEnum.NOT_REDIS_CACHE_ERROR.getInfo()+key);
                }
            }finally {
                //關閉redis連線
                jedis.close();
            }
        }catch (Exception e){
            //將錯誤記錄日誌
            logger.error(e.getMessage(),e);
            //redis。連線失敗,不用redis
            throw new RedisException(e.getMessage());
        }
    }
}
4、在對應spring配置檔案中加入該檔案的依賴
<bean id="redisApplicationsDao" class="com.mvc.dao.redis.RedisApplicationsDao"/>
5、建立單元測試類檢測當前的編碼是否可行
package com.mvc.dao.redis;

import com.mvc.dao.ApplicationsDAO;
import com.mvc.entity.Applications;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

import java.util.List;

import static org.junit.Assert.*;

/**
 * Created by yuyu on 2017/4/18.
 */
@RunWith(SpringJUnit4ClassRunner.class)
//告訴junit spring的配置檔案
@ContextConfiguration({"classpath:spring/spring-dao.xml"})

public class RedisApplicationsDaoTest {

    @Autowired
    public RedisApplicationsDao redisApplicationsDao;

    @Autowired
    public ApplicationsDAO applicationsDAO;

    @Test
    public void getListApplications() throws Exception {
        List<Applications> list= redisApplicationsDao.getListApplications("3");
        for(Applications data:list){

            System.out.println(data);

        }

    }

    @Test
    public void putListApplications() throws Exception {
        String id="3";
        List<Applications> list=applicationsDAO.selectByUserid(id);
        redisApplicationsDao.putListApplications(list,id);
    }

    @Test
    public void putApplications() throws Exception {
        String id="1";
        String code="TEST";
        Applications applications=applicationsDAO.selectByUserIdAndAppCode(id,code);
        System.out.println(applications);
        redisApplicationsDao.putApplications(applications,id,code);
    }

    @Test
    public void getApplications() throws Exception {
        String id="1";
        String code="TEST";
        Applications applications=redisApplicationsDao.getApplications(id,code);
        System.out.println(applications);
    }

}
6、執行的結果