写作时间:2019-01-29
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA, MySQL 8.0.13

Redis 介绍

Redis是目前业界使用最广泛的内存数据存储。相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化。除此之外,Redis还提供一些类数据库的特性,比如事务,HA,主从库。可以说Redis兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。

安装 Redis Server环境

  1. 安装Redis
brew install redis
  1. 启动Redis服务器:
redis-server

启动成功日志:

20068:C 29 Jan 2019 09:35:17.742 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
20068:C 29 Jan 2019 09:35:17.743 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=20068, just started
20068:C 29 Jan 2019 09:35:17.743 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
20068:M 29 Jan 2019 09:35:17.744 * Increased maximum number of open files to 10032 (it was originally set to 256)._._                                                  _.-``__ ''-._                                             _.-``    `.  `_.  ''-._           Redis 5.0.3 (00000000/0) 64 bit.-`` .-```.  ```\/    _.,_ ''-._                                   (    '      ,       .-`  | `,    )     Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379|    `-._   `._    /     _.-'    |     PID: 20068`-._    `-._  `-./  _.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |           http://redis.io        `-._    `-._`-.__.-'_.-'    _.-'                                   |`-._`-._    `-.__.-'    _.-'_.-'|                                  |    `-._`-._        _.-'_.-'    |                                  `-._    `-._`-.__.-'_.-'    _.-'                                   `-._    `-.__.-'    _.-'                                       `-._        _.-'                                           `-.__.-'                                               20068:M 29 Jan 2019 09:35:17.747 # Server initialized
20068:M 29 Jan 2019 09:35:17.747 * DB loaded from disk: 0.000 seconds
20068:M 29 Jan 2019 09:35:17.747 * Ready to accept connections
  1. 启动Redis客户端
redis-cli

操作命令都在客户端显示

  1. 操作字符串
127.0.0.1:6379> set name zgpeace
OK
127.0.0.1:6379> get name
"zgpeace"
  1. Hashes 哈希值
127.0.0.1:6379> hmset student username zgpeace password ThePassword age 18
OK
127.0.0.1:6379> hgetall student
1) "username"
2) "zgpeace"
3) "password"
4) "ThePassword"
5) "age"
6) "18"
  1. Lists 列表
127.0.0.1:6379> lpush classmates JackMa
(integer) 1
127.0.0.1:6379> lpush classmates Lucy
(integer) 2
127.0.0.1:6379> lrange classmates 0 10
1) "Lucy"
2) "JackMa"
  1. Redis有序集合
127.0.0.1:6379> zadd db 1 redis
(integer) 1
127.0.0.1:6379> zadd db 2 mongodb
(integer) 1
127.0.0.1:6379> zadd db 3 mysql
(integer) 1
127.0.0.1:6379> zadd db 4 oracle
(integer) 1
127.0.0.1:6379> zrange db 0 10 withscores
1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "3"
7) "oracle"
8) "4"
  1. Redis发布订阅
    启动客户端一redis-cli
    监听两个channel,wechat和messages
subscribe wechat messages
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "wechat"
3) (integer) 1
1) "subscribe"
2) "messages"
3) (integer) 2

开启新的控制台,启动客户端二redis-cli, 并发布消息

127.0.0.1:6379> publish wechat "Hello"
(integer) 1

客户端一收到消息

1) "message"
2) "wechat"
3) "Hello"
  1. 更多命令参考Redis官网

工程建立

工程建立的时候,需要勾选NOSQL的Redis:

参照教程【SpringBoot 2.1 | 第一篇:构建第一个SpringBoot工程】新建一个Spring Boot项目,名字叫demoredis, 在目录src/main/java/resources 下找到配置文件application.properties,重命名为application.yml

配置文件

数据库连接信息配置src/main/resources/application.yml

spring:redis:host: localhost #服务器地址port: 6379      #服务器连接端口database: 1     #数据库索引(默认为0)password:       #服务器连接密码(默认为空)

测试访问

通过编写测试用例,设置Redis的key, value, 读取验证。
修改测试类com.zgpeace.demoredis.DemoredisApplicationTests

package com.zgpeace.demoredis;import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoredisApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void test() throws Exception {String key = "yourState";String value = "passion";stringRedisTemplate.opsForValue().set(key, value);Assert.assertEquals("passion", stringRedisTemplate.opsForValue().get(key));}@Testpublic void contextLoads() {}}

注意必须启动redis-server,否则连接失败,

