1. 程式人生 > >Spring+Redis整合

Spring+Redis整合

一:目錄

  • redis的安裝和啟動
  • jedis的使用
    • Hello World
    • JedisPool的使用
  • Spring整合

二:Redis下載、安裝和啟動

2、啟動Redis服務
使用終端切換到redis的目錄下,然後 使用命令啟動 redis-server.exe redis.windows.conf

3、啟動客戶端

使用終端切換到redis的目錄下,然後 使用命令啟動 redis-cli.exe

三:jedis的使用

1、在pom.xml 中引入spring(需要用到spring-test來測試)和jedis相關的依賴

  <properties
>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.2.3.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId
>
<version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version>
<scope>test</scope> </dependency> <!-- springframework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> </dependencies>

2、測試Jedis相關的方法

這裡只是列舉出jedis常用的一些方法,jedis的方法名和redis的命令是一樣的,瞭解了命令就自然知道jedis中相關的方法了,這裡並不介紹redis中的每個命令

SpringTestCase

package com.mengdee.manager.redis;

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;

@ContextConfiguration(locations = {"classpath:conf/spring/spring-base.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTestCase extends AbstractJUnit4SpringContextTests{

}

JedisTest

package com.mengdee.manager.redis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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


import redis.clients.jedis.Jedis;

public class JedisTest extends SpringTestCase{

    private Jedis jedis;

    @Before
    public void setup(){
        jedis = new Jedis("127.0.0.1", 6379);
    }



     /**
      * redis 字串string
      * 
      * 常用操作:新增鍵值對 、獲取鍵對應的值、刪除鍵、批量新增鍵值對、對數字型的值+1或者-1
      */
      @Test
      public void testString() {
          //-----新增資料----------  
          String key = "name";
          jedis.set(key,"mengdee");
          System.out.println(jedis.get(key));

          jedis.append(key, " is good"); 
          System.out.println(jedis.get(key)); 

          jedis.del(key);  
          System.out.println(jedis.get(key));

          // 批量新增鍵值對,注意值都是字串型別,注意這裡是一次性新增三個鍵值對,他們的關係是並列關係(即使三個鍵值對而不是一個鍵值對的值是三個值)
          jedis.mset("name","mengdee","age","23","nickname","mengday");
          jedis.incr("age"); //進行加1操作
          System.out.println(jedis.get(key) + "-" + jedis.get("age") + "-" + jedis.get("nickname"));
      }

      /**
       * redis map
       * map 包含多個鍵值對,通常儲存Java中的物件使用map資料型別儲存
       */
      @Test
      public void testMap() {
          //-----新增資料----------  
          Map<String, String> userMap = new HashMap<String, String>();
          userMap.put("id", "1");
          userMap.put("username", "mengdee");
          userMap.put("age", "20");

          String key = "user:1";
          jedis.hmset(key, userMap);


          // 一次獲取多個欄位的值
          List<String> values = jedis.hmget(key, "id", "username", "age");
          System.out.println(values);  

          // 通常使用hgetAll獲取到的Map轉換成Java中的物件
          Map<String, String> userMap2 = jedis.hgetAll(key);
          Set<Entry<String, String>> entrySet = userMap2.entrySet();
          for (Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
          }

          System.out.println(jedis.hmget(key, "age")); 
          System.out.println(jedis.hlen(key)); 
          System.out.println(jedis.exists(key));  
          System.out.println(jedis.hkeys(key));
          System.out.println(jedis.hvals(key));

          jedis.hdel(key,"age");
      }

      /** 
       * jedis list(一般儲存像Java中的陣列或者List這樣的資料型別)
       */  
      @Test  
      public void testList(){  
          //開始前,先移除所有的內容  
          String key = "java";
          jedis.del(key);  

          jedis.lpush(key, "gradle");  
          jedis.lpush(key, "springmvc");  
          jedis.lpush(key, "mybatis");  
          jedis.rpush(key, "spring boot");

          System.out.println(jedis.lrange(key, 0, -1));  

          jedis.del(key);
          jedis.rpush(key, "spring");  
          jedis.rpush(key, "struts");  
          jedis.rpush(key, "hibernate"); 
          System.out.println(jedis.lrange(key, 0, -1));
      }  

     /** 
      * jedis set
      * 
      * 注意set操作是無須的
      */  
     @Test  
     public void testSet(){  
         //新增  
         String key = "users";
         jedis.sadd(key,"zhangsan");  
         jedis.sadd(key,"lisi");  
         jedis.sadd(key,"mengdee");  
         jedis.sadd(key,"mengday");
         jedis.sadd(key,"X");  

         jedis.srem(key,"X");  

         System.out.println(jedis.smembers(key));
         System.out.println(jedis.sismember(key, "mengdee"));
         System.out.println(jedis.srandmember(key));  
         System.out.println(jedis.scard(key));
     }  


}

3、JedisPool的使用

上面示例是沒有使用執行緒池的,在實際開發中肯定要使用執行緒池,要不然每次都要建立連線,下面只是簡單的實現方式,demo版,不能實際在專案中使用,在專案中實際使用還需要使用更優的實現

package com.mengdee.manager.utils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public final class RedisUtil {

    //Redis伺服器IP
    private static String ADDR = "127.0.0.1";

    //Redis的埠號
    private static int PORT = 6379;

    //訪問密碼
    private static String AUTH = "admin";

    //控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。
    private static int MAX_IDLE = 200;

    private static int TIMEOUT = 10000;

    //在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;
    private static boolean TEST_ON_BORROW = true;

    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis連線池
     */
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(MAX_IDLE);
            config.setTestOnBorrow(TEST_ON_BORROW);
            jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取Jedis例項
     * @return
     */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 釋放jedis資源
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }
}

