spring redis - downgoon/hello-world GitHub Wiki

实验-1: spring-redis-c1-codeonly

内容提要

  • 进入演示代码
  • 添加依赖构件
  • 讲解主要代码

进入演示代码

进入“实验-1”的代码:

$ git checkout spring-redis
$ git checkout spring-redis-c1-codeonly

添加依赖构件

在pom.xml中引用 spring-boot-starter-redis

<parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>1.3.3.RELEASE</version>
</parent>

<dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-redis</artifactId>
     </dependency>
</dependencies>

讲解主要代码

RedisHello.java中编写代码:

JedisConnectionFactory factory = new JedisConnectionFactory();
factory.afterPropertiesSet();
		
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(factory);
template.afterPropertiesSet();

        
template.opsForValue().set("name", "downgoon");

String name = template.opsForValue().get("name");
        
LOG.info("name: {}", name);

上述代码有2个主要类:

  • JedisConnectionFactory: 管理Redis连接池。我们并没有设置RedisServer的host:port ? 因为有默认值 localhost:6379的。
  • StringRedisTemplate: 管理对Redis的操作。StringRedisTemplateRedisTemplate的一个子类,表示Key和Value的编码方式都是String类型。如果其他类型,可以设置相应的序列化机制。

特别注意

Spring中的组件初始化往往并不是init(),而是afterPropertiesSet()方法。factory.afterPropertiesSet();template.afterPropertiesSet();分别表示初始化。

功能拓展

  • 设置指定的host:port
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName("localhost");
factory.setPort(6379);
factory.afterPropertiesSet();
  • 如何读写一个Java Bean ?

附录-1: 安装运行Redis

安装Redis

  • 用docker安装redis (下载redis镜像):
$ docker search redis
$ docker pull daocloud.io/redis
  • 运行redis-server:
$ docker run --name redis -d -p 6379:6379 daocloud.io/redis

接着可以访问localhost:6379的Redis服务了。

  • Mac 下安装Redis
$ brew install redis
  • 安装后可执行文件:
➜  3.2.6 tree /usr/local/Cellar/redis/3.2.6/bin
/usr/local/Cellar/redis/3.2.6/bin
├── redis-benchmark
├── redis-check-aof
├── redis-check-rdb
├── redis-cli
├── redis-sentinel -> redis-server
└── redis-server
  • 用客户端连接redis-server
$ redis-cli
127.0.0.1:6379> keys *

连接本地redis-server,并用keys *指令查看所有keys列表。 注意:请勿轻易在生产库使用该指令,更多技巧请阅读 10 Tips on Redis

实验-2: spring-redis-c2-readwritebean

进入“实验-2”的代码:

$ git checkout spring-redis
$ git checkout spring-redis-c2-readwritebean

编写主要代码:RedisHello.java

JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName("localhost");
factory.setPort(6379);
factory.afterPropertiesSet();

RedisTemplate<String, Employee> template = new RedisTemplate<String, Employee>();
template.setConnectionFactory(factory);

template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());

template.afterPropertiesSet();

template.opsForValue().set("name", new Employee("downgoon", 18));

Employee employee = template.opsForValue().get("name");

LOG.info("employee: {}", employee);

其中Value部分的序列化是JSON方式:GenericJackson2JsonRedisSerializer

我们查查Redis中,序列化情况:

$ redis-cli
127.0.0.1:6379> get name
"{\"@class\":\"io.downgoon.hello.spring.redis.Employee\",\"name\":\"downgoon\",\"age\":18}"

Employee类的片段:

public class Employee implements Serializable {

    private static final long serialVersionUID = -1L;

    private String name;
    private Integer age;
    
    
    public Employee() {
    	/* called on JSON de-serialization */
    }

    public Employee(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

注意: 为了Employee 能够被反序列化,构造方法必须保留一个输入参数为空的默认构造方法。

实验-3: JSON序列化的三个实现

接口 RedisSerializer 有三个实现,分别是:

  • GenericJackson2JsonRedisSerializer
  • Jackson2JsonRedisSerializer
  • JacksonJsonRedisSerializer

它们有什么区别呢? 进入代码:$ git checkout spring-redis-c3-jackson2

  • 通用序列化: GenericJackson2JsonRedisSerializer 代码:
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());

它的好处是:反序列化的时候,不需要指定Java对象的类型。为什么能做到这一点? 原因是“在序列化的时候,序列化结果中包含了类的名称”。如下从Redis中获取序列化的结果:

127.0.0.1:6379> get name
"{\"@class\":\"io.downgoon.hello.spring.redis.Employee\",\"name\":\"downgoon\",\"age\":18}"
  • 特定序列化:Jackson2JsonRedisSerializer
template.setValueSerializer(new Jackson2JsonRedisSerializer<Employee>(Employee.class));

反序列化的时候,需要指定Java类。这是因为序列化的时候,里面没有携带任何类名信息:

127.0.0.1:6379> get name
"{\"name\":\"downgoon\",\"age\":18}"
  • JacksonJsonRedisSerializer

至于JacksonJsonRedisSerializer从代码看,应该只是使用的是jackson1.X版本而已,跟Jackson2JsonRedisSerializer在序列化结果上没什么不一样。

顺便说一下

GenericJackson2JsonRedisSerializer还是一个PullRequest,编号 #145

We introduced GenericJackson2JsonRedisSerializer holding a preconfigured ObjectMapper which writes class type informations into the JSON structure. This enables polymorphic deserialization and allows RedisCacheManager to operate upon a RedisTemplate storing data in JSON format, which had until this only been possible using the JdkSerializer.

附录-3:四种常见的JSON序列化工具性能对比

参考资料

大致结论

  • 别再使用 json-lib 了,已经淘汰了。
  • Spring 官方默认使用 jackson 。jackson 主要分两个版本:1.x版本的包名是codehaus; Jackson从2.0开始改用新的包名fasterxml
  • Gson 是Google的,但是性能很差。
  • fastjson 是国产的,号称是最快的JSON解析工具。

附录-4:SQL on Redis

它可以基于Redis创建关系型的表结构,并且执行Insert和Select语句。直接运行:java -jar redisql-0.1.0-standalone.jar就可以。

⚠️ **GitHub.com Fallback** ⚠️