Terminal启动redis-server

% redis-server

在方法左侧,点击单元测试按钮,验证通过。

关掉redis-server的方法,先找到正在运行的pid

$ ps aux | grep redis
MyUser  8821   0.0  0.0  2459704    596   ??  S    4:54PM   0:03.40 redis-server *:6379

或者用 ps -ef|grep redis
手动kill掉pid

$ kill -9 8821

操作对象

Redis存储String类型,也可以存储对象,使用类似RedisTemplate<String, City>来初始化并进行操作。Spring Boot并不支持直接使用,需要自己实现RedisSerializer接口来对传入对象进行序列化和反序列化,下面通过一个实例来完成对象的读写操作。

修改pom.xml Redis的依赖

Spring Boot 2.0中spring-boot-starter-data-redis默认使用Lettuce方式替代了Jedis。使用Jedis的话先排除掉Lettuce的依赖,然后手动引入Jedis的依赖。
pom.xml 依赖项spring-boot-starter-data-redis修改

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>

创建Bean对象

对象需要在Redis中的语言跟Java语言之间转换,所以需要序列化
com.zgpeace.demoredis.bean.City

package com.zgpeace.demoredis.bean;import java.io.Serializable;public class City implements Serializable {private static final long serialVersionUID = -1L;private String name;private String state;private String country;public City(String name, String state, String country) {this.name = name;this.state = state;this.country = country;}// getter setter ..
}

通用对象序列化类

com.zgpeace.demoredis.dao.RedisObjedctSerializer

package com.zgpeace.demoredis.dao;import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;public class RedisObjedctSerializer implements RedisSerializer<Object> {private Converter<Object, byte[]> serailizer = new SerializingConverter();private Converter<byte[], Object> deserializer = new DeserializingConverter();static final byte[] EMPTY_ARRAY = new byte[0];@Overridepublic byte[] serialize(Object o) throws SerializationException {if (o == null) {return EMPTY_ARRAY;}try {return serailizer.convert(o);} catch (Exception ex) {return EMPTY_ARRAY;}}@Overridepublic Object deserialize(byte[] bytes) throws SerializationException {if (isEmpty(bytes)) {return null;}try {return deserializer.convert(bytes);} catch (Exception ex) {throw new SerializationException("Connot deserialize", ex);}}private boolean isEmpty(byte[] data) {return (data == null || data.length == 0);}
}

配置针对City的RedisTemplate实例

com.zgpeace.demoredis.dao.CityRedisConfig

package com.zgpeace.demoredis.dao;import com.zgpeace.demoredis.bean.City;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class CityRedisConfig {@BeanRedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory();}@Beanpublic RedisTemplate<String, City> redisTemplate(RedisConnectionFactory jedisConnectionFactory) {RedisTemplate<String, City> template = new RedisTemplate<String, City>();template.setConnectionFactory(jedisConnectionFactory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new RedisObjedctSerializer());return template;}
}

添加新的测试用例

com.zgpeace.demoredis.DemoredisApplicationTests

@Testpublic void testRedisCity() throws Exception {City city = new City("San Jose", "California", "America");cityRedisTemplate.opsForValue().set(city.getName(), city);city = new City("Vancouver", "British Columbi", "Canada");cityRedisTemplate.opsForValue().set(city.getName(), city);Assert.assertEquals("California", cityRedisTemplate.opsForValue().get("San Jose").getState());Assert.assertEquals("Canada", cityRedisTemplate.opsForValue().get("Vancouver").getCountry());}

监听消息

接收消息对象

消息应用都有消息接收方,消息发送方。创建一个消息接收方,实现打印接收到的消息。

com.zgpeace.demoredis.bean.Receiver

package com.zgpeace.demoredis.bean;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import java.util.concurrent.CountDownLatch;public class Receiver {private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);private CountDownLatch latch;@Autowiredpublic Receiver(CountDownLatch latch) {this.latch = latch;}public void receiveMessage(String message) {LOGGER.info("Received <" + message + ">");latch.countDown();}}

消息接收对象是个POJO,定义一个方法去接收消息。一旦注册对象为监听消息,可以取任何方法的名字。receiveMessage

注册一个监听者,并发送消息

Spring Data Redis 提供了所有组件在Redis之间发送和接收消息,主要配置一下信息:

  1. 连接工厂connection factory
  2. 消息监听容器message listener container
  3. Redis template

Redis template发送消息,注册的接收消息对象会接收消息。连接工厂驱动前面两者连接到Redis server。