使用JedisUtil獲取Jedis物件,操作快取

@Test
public void testRedisPool() {
      JedisUtil.getJedis().set("newname", "中文測試");
      System.out.println(RedisUtil.getJedis().get("newname"));
}

第二部分:Spring整合

開發中可以單獨使用Jedis中相關的方法操作快取,也可以使用spring提供的相關的註解

1、 在pom.xml中引入相關依賴

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>4.2.3.RELEASE</spring.version>
  </properties>


  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>

    <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>
         <version>${spring.version}</version>
         <scope>test</scope>
     </dependency>

     <!-- springframework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.8.1.RELEASE</version>
    </dependency>


    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
  </dependencies>

2、在src/main/resources/conf/settings/application.properties下配置redis相關配置

redis.master.ip=localhost
redis.master.port=6379
redis.pool.maxActive=1024
redis.pool.maxIdle=200
redis.pool.maxWait=1000
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true

3、在src/main/resources/conf/spring 下配置spring-base.xml和spring-redis.xml

spring-base.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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 載入配置檔案資料庫連線檔案 -->
    <context:property-placeholder location="classpath:conf/settings/*.properties" />

    <context:component-scan base-package="com.mengdee.**.dao,com.mengdee.**.service"/>

</beans>

spring-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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/cache
       http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- 以前專案中的配置,注意需要新增Spring Data Redis等jar包 -->
    <description>redis配置</description>

    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.pool.maxIdle}"/>
        <property name="maxTotal" value="${redis.pool.maxActive}"/>
        <property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
        <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
        <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
    </bean>

    <!-- JedisConnectionFactory -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.master.ip}"/>
        <property name="port" value="${redis.master.port}"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
          p:connectionFactory-ref="jedisConnectionFactory">
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </bean>

    <!--spring cache-->
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
          c:redisOperations-ref="redisTemplate">
        <!-- 預設快取10分鐘 -->
        <property name="defaultExpiration" value="600"/>
        <property name="usePrefix" value="true"/>
        <!-- cacheName 快取超時配置,半小時,一小時,一天 -->
        <property name="expires">
            <map key-type="java.lang.String" value-type="java.lang.Long">
                <entry key="halfHour" value="1800"/>
                <entry key="hour" value="3600"/>
                <entry key="oneDay" value="86400"/>
                <!-- shiro cache keys -->
                <entry key="authorizationCache" value="1800"/>
                <entry key="authenticationCache" value="1800"/>
                <entry key="activeSessionCache" value="1800"/>
            </map>
        </property>
    </bean>

    <!-- cache註解,和spring-ehcache.xml中的只能使用一個 -->
    <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
</beans>

4、Service 類

User

package com.mengdee.manager.entity;

import java.io.Serializable;

// 一定要實現Serializable,否則報錯
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;
    private String username;
    private int age;


    public User() {
        super();
    }


    public User(Long id, String username, int age) {
        super();
        this.id = id;
        this.username = username;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", age=" + age + "]";
    }

    // getter && setter
}

UserService

package com.mengdee.manager.service;

import com.mengdee.manager.entity.User;

public interface UserService {

    public User getUserInfo(String username);

    public void deleteUser(String username);

