一、概念简介:

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 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<!-- config redis data and client jar -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.1.0</version>
</dependency> <!-- config need jar -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
<version>1.0</version>
</dependency>
<!-- cofig spring jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
……

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的一些基本配置,开启注解扫描功能和扫描路径。

 <!-- 激活@Controller模式 -->
<mvc:annotation-driven /> <context:annotation-config /> <!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
<context:component-scan base-package="com.chr" /> <!-- 引入redis属性配置文件 -->
<import resource="redis-context.xml"/>

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

  Spring配置redis,这些配置都比较基本,看文档就好了,但是有一个比较重要的点,就是redistemplate的Serializer配置,在后面通过SDR(Spring Data Redis)封装的一些方法操作Redis时会说到。

 <!-- scanner redis properties -->
<context:property-placeholder location="classpath:property/redis.properties" />
<!—注意此处注入的是JedisPoolConfig,说明SDR还依赖与Jedis -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxActive" value="${redis.maxActive}" />
<property name="maxWait" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean> <bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
p:pool-config-ref="poolConfig" /> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<!-- 如果不配置Serializer,那么存储的时候智能使用String,如果用User类型存储,那么会提示错误User can't cast to String!!!
--> <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> <bean id="viewResolver"
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。这样做的好处是:项目的层次比较清晰,方便后期改动。

     <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring-context.xml</param-value>
</context-param> <servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

下面是Spring MVC的java实现了:

User.java(实体类, com.chr.domain.User.java)

  注意User类必须实现Serializable接口,后面会解释。User类总共定义了三个字段:id、name、password。省略了相应的setter/getter方法。

 public class User implements Serializable {
private static final long serialVersionUID = 522889572773714584L; private String id;
private String name;
private String password; public User() {} public User(String id,String name,String password) {
this.id = id;
this.name = name;
this.password = password;
}

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

  在service接口中定义了两个方法:

  Add方法用于向redis中添加User实例,getUser则从redis中取出User实例。

 public interface UserOperationsService {
void add(User user);
User getUser(String key); }

UserOperationsServiceImpl.java(service的实现类,实现service借口 com.chr.service.impl. UserOperationsServiceImpl.java)

 @Service
public class UserOperationsServiceImpl implements UserOperationsService {
@Autowired
private RedisTemplate redisTemplate; @Override
public void add(User user) {
// TODO Auto-generated method stub
/*
* boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
* public Boolean doInRedis(RedisConnection redisConnection) throws
* DataAccessException { RedisSerializer<String> redisSerializer =
* redisTemplate .getStringSerializer(); byte[] key =
* redisSerializer.serialize(user.getId()); byte[] value =
* redisSerializer.serialize(user.getName()); return
* redisConnection.setNX(key, value); } }); return result;
*/
ValueOperations<String, User> valueops = redisTemplate
.opsForValue();
valueops.set(user.getId(), user);
} @Override
public User getUser(String key) {
ValueOperations<String, User> valueops = redisTemplate
.opsForValue();
User user = valueops.get(key);
return user;
} }

   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注释的代码:

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

  四、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)

 @Controller
@RequestMapping(value = "/redis")
public class UserController {
@Autowired
private UserOperationsServiceImpl userOperationsService;
private User user; @RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String addUser(
@RequestParam(value = "Id", required = true) String Id,
@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "password", required = true) String password) {
user = new User(Id, name, password);
userOperationsService.add(user);
return "/WEB-INF/jsp/AddUserSuccess.jsp";
} @RequestMapping(value = "/addUser", method = RequestMethod.GET)
public String addUser() {
return "/WEB-INF/jsp/AddUser.jsp";
}
}

  这里只贴出了部分代码(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>

三、部署运行

最后部署到Tomcat中,浏览器运行:http://localhost:8080/redis-web/redis/addUser

填写信息,单击添加Button后,即跳转到结果页面

整个项目只是一个展示Spring整合Redis基本使用的Demo,因本人知识有限,如文中有错误或偏颇之处,请各位提出。非常感谢:)

四、项目源码:

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

Jdk 1.7

MyEclipse 10.1