例子连接工厂用Spring Boot的RedisConnectionFactory,JedisConnectionFactory的一个实例。 连接工厂注入到消息监听对象和Redis template.

com.zgpeace.demoredis.DemoredisApplication

package com.zgpeace.demoredis;import com.zgpeace.demoredis.bean.Receiver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;import java.util.concurrent.CountDownLatch;@SpringBootApplication
public class DemoredisApplication {private static final Logger LOGGER= LoggerFactory.getLogger(DemoredisApplication.class);@BeanRedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,MessageListenerAdapter listenerAdapter) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.addMessageListener(listenerAdapter, new PatternTopic("chat"));return container;}@BeanMessageListenerAdapter listenerAdapter(Receiver receiver) {return new MessageListenerAdapter(receiver, "receiveMessage");}@BeanReceiver receiver(CountDownLatch latch) {return new Receiver(latch);}@BeanCountDownLatch latch() {return new CountDownLatch(1);}@BeanStringRedisTemplate template(RedisConnectionFactory connectionFactory) {return new StringRedisTemplate(connectionFactory);}public static void main(String[] args) throws InterruptedException {ApplicationContext ctx = SpringApplication.run(DemoredisApplication.class, args);StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);CountDownLatch latch = ctx.getBean(CountDownLatch.class);LOGGER.info("Sending message...");template.convertAndSend("chat", "Hello from Redis!");latch.await();//System.exit(0);}}

Terminal启动Redis server

% redis-server

运行结果

2019-01-31 09:49:34.007  INFO 50210 --- [           main] c.z.demoredis.DemoredisApplication       : Started DemoredisApplication in 2.073 seconds (JVM running for 2.625)
2019-01-31 09:49:34.008  INFO 50210 --- [           main] c.z.demoredis.DemoredisApplication       : Sending message...
2019-01-31 09:49:34.020  INFO 50210 --- [    container-2] com.zgpeace.demoredis.bean.Receiver      : Received <Hello from Redis!>

程序解析:
方法 listenerAdapter 注册为消息监听,并监听"chat" Topic. 因为接收方为POJO,所以需要 addMessageListener 把接收到的消息传递过去。 listenerAdapter() 实例配置去调用接收方方法 receiveMessage()

连接工厂和连接容器使应用可以监听消息。用Redis template去发送消息,StringRedisTemplate是实现了RedisTemplate, 针对Redis中的keys和values都是String。

main() 方法创建了Spring application context,context然后启动了监听容器。 StringRedisTemplate 在topic为"chat"发送消息"Hello from Redis!", 接收方打印消息。

分布式Session

分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一,

Spring Session官方说明
Spring Session provides an API and implementations for managing a user’s session information.

pom.xml引入依赖

<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
</dependency>

Session配置类

com.zgpeace.demoredis.dao.SessionConfig

package com.zgpeace.demoredis.dao;import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {}

maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Boot的server.session.timeout属性不再生效

测试方法

com.zgpeace.demoredis.web.SessionController

package com.zgpeace.demoredis.web;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;
import java.util.UUID;@RestController
public class SessionController {@RequestMapping(value = "/uid", method = RequestMethod.GET)public String uid(HttpSession session){UUID uid = (UUID)session.getAttribute("uid");if (uid == null) {uid = UUID.randomUUID();}session.setAttribute("uid", uid);return session.getId();}
}

Terminal调用接口

% curl http://localhost:8080/uid
f2b87954-2d97-4029-909f-636dfe584d9a%   

Terminal开启Redis client,查看生产的sessionId, 和过期时间

% redis-cli
127.0.0.1:6379> keys '*sessions*'
1) "spring:session:sessions:expires:f2b87954-2d97-4029-909f-636dfe584d9a"
2) "spring:session:sessions:f2b87954-2d97-4029-909f-636dfe584d9a"

如何在两台或者多台中共享session
其实就是按照上面的步骤在另一个项目中再次配置一次,
启动后自动就进行了session共享。

总结

恭喜你!学会了操作Redis字符串,对象,以及监听消息。
代码地址:https://github.com/zgpeace/Spring-Boot2.1/tree/master/db/demoredis

参考

https://blog.csdn.net/forezp/article/details/70991675
https://blog.csdn.net/forezp/article/details/61471712
https://spring.io/guides/gs/messaging-redis/
https://www.cnblogs.com/ityouknow/p/5748830.html
http://blog.didispace.com/springbootredis/
https://www.concretepage.com/questions/599