    public User updateUser(User user);

}

UserServiceImpl

package com.mengdee.manager.service;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.mengdee.manager.entity.User;

@Service
public class UserServiceImpl implements UserService {

    @Cacheable("users")
    @Override
    public User getUserInfo(String username) {
        System.out.println("從資料庫中查詢使用者資訊。。。");
        long id = (int)((Math.random()*9+1)*100000);

        return new User(id, username, 20);
    }

    @CacheEvict("users")
    @Override
    public void deleteUser(String username) {
        System.out.println("刪除使用者:"+username);
    }

    // 使用@CachePut比許返回要快取的物件,使用value作為鍵的字首(users),使用冒號作為分隔符(:),使用key的值追加到前面的組合,如"users:mengdee"
    // 方法的返回值作為鍵值對的值快取起來,如果方法沒有返回值,那麼就相當於沒有更新快取
    @CachePut(value="users", key="#user.getUsername()")
    @Override
    public User updateUser(User user) {
        System.out.println("更新使用者");

        return user;
    }

}

5、測試

UserServiceTest

package com.mengdee.manager.redis;

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

import com.mengdee.manager.service.UserService;


public class UserServiceTest extends SpringTestCase{

    @Autowired
    private UserService userService;


    @Test
    public void testGetUserInfo(){
        String username = "mengdee";
        // 第一次執行了方法體
        userService.getUserInfo(username);

        // 第二次沒有執行方法體,直接從快取中獲取的
        User userInfo = userService.getUserInfo(username);
        System.out.println(userInfo); // User [id=565857, username=mengdee, age=20]
    }

    @Test
    public void testDeleteUser(){
        String username = "mengdee";
        User userInfo = userService.getUserInfo(username);
        System.out.println(userInfo);

        userService.getUserInfo(username);

        userService.deleteUser(username);
    }

    @Test
    public void testUpdateUser(){
        String username = "mengdee";
        User userInfo = userService.getUserInfo(username);
        System.out.println(userInfo);

        userInfo.setAge(200);
        userInfo.setId(10L);
        userService.updateUser(userInfo);

        User userInfo2 = userService.getUserInfo(username);
        System.out.println(userInfo2);
    }
}

使用redis-cli可以看到User物件快取的鍵是“users:mengdee”, 從中可以看出key的預設規則是@Cacheable中的value值跟冒號分隔,然後跟引數的實際值

這裡寫圖片描述

注意

1、注意配置key的失效時間,既可以野資料的存在,也最大化利用記憶體,一般不要失效時間配置為永久

2、在使用redis的時候,對於鍵的命名規則非常重要,常用的做法是實體名字串跟冒號跟ID值,如“user:1”, “user:2”, 或者其他命名規則在使用Spring的 @Cacheable 的時候更要注意,因為當兩個方法的key相同時,兩個方法的返回值會相互覆蓋,例如以下兩個方法

@Cacheable("user")
User getUser(String id);

@Cacheable("user")
User getUserDetail(String id);

當執行第一個方法後換成user物件,再執行第二個方法還會換成user物件,因為這兩個方法的key最終生成的是完全一樣的,所以第二個方法其實會更新快取,這兩個方法返回雖然都是User物件,很可能返回user物件的欄位是不同的,這樣在使用user物件時很可能拿不到值,解決方法就是key的生成規則一定不能一樣,可以在key的生成規則中加入方法名作為區分,當然這不是一個很好的方式,因為方法名往往是比較長的,key越長越佔記憶體,key應該儘可能的簡短來節省記憶體

相關推薦

eclipse spring redis 整合-配置

wait 版本 ace name 合取 instance wid cati 17. 花了一天時間折騰redis的配置 用到的jar spring 3.1.1 aopalliance-1.0.jar commons-pool2-2.3.jar jedis-2.7.2

ssm中加入redisspring -redis整合,簡單,認識redis

1匯入spring和redis的jar包,當然推薦用maven。開啟服務 2.application.xml中配置 定義執行緒池 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  

spring + redis 整合

1.新增pom依賴 <properties> <spring.version>5.0.8.RELEASE</spring.version> <redis.version>2.9.

Spring+Redis整合以及異常 Could not resolve placeholder解決

spring+Redis 概述 本文主要為了整合spring和redis,以及記錄解決中間遇到的問題。 什麼是redis? Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言

java程式碼中操作Redis:單機redis、叢集redisspring+redis整合