Spring Data Redis简介以及项目Demo,RedisTemplate和 Serializer详解的更多相关文章

  1. Redis在Laravel项目中的应用实例详解

    https://mp.weixin.qq.com/s/axIgNPZLJDh9VFGVk7oYYA 在初步了解Redis在Laravel中的应用 那么我们试想这样的一个应用场景 一个文章或者帖子的浏览 ...

  2. Spring Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  3. Spring Data Redis—Pub/Sub(附Web项目源码) (转)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  4. spring mvc Spring Data Redis RedisTemplate [转]

    http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载) ...

  5. spring data redis RedisTemplate操作redis相关用法

    http://blog.mkfree.com/posts/515835d1975a30cc561dc35d spring-data-redis API:http://docs.spring.io/sp ...

  6. 关于在项目中使用spring data redis与jedis的选择

    项目中需要用到redis,主要用来作为缓存,redis的客户端有两种实现方式,一是可以直接调用jedis来实现,二是可以使用spring data redis,通过spring的封装来调用. 应该使用 ...

  7. Spring Data Redis 让 NoSQL 快如闪电(2)

    [编者按]本文作者为 Xinyu Liu,文章的第一部分重点概述了 Redis 方方面面的特性.在第二部分,将介绍详细的用例.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 把 Redis ...

  8. Spring Data Redis 2.x 中 RedisConfiguration 类的新编写方法

    在 Spring Data Redis 1.x 的时候,我们可能会在项目中编写这样一个RedisConfig类: @Configuration @EnableCaching public class ...

  9. Spring Boot使用Spring Data Redis操作Redis(单机/集群)

    说明:Spring Boot简化了Spring Data Redis的引入,只要引入spring-boot-starter-data-redis之后会自动下载相应的Spring Data Redis和 ...

随机推荐

  1. 解决ubuntu侧边栏固定应用单击无反应的问题

    Linux下有些绿色软件,不需要安装就可以双击启动,但有些程序在打开后直接在 Launcher 中右键选择 Lock to Launcher ,但是,有时候单击图标后并未启动应用,下面给出解决方法. ...

  2. 解决iOS应用内购买报错:invalidProductIdentifiers

    当写完IAP业务过程后,点击测试却发现没有返回成功的商品Id,反而返回了无效的商品:response.invalidProductIdentifiers 这种情况下考虑以下因素: 创建的App ID是 ...

  3. 使用reuseport和recvmmsg优化UDP服务器

    http://skoo.me/system/2014/03/18/udp-server-performance/ http://www.helplib.net/s/linux.die/65_3223/ ...

  4. 使用API网关构建微服务

    使用传统的异步回调方法编写API组合代码会让你迅速坠入回调地狱.代码会变得混乱.难以理解且容易出错.一个更好的方法是使用响应式方法以一种声明式样式编写API网关代码.响应式抽象概念的例子有Scala中 ...

  5. Button with Hover Effect (Learned from 百度脑图)

    今天想学学PM的技能, 打开了百度脑图的网站, 看到中间那个按键的hover效果蛮好看, 遂学习一下. 效果如下: Demo 其实就是利用:before绘制了半透明白色的遮罩, 平时用transfor ...

  6. Trace和Debug主要用法

    #region 日志记录 //System.Diagnostics.Trace.Listeners.Clear(); //System.Diagnostics.Trace.AutoFlush = tr ...

  7. 深入分析iSCSI协议的应用

    深入分析iSCSI协议的应用 1 引言 快速增长的存储容量使得企业需要采用网络存储解决方案.目前网络存储技术采用的连接技术主要有光纤通道和TCP/IP.基于IP的网络存储能解决基于光纤通道的网络存储中 ...

  8. [NYOJ 860] 又见01背包

    又见01背包 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述     有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W  的物品,求所 ...

  9. Unity3D常见技术点(持续更新)

    一:获取对象, 添加对象等 1:使用prefab生成对象 GameObject ballObj = GameObject.Instantiate(Resources.Load(, Quaternion ...

  10. [转]CharacterController与Rigidbody

    From: http://blog.csdn.net/czlilove/article/details/9139103 今天下午碰到个问题纠结了很久:人物加上了Rigidbody并使用了重力,遇到悬崖 ...