Redis+Spring緩存實例(windows環境,附實例源碼及詳解)

jopen 10年前發布 | 35K 次閱讀 Redis NoSQL數據庫

一、Redis了解

1.1、Redis介紹:

redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set –有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。

Redis數據庫完全在內存中,使用磁盤僅用于持久性。相比許多鍵值數據存儲,Redis擁有一套較為豐富的數據類型。Redis可以將數據復制到任意數量的從服務器。

1.2、Redis優點:

(1)異常快速:Redis的速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄。

(2)支持豐富的數據類型:Redis支持最大多數開發人員已經知道像列表,集合,有序集合,散列數據類型。這使得它非常容易解決各種各樣的問題,因為我們知道哪些問題是可以處理通過它的數據類型更好。

(3)操作都是原子性:所有Redis操作是原子的,這保證了如果兩個客戶端同時訪問的Redis服務器將獲得更新后的值。

(4)多功能實用工具:Redis是一個多實用的工具,可以在多個用例如緩存,消息,隊列使用(Redis原生支持發布/訂閱),任何短暫的數據,應用程序,如Web應用程序會話,網頁命中計數等。

1.3、Redis缺點:

(1)單線程

(2)耗內存

二、64位windows下Redis安裝

Redis官方是不支持windows的,但是Microsoft Open Tech group 在 GitHub上開發了一個Win64的版本,下載地址:https://github.com/MSOpenTech/redis/releases注意只支持64位哈

小寶鴿是下載了Redis-x64-3.0.500.msi進行安裝。安裝過程中全部采取默認即可。

安裝完成之后可能已經幫你開啟了Redis對應的服務,博主的就是如此。查看資源管理如下,說明已經開啟:

圖1

已經開啟了對應服務的,我們讓它保持,下面例子需要用到。如果沒有開啟的,我們命令開啟,進入Redis的安裝目錄(博主的是C:\Program Files\Redis),然后如下命令開啟:

redis-server  redis.windows.conf 

這里寫圖片描述

OK,下面我們進行實例。

三、詳細實例

本工程采用的環境:eclipse + maven + spring + junit

3.1、添加相關依賴(spring+junit+redis依賴),pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.luo</groupId>
  <artifactId>redis_project</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
        <!-- spring版本號 -->
        <spring.version>3.2.8.RELEASE</spring.version>
        <!-- junit版本號 -->
        <junit.version>4.10</junit.version>
  </properties>

  <dependencies>
        <!-- 添加Spring依賴 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--單元測試依賴 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!--spring單元測試依賴 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Redis 相關依賴 -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.3</version>
        </dependency>

    </dependencies>
</project>