一、準備 關於redis的一些安裝,可以檢視我的幾篇文章自行安裝:Redis目錄。匯入java的Redis客戶端依賴包Jedis:<dependency> <groupId>redis.clients</groupId

spring+redis整合,策略設計,靈活配置,支援單機和叢集

spring+redis整合,策略設計,支援單機和叢集 前言 單JVM保證併發資料安全 1.執行緒同步鎖,synchronized(this)或者Lock介面 2.資料表增加版本號欄位,update where條件後面跟上版本號.這樣就只會更新一次 3.

Spring+Redis整合

一:目錄 redis的安裝和啟動 jedis的使用 Hello World JedisPool的使用 Spring整合 二:Redis下載、安裝和啟動 2、啟動Redis服務 使用終端切換到redis的目錄下,然後 使用命令啟動 red

jedis,spring-redis-data 整合使用,版本問題異常

問題 artifact ons com pri connect def 中心 div jedis,spring-redis-data 整合使用,版本不匹配的時候經常會報一些異常,例如1: java.lang.NoClassDefFoundError: org/springf

Redis整合spring總結

sca eric str 綁定 apach 編寫 登錄 drive his 1 一:Redis簡介: 2 Redis是一個開源(BSD許可)的內存數據結構存儲,用作數據庫,緩存和消息代理。 3 簡單來說,它是一個以(key,value)

Redis整合Spring實現分布式鎖

gte 展示 是否 alt cep 狀態 wait 封裝 RR spring把專門的數據操作獨立封裝在spring-data系列中,spring-data-redis是對Redis的封裝 <dependencies> <!-- 添加spri

Spring Boot整合JPA、Redis和Swagger2

enc code extends art redis學習 and 小結 JD pip 好久沒有總結了,最近也一直在學習。今天就把spring boot與其它技術的整合做個小總結,主要是jpa、redis和swagger2。公司裏有用到這些,整合起來也很簡單。 首先,新建一個

Spring Boot-整合redis(六)

lec access IV 使用 tty factor cat 訪問 spa redis安裝 參考:https://www.cnblogs.com/LQBlog/p/9214517.html 單機版 1.添加pom依賴 <!-- Spring Boot R

Spring AOP整合redis 實現緩存統一管理

integer eva spring eas chm 形參 結束 system 常量 項目使用redis作為緩存數據,但面臨著問題,比如,項目A,項目B都用到redis,而且用的redis都是一套集群,這樣會帶來一些問題。問題:比如項目A的開發人員,要緩存一些熱門數據,想到

spring boot 整合redis 以一個熱門房產為例子

1.新增redis依賴 就是jedis redis.clients jedis 2.9.0 2.每次點選房屋詳情熱度加一 呼叫此方法 recommandService.increase(id);//每次點選房屋熱度加1 3.recommandService如何寫主要

redis整合spring(redisTemplate工具類) redis整合spring(redisTemplate工具類)

redis整合spring(redisTemplate工具類) 原文地址:http://blog.csdn.net/qq_34021712/article/details/75949706   ©王賽超 前言 關於哨兵模式的配置,我是參考網上

Spring Boot整合Redis實戰操作

最近在使用Spring Boot,發現其功能真是強大,可以快速的整合很多的元件功能,非常方便: 今天就來介紹下,如何整合Redis。 定義 Redis 是一個高效能的key-value資料庫。它支援儲存的value型別很多,包括string(字串)、list(連結串列)、set(集合)、zset

Spring Boot(十一)Redis整合從Docker安裝到分散式Session共享

一、簡介 Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API,Redis也是技術領域使用最為廣泛的儲存中介軟體,它是「Remote Dictionary Service」首字母縮寫,也就是「遠端字典服務」。 Red

Spring boot整合Redis(2)—RedisTemplate的使用來儲存Map集合

前言:上一篇文章我們用的是StringRedisTemplate,但是它存在一點問題,也迫使我重新寫了程式碼,問題是:在我們往快取中存入數字形式的String型別時,我們在利用Spring could將獲取到的資料傳送到另一服務時,我們發現數據已經被強轉為Integer型別了,因為我們可能傳輸的資料龐大,型別

Spring Boot整合Redis及RedisTemplate常用操作

Spring Boot整合Redis maven依賴 <!-- redis 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <

spring boot整合redis實戰

1.spring boot整合redis,此次專案有進行maven的相關配置工作,整個程式碼結構目錄如下: 其中pom檔案繫結相關的redis的引數步驟如下: 其中<dependency>依賴當中進新配置了相關的redis依賴,也就是spring-boot-start