Spring Data Redis簡介以及項目Demo,RedisTemplate和 Serializer詳解

一、概念簡介:


Redis:


  Redis是一款開源的Key-Value數據庫,運行在內存中,由ANSI C編寫,詳細的信息在Redis官網上面有,因爲我自己通過google等各種渠道去學習Redis,走了不少彎路,所以總結一條我認爲不錯的學習路徑給大家:


  1.《The Little Redis Book》


是一本開源PDF,只有29頁的英文文檔,看完後對Redis的基本概念應該差不多熟悉了,剩下的可以去Redis官網熟悉相關的命令。


  2.《Redis設計與實現》


如果想繼續深入,推薦這本書,現在已經出到第二版了,有紙質版書籍可以購買。上面詳細介紹了Redis的一些設計理念,並且給出了一些內部實現方式,和數據結構的C語言定義,有一些基本C語言基礎,就能看明白。


  3.Redis 2.6源代碼:


《Redis設計與實現》的作者發佈在Github上的一個開源項目,有作者詳細的註釋。


https://github.com/huangz1990/annotated_redis_source


Jedis:


  Jedis是Redis官方推出的一款面向Java的客戶端,提供了很多接口供Java語言調用。可以在Redis官網下載,當然還有一些開源愛好者提供的客戶端,如Jredis、SRP等等,推薦使用Jedis。


Spring Data Redis


  SDR是Spring官方推出,可以算是Spring框架集成Redis操作的一個子框架,封裝了Redis的很多命令,可以很方便的使用Spring操作Redis數據庫,Spring對很多工具都提供了類似的集成,如Spring Data MongDB…


  這三個究竟有什麼區別呢?可以簡單的這麼理解,Redis是用ANSI C寫的一個基於內存的Key-Value數據庫,而Jedis是Redis官方推出的面向Java的Client,提供了很多接口和方法,可以讓Java操作使用Redis,而Spring Data Redis是對Jedis進行了封裝,集成了Jedis的一些命令和方法,可以與Spring整合。在後面的配置文件(redis-context.xml)中可以看到,Spring是通過Jedis類來初始化connectionFactory的。


二、Spring Data Redis Demo


項目目錄:


Pom.xml配置: 


  Spring jar因爲比較多,就不貼出來了,讀者可以下載後面的項目源碼查看詳細配置,其實pom.xml可以精簡,並非一定需要寫的這麼細,我之所以這麼寫,是爲了看得更清楚。


<!-- config junit jar -->

 2         <dependency>

 3             <groupId>junit</groupId>

 4             <artifactId>junit</artifactId>

 5             <version>4.8.2</version>

 6             <scope>test</scope>

 7         </dependency>

 8         <!-- config redis data and client jar -->        

 9         <dependency>

10             <groupId>org.springframework.data</groupId>

11             <artifactId>spring-data-redis</artifactId>

12             <version>1.0.2.RELEASE</version>

13         </dependency>

14         <dependency>

15             <groupId>redis.clients</groupId>

16             <artifactId>jedis</artifactId>

17             <version>2.1.0</version>

18         </dependency>

19

20         <!-- config need jar -->

21         <dependency>

22             <groupId>commons-lang</groupId>

23             <artifactId>commons-lang</artifactId>

24             <version>2.6</version>

25         </dependency>

26         <dependency>

27             <groupId>org.apache.geronimo.specs</groupId>

28             <artifactId>geronimo-servlet_3.0_spec</artifactId>

29             <version>1.0</version>

30         </dependency>

31     <!-- cofig spring jar -->

32         <dependency>

33             <groupId>org.springframework</groupId>

34             <artifactId>spring-core</artifactId>

35             <version>${org.springframework.version}</version>

36         </dependency>

37     ……

redis.properties配置(WEB-INF/property/redis.properties)


  從properties文件的內容就知道這個文件是幹嘛的了,主要是redis連接池基本配置,詳細的配置可以查看redis文檔。


    redis.host=127.0.0.1

    redis.port=6379

    redis.pass=

       

    redis.maxIdle=300

    redis.maxActive=600

    redis.maxWait=1000

    redis.testOnBorrow=true

spring-context.xml(WEB-INF/config/spring-context.xml)


  Spring配置,這個也沒什麼說的,就是springMVC的一些基本配置,開啓註解掃描功能和掃描路徑。


 1 <!-- 激活@Controller模式 -->

 2     <mvc:annotation-driven />

 3    

 4     <context:annotation-config />  

 5    

 6     <!-- 對包中的所有類進行掃描,以完成Bean創建和自動依賴注入的功能 -->

 7     <context:component-scan base-package="com.chr" />

 8

 9    

10     <!-- 引入redis屬性配置文件 -->

11     <import resource="redis-context.xml"/>


redis-context.xml(WEB/config/redis-context.xml)


  Spring配置redis,這些配置都比較基本,看文檔就好了,但是有一個比較重要的點,就是redistemplate的Serializer配置,在後面通過SDR(Spring Data Redis)封裝的一些方法操作Redis時會說到。


 1 <!-- scanner redis properties -->

 2     <context:property-placeholder location="classpath:property/redis.properties" />

 3 <!—注意此處注入的是JedisPoolConfig,說明SDR還依賴與Jedis -->

 4     <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">

 5         <property name="maxIdle" value="${redis.maxIdle}" />

 6         <property name="maxActive" value="${redis.maxActive}" />

 7         <property name="maxWait" value="${redis.maxWait}" />

 8         <property name="testOnBorrow" value="${redis.testOnBorrow}" />

 9     </bean>

10

11     <bean id="connectionFactory"

12         class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"

13         p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"

14         p:pool-config-ref="poolConfig" />

15

16     <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">

17         <property name="connectionFactory" ref="connectionFactory" />

18 <!--         如果不配置Serializer,那麼存儲的時候智能使用String,如果用User類型存儲,那麼會提示錯誤User can't cast to String!!!

19  -->        <property name="keySerializer">

20             <bean

21                 class="org.springframework.data.redis.serializer.StringRedisSerializer" />

22         </property>

23         <property name="valueSerializer">

24             <bean

25                 class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

26         </property>

27     </bean>

28    

29     <bean id="viewResolver" 

30         class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

web.xml


  web.xml中只配置了spring-context.Xml,這是因爲我在spring-context.xml中加了一條語句:<import resource="redis-context.xml"/>,所以看起來有兩個配置,其實只需要配置spring-context.xml。這樣做的好處是:項目的層次比較清晰,方便後期改動。


 1     <listener>

 2         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

 3     </listener>

 4

 5     <context-param>

 6         <param-name>contextConfigLocation</param-name>

 7         <param-value>/WEB-INF/config/spring-context.xml</param-value>

 8     </context-param>

 9

10      <servlet>

11         <servlet-name>SpringMVC</servlet-name>

12         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

13         <init-param>

14                  <param-name>contextConfigLocation</param-name>

15                  <param-value>/WEB-INF/config/spring-context.xml</param-value>

16          </init-param>

17          <load-on-startup>2</load-on-startup>

18     </servlet>

19    

20     <servlet-mapping>

21         <servlet-name>SpringMVC</servlet-name>

22         <url-pattern>/</url-pattern>

23     </servlet-mapping>

下面是Spring MVC的java實現了:


User.java(實體類, com.chr.domain.User.java)


  注意User類必須實現Serializable接口,後面會解釋。User類總共定義了三個字段:id、name、password。省略了相應的setter/getter方法。


 1 public class User implements Serializable {

 2     private static final long serialVersionUID = 522889572773714584L;

 3    

 4     private String id;

 5     private String name;

 6     private String password;

 7    

 8     public User() {}

 9    

10     public User(String id,String name,String password) {

11         this.id = id;

12         this.name = name;

13         this.password = password;

14     }

UserOperationsService.java(service接口,com.chr.service.UserOperationsService.java)


  在service接口中定義了兩個方法:


  Add方法用於向redis中添加User實例,getUser則從redis中取出User實例。


1 public interface UserOperationsService {

2     void add(User user);

3     User getUser(String key);

4    

5 }

UserOperationsServiceImpl.java(service的實現類,實現service藉口 com.chr.service.impl. UserOperationsServiceImpl.java)

1 @Service

 2 public class UserOperationsServiceImpl implements UserOperationsService {

 3     @Autowired

 4     private RedisTemplate redisTemplate;

 5

 6     @Override

 7     public void add(User user) {

 8         // TODO Auto-generated method stub

 9         /*

10          * boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {

11          * public Boolean doInRedis(RedisConnection redisConnection) throws

12          * DataAccessException { RedisSerializer<String> redisSerializer =

13          * redisTemplate .getStringSerializer(); byte[] key =

14          * redisSerializer.serialize(user.getId()); byte[] value =

15          * redisSerializer.serialize(user.getName()); return

16          * redisConnection.setNX(key, value); } }); return result;

17          */

18         ValueOperations<String, User> valueops = redisTemplate

19                 .opsForValue();

20         valueops.set(user.getId(), user);

21     }

22

23

24     @Override

25     public User getUser(String key) {

26         ValueOperations<String, User> valueops = redisTemplate

27                 .opsForValue();

28         User user = valueops.get(key);

29         return user;

30     }

31

32 }

?

RedisTemplate和 Serializer詳解


  可以看到我在代碼中註釋掉了一段代碼,現在可以解釋上面留下的兩個問題了,第一個是在redis.xml中配置redistemplate的時候,同時配置了兩個Serializer:keySerializer實現了StringRedisSerializer,valueSerializer實現了JdkSerializationRedisSerializer。


  一、爲什麼要使用Serializer


  因爲redis是以key-value的形式將數據存在內存中,key就是簡單的string,key似乎沒有長度限制,不過原則上應該儘可能的短小且可讀性強,無論是否基於持久存儲,key在服務的整個生命週期中都會在內存中,因此減小key的尺寸可以有效的節約內存,同時也能優化key檢索的效率。


  value在redis中,存儲層面仍然基於string,在邏輯層面,可以是string/set/list/map,不過redis爲了性能考慮,使用不同的“encoding”數據結構類型來表示它們。(例如:linkedlist,ziplist等)。


  所以可以理解爲,其實redis在存儲數據時,都把數據轉化成了byte[]數組的形式,那麼在存取數據時,需要將數據格式進行轉化,那麼就要用到序列化和反序列化了,這也就是爲什麼需要配置Serializer的原因。


  二、SDR支持的序列化策略:


(詳細可查閱API文檔)


JdkSerializationRedisSerializer:

StringRedisSerializer:

JacksonJsonRedisSerializer:

OxmSerializer:

  其中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎的序列化策略,其中“JacksonJsonRedisSerializer”與“OxmSerializer”都是基於stirng存儲,因此它們是較爲“高級”的序列化(最終還是使用string解析以及構建java對象)。


  基本推薦使用JdkSerializationRedisSerializer和StringRedisSerializer,因爲其他兩個序列化策略使用起來配置很麻煩,如果實在有需要序列化成Json和XML格式,可以使用java代碼將String轉化成相應的Json和XML。


  三、使用Serializer


  在本項目中,是在配置文件中直接配置了相應的Serializer,key用的是StringRedisSerializer,value用的是JdkSerializationRedisSerializer,因爲在此項目中,key爲userId,爲String類型,value爲user爲java類,即POJO,所以使用JdkSerializationRedisSerializer。


  在redistemplate中直接配置Serializer當然比較方便,因爲在後面想redis中存取數據時,就不用再次配置Serializer,但是這僅限於只有一種數據類型的情況,比如在本項目中只有<String userId,User user>類型的數據需要存儲,如果有多種數據類型時,在配置文件中配置就顯得不方便了,那麼我們可以在存取數據時,即Service的實現類存取數據操作時分別指定相應的Serializer。


  所以在編程時有兩種選擇:


 1.在redistemplate中配置Serializer(本項目即採用這種方式)

  ValueOperations<String, User> valueops = redisTemplate

                .opsForValue();

  valueops.set(user.getId(), user);

  2.不在redistemplate中配置Serializer,而是在Service的實現類中單獨指定Serializer。就如同UserOperationsServiceImpl.java註釋的代碼:

    

 四、Redistemplate


  SDR官方文檔中對Redistemplate的介紹:the template is in fact the central class of the Redis module due to its rich feature set. The template offers a high-level abstraction for Redis interactions.


  通過Redistemplate可以調用ValueOperations和ListOperations等等方法,分別是對Redis命令的高級封裝。


  但是ValueOperations等等這些命令最終是要轉化成爲RedisCallback來執行的。也就是說通過使用RedisCallback可以實現更強的功能,SDR文檔對RedisCallback的介紹:RedisTemplate and StringRedisTemplate allow the developer to talk directly to Redis through the RedisCallback interface. This gives complete control to the developer as it talks directly to the RedisConnection。


  具體的使用方法可以參考Api文檔。


UserController.java(控制器類,com.chr.controller)

1 @Controller

 2 @RequestMapping(value = "/redis")

 3 public class UserController {

 4     @Autowired

 5     private UserOperationsServiceImpl userOperationsService;

 6     private User user;

 7

 8     @RequestMapping(value = "/addUser", method = RequestMethod.POST)

 9     public String addUser(

10             @RequestParam(value = "Id", required = true) String Id,

11             @RequestParam(value = "name", required = true) String name,

12             @RequestParam(value = "password", required = true) String password) {

13         user = new User(Id, name, password);

14         userOperationsService.add(user);

15         return "/WEB-INF/jsp/AddUserSuccess.jsp";

16     }

17

18     @RequestMapping(value = "/addUser", method = RequestMethod.GET)

19     public String addUser() {

20         return "/WEB-INF/jsp/AddUser.jsp";

21     }

22 }


 這裏只貼出了部分代碼(addUser的代碼),剩下的getUser代碼類似,可以下載源碼查看。


其中分爲兩種方法,get和post,get方法直接return到表單填寫頁面,從而實現post到addUser添加User。


AddUser.jsp

<form id="addUser" name="addUser" action="redis/addUser" method="post">

                ID:<input id="Id" name="Id" type="text" />

                Name:<input id="name" name="name" type="text" /> 

                Password:<input id="password" name="password" type="password" />

                <input value="添加"

                    type="submit" />

</form>

三、部署運行


最後部署到Tomcat中,瀏覽器運行:http://localhost:8080/redis-web/redis/addUser


填寫信息,單擊添加Button後,即跳轉到結果頁面


整個項目只是一個展示Spring整合Redis基本使用的Demo,因本人知識有限,如文中有錯誤或偏頗之處,請各位提出。非常感謝:)


四、項目源碼:


http://files.cnblogs.com/edwinchen/redis-web.rar


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章