3.2、spring配置文件application.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" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 自動掃描注解的bean -->
    <context:component-scan base-package="com.luo.service" />

    <!-- 引入properties配置文件 -->  
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
               <value>classpath:properties/*.properties</value>
                <!--要是有多個配置文件,只需在這里繼續添加即可 -->
            </list>
        </property>
    </bean>

    <!-- jedis 配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >
          <property name="maxIdle" value="${redis.maxIdle}" />
          <property name="maxWaitMillis" value="${redis.maxWait}" />
          <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean >

    <!-- redis服務器中心 -->
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
          <property name="poolConfig" ref="poolConfig" />
          <property name="port" value="${redis.port}" />
          <property name="hostName" value="${redis.host}" />
          <!-- <property name="password" value="${redis.password}" /> -->
          <property name="timeout" value="${redis.timeout}" ></property>
    </bean >
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
          <property name="connectionFactory" ref="connectionFactory" />
          <property name="keySerializer" >
              <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
          </property>
          <property name="valueSerializer" >
              <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
          </property>
    </bean >

    <!-- cache配置 -->
    <bean id="methodCacheInterceptor" class="com.luo.redis.cache.MethodCacheInterceptor" >
          <property name="redisTemplate" ref="redisTemplate" />
    </bean >

    <!-- aop配置切點跟通知 -->
    <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="methodCacheInterceptor"/>
        <property name="pattern" value=".*ServiceImpl.*getTimestamp"/>
    </bean>
    <bean id="redisTestService" class="com.luo.service.impl.RedisTestServiceImpl">
    </bean>
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

</beans>

3.3、Redis配置參數,redis.properties:

#redis中心
#綁定的主機地址
redis.host=127.0.0.1 
#指定Redis監聽端口,默認端口為6379
redis.port=6379 
#授權密碼(本例子沒有使用)
redis.password=123456  
#最大空閑數:空閑鏈接數大于maxIdle時,將進行回收
redis.maxIdle=100  
#最大連接數:能夠同時建立的“最大鏈接個數”
redis.maxActive=300  
#最大等待時間:單位ms
redis.maxWait=1000   
#使用連接時,檢測連接是否成功 
redis.testOnBorrow=true 
#當客戶端閑置多長時間后關閉連接,如果指定為0,表示關閉該功能
redis.timeout=10000 

3.4、添加接口及對應實現RedisTestService.java和RedisTestServiceImpl.java:

package com.luo.service;

public interface RedisTestService {
    public String getTimestamp(String param);
}
package com.luo.service.impl;

import org.springframework.stereotype.Service;
import com.luo.service.RedisTestService;

@Service
public class RedisTestServiceImpl implements RedisTestService {

    public String getTimestamp(String param) {
        Long timestamp = System.currentTimeMillis();
        return timestamp.toString();
    }

}

3.5、本例采用spring aop切面方式進行緩存,配置已在上面spring配置文件中,對應實現為MethodCacheInterceptor.java:

package com.luo.redis.cache;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class MethodCacheInterceptor implements MethodInterceptor {

    private RedisTemplate<Serializable, Object> redisTemplate;
    private Long defaultCacheExpireTime = 10l; // 緩存默認的過期時間,這里設置了10秒

    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object value = null;

        String targetName = invocation.getThis().getClass().getName();
        String methodName = invocation.getMethod().getName();

        Object[] arguments = invocation.getArguments();
        String key = getCacheKey(targetName, methodName, arguments);

        try {
            // 判斷是否有緩存
            if (exists(key)) {
                return getCache(key);
            }
            // 寫入緩存
            value = invocation.proceed();
            if (value != null) {
                final String tkey = key;
                final Object tvalue = value;
                new Thread(new Runnable() {
                    public void run() {
                        setCache(tkey, tvalue, defaultCacheExpireTime);
                    }
                }).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (value == null) {
                return invocation.proceed();
            }
        }
        return value;
    }

    /** * 創建緩存key * * @param targetName * @param methodName * @param arguments */
    private String getCacheKey(String targetName, String methodName,
            Object[] arguments) {
        StringBuffer sbu = new StringBuffer();
        sbu.append(targetName).append("_").append(methodName);
        if ((arguments != null) && (arguments.length != 0)) {
            for (int i = 0; i < arguments.length; i++) {
                sbu.append("_").append(arguments[i]);
            }
        }
        return sbu.toString();
    }



    /** * 判斷緩存中是否有對應的value * * @param key * @return */
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /** * 讀取緩存 * * @param key * @return */
    public Object getCache(final String key) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate
                .opsForValue();
        result = operations.get(key);
        return result;
    }



    /** * 寫入緩存 * * @param key * @param value * @return */
    public boolean setCache(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate
                    .opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void setRedisTemplate(
            RedisTemplate<Serializable, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}

3.6、單元測試相關類:

package com.luo.baseTest;

import org.junit.runner.RunWith;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  

//指定bean注入的配置文件 
@ContextConfiguration(locations = { "classpath:application.xml" })  
//使用標準的JUnit @RunWith注釋來告訴JUnit使用Spring TestRunner 
@RunWith(SpringJUnit4ClassRunner.class)  
public class SpringTestCase extends AbstractJUnit4SpringContextTests {

}
package com.luo.service;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.luo.baseTest.SpringTestCase;

public class RedisTestServiceTest extends SpringTestCase {

    @Autowired  
    private RedisTestService redisTestService;

    @Test  
    public void getTimestampTest() throws InterruptedException{  
        System.out.println("第一次調用:" + redisTestService.getTimestamp("param"));
        Thread.sleep(2000);
        System.out.println("2秒之后調用:" + redisTestService.getTimestamp("param"));
        Thread.sleep(11000);
        System.out.println("再過11秒之后調用:" + redisTestService.getTimestamp("param"));
    } 
}

3.7、運行結果:

這里寫圖片描述

四、源碼下載

http://download.csdn.net/detail/u013142781/9403316

來自: http://blog.csdn.net/u013142781/article/details/50515320

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!