易筋SpringBoot 2.1 | 第九篇:SpringBoot使用Redis内存数据库相关推荐

  1. SpringBoot (一) :入门篇

    SpringBoot (一) :入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使 ...

  2. SpringBoot系统整理|基础篇|黑马视频

    写在前面:很早之前看了狂神的springboot快速入门,后来发现还是有很多开发知识点需要补充学习.乘着假期,将基础篇.运维实用篇.开发实用篇.原理篇一口气学习巩固,再次记录下学习笔记.系列笔记在sp ...

  3. SpringBoot运维实用篇

    SpringBoot2零基础到项目实战-基础篇 SpringBoot运维实用篇 从此刻开始,咱们就要进入到实用篇的学习了.实用篇是在基础篇的根基之上,补全SpringBoot的知识图谱.比如在基础篇中 ...

  4. Java学习篇——SpringBoot

    1. 关于Spring Boot Spring Boot框架主要解决了创建工程后需要进行繁琐的配置的问题,是一个"开箱即用"的框架,其核心思想是"约定大于配置" ...

  5. SpringBoot第二十五篇:2小时学会springboot

    一.什么是spring boot Takes an opinionated view of building production-ready Spring applications. Spring ...

  6. SpringBoot非官方教程 | 第一篇:构建第一个SpringBoot工程

    转载请标明出处:  http://blog.csdn.net/forezp/article/details/70341651  本文出自方志朋的博客 简介 spring boot 它的设计目的就是为例 ...

  7. SpringBoot 就这一篇全搞定

    一.Hello Spring Boot 1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 微服务 ...

  8. Java高级篇-----Springboot框架

    目录 1.什么是Springboot 2.Springboot框架的特点 3.创建Springboot工程 3.1.准备条件 3.2. 创建springboot的方式有两种 3.2.1. 使用idea ...

  9. springboot学习笔记1:springboot入门

    1.什么是springboot springboot是spring生态圈的一个轻量级的框架,换句话说springboot就是spring,是spring的一个衍生版本. 使用spring框架,项目搭建 ...

  10. springboot maven打包jar运行,springboot mybatis druid,demo源码

    注:本文介绍的mysql版本是5.x ,如果mysql升级到8 有几个地方需要改动 https://blog.csdn.net/a704397849/article/details/108396563 ...

最新文章

  1. 《MySQL CAST与CONVERT
  2. mysql 查看版本
  3. python 3d绘图 范围_python – 在3D绘图中绘制所有三个轴上的分布轮廓
  4. 快速理解平衡二叉树、B-tree、B+tree、B*tree
  5. html怎样同框架页面内跳转,使用iframe框架时,实现子页面内跳转到整个页面,而不是在子页面内跳转...
  6. HDU1285 确定名次 拓扑排序
  7. 计算机网络之数据链路层:1、概述
  8. c语言tcp读写二进制文件,通过TCP/IP连接发送二进制文件
  9. 红黑树真的没你想的那么难!
  10. 阿里巴巴举办全球数学竞赛 助力基础科学杰出人才培养
  11. 笑出腹肌的程序猿搞笑趣图
  12. 调试技巧之调用堆栈 - Call stack
  13. 软件工作的量化考核有办法吗?
  14. 微机——微型计算机系统组成及工作原理
  15. Win7一键还原系统的方法【系统天地】
  16. ubuntu更新源出现错误
  17. 国产麒麟系统为何饱受争议?
  18. 酷开电视能装鸿蒙吗,最新酷开系统电视安装第三方应用教程【全能版】
  19. 内存泄漏检测工具asan
  20. linux如何打印脚本运行进度,linux-如何在使用systemd引导期间最后运行并打印我的脚本输出?...

热门文章

  1. 5二代配什么主板最好_新教育5:父母什么时间陪伴孩子最好
  2. 解决SpringBoot集成Redis出现RedisConnectionException: Unable to connect to 192.168.64.100:6379
  3. Caliburn.Micro入门
  4. 震撼!寒冬腊月里惊现多台历途外墙清洗机器人
  5. Confluence 6 配置数字格式
  6. 11.30 iptables filter表案例 iptables nat表应用
  7. C#中用ToString方法格式化时间
  8. 通过HttpURLConnection模拟post表单提交
  9. 敏捷个人A1组第三次练习讨论 你是如何管理你的精力的?
  10. SQL2005企业版详细部署(一)