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

1、概念簡介:java

Redis:git

  Redis是一款開源的Key-Value數據庫,運行在內存中,由ANSI C編寫,詳細的信息在Redis官網上面有,由於我本身經過google等各類渠道去學習Redis,走了很多彎路,因此總結一條我認爲不錯的學習路徑給你們:github

  1.《The Little Redis Book》web

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

  2.《Redis設計與實現》spring

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

  3.Redis 2.6源代碼:apache

《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的。

 

2、Spring Data Redis Demo

項目目錄:

 

 

Pom.xml配置: 

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

 1 <!-- 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。

  1、爲何要使用Serializer

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

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

  因此能夠理解爲,其實redis在存儲數據時,都把數據轉化成了byte[]數組的形式,那麼在存取數據時,須要將數據格式進行轉化,那麼就要用到序列化和反序列化了,這也就是爲何須要配置Serializer的緣由。

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

(詳細可查閱API文檔)

  • JdkSerializationRedisSerializer:
  • StringRedisSerializer:
  • JacksonJsonRedisSerializer:
  • OxmSerializer:

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

  基本推薦使用JdkSerializationRedisSerializer和StringRedisSerializer,由於其餘兩個序列化策略使用起來配置很麻煩,若是實在有須要序列化成Json和XML格式,可使用java代碼將String轉化成相應的Json和XML。

  3、使用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註釋的代碼:

1 boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
2      public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException { 
3          RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer(); 
4          byte[] key = redisSerializer.serialize(user.getId());
5          byte[] value = redisSerializer.serialize(user.getName()); 
6          return redisConnection.setNX(key, value); } }); 
7     return result;
8 }

 

 

  4、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" /><br/>
                Name:<input id="name" name="name" type="text" /><br/> 
                Password:<input id="password" name="password" type="password" /><br/>
                <input value="添加"
                    type="submit" />
</form>

 

 

3、部署運行

 

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

 

 

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

 

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

 

4、項目源碼:

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

 

Jdk 1.7

MyEclipse 10.1

相關文章
相關標籤/搜索