关于 Spring For All

关于 Spring For All

Spring For All 的一切
最新动态

最新动态

Spring 5 会是咋样呢
Spring Boot

Spring Boot

快速构建并运行 Spring 应用程序
Spring Cloud

Spring Cloud

分布式系统的一套工具,可用于构建微服务
Spring Framework

Spring Framework

提供依赖注入、事务、Web应用、数据访问等模块
Spring Data

Spring Data

提供一致性数据访问模块
Spring Security

Spring Security

提供应用身份验证和授权支持
Spring Batch

Spring Batch

提供高容批处理操作模块
Spring AMQP

Spring AMQP

基于AMQP消息解决方案
Micro Service Arch.

Micro Service Arch.

微服务架构相关
开源项目及视频教程

开源项目及视频教程

做中国最好的 Spring 开源项目及视频教程
小马哥专栏

小马哥专栏

阿里技术布道者,专注 Spring Boot 及微服务

web-fragment在spring boot中无法生效

回复

Spring Bootstring2020 发起了问题 • 1 人关注 • 0 个回复 • 16 次浏览 • 5 小时前 • 来自相关话题

spring boot 启动找不到类:com.sun.tools.javac.util.List

回复

Spring Bootlaien 发起了问题 • 1 人关注 • 0 个回复 • 32 次浏览 • 15 小时前 • 来自相关话题

spring cloud config post /bus/refresh只有一个端口刷新

回复

Spring Cloudwuhao939 发起了问题 • 1 人关注 • 0 个回复 • 63 次浏览 • 1 天前 • 来自相关话题

在windows本机安装的elasticsearch服务,启动项目连接会报下面的错,

回复

最新动态zhoun 发起了问题 • 1 人关注 • 0 个回复 • 30 次浏览 • 1 天前 • 来自相关话题

从spring转移到springboot后jpa报错Illegal mix of collations for operation 'case'

回复

Spring Datajkgeekjk 发起了问题 • 1 人关注 • 0 个回复 • 33 次浏览 • 1 天前 • 来自相关话题

「转」Spring Cloud在国内中小型公司能用起来吗?

Spring Cloud泥瓦匠BYSocket 发表了文章 • 0 个评论 • 640 次浏览 • 1 天前 • 来自相关话题

今天吃完饭休息的时候瞎逛知乎,突然看到这个一个问题Spring Cloud在国内中小型公司能用起来吗?,吸引了我的注意。仔细的看了题主的问题,发现这是一个好问题,题主经过了一番思考,并且用图形全面的将自己的疑问表达了出来,作为一个研究并使用Spring Boot和Spring Cloud近两年的程序员,看的我手痒痒不答不快呀。

好问题

好问题必须配认真的回答,仔细的看了题主的问题,发现这个问题非常具有代表性,可能是广大网友想使用Spring Cloud却又对Spring Cloud不太了解的共同想法,题主对Spring Cloud使用的方方面面都进行过了思考,包括市场,学习、前后端、测试、配置、部署、开发以及运维,下面就是题主原本的问题:

想在公司推广Spring Cloud,但我对这项技术还缺乏了解,画了一张脑图,总结了种种问题。






微服务是这样一个结构吗?
前端或二方 - > ng集群 -> zuul集群 -> eureka-server集群 -> service provider集群(二方指其他业务部门)

想要明白这个问题,首先需要知道什么是Spring Boot,什么是Spring Cloud,以及两者之间有什么关系?

什么是Spring Boot

Spring Boot简化了基于Spring的应用开发,通过少量的代码就能创建一个独立的、产品级别的Spring应用。 Spring Boot为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数Spring Boot应用只需要很少的Spring配置。

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是Spring Boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,Spring Boot整合了所有的框架(不知道这样比喻是否合适)。

Spring Boot的核心思想就是约定大于配置,一切自动完成。采用Spring Boot可以大大的简化你的开发模式,所有你想集成的常用框架,它都有对应的组件支持。如果你对Spring Boot完全不了解,可以参考我的这篇文章:Springboot(一):入门篇

什么是Spring Cloud

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

微服务是可以独立部署、水平扩展、独立访问(或者有独立的数据库)的服务单元,Spring Cloud就是这些微服务的大管家,采用了微服务这种架构之后,项目的数量会非常多,Spring Cloud做为大管家就需要提供各种方案来维护整个生态。

Spring Cloud就是一套分布式服务治理的框架,既然它是一套服务治理的框架,那么它本身不会提供具体功能性的操作,更专注于服务之间的通讯、熔断、监控等。因此就需要很多的组件来支持一套功能,如果你对Spring Cloud组件不是特别了解的话,可以参考我的这篇文章:springcloud(一):大话Spring Cloud

Spring Boot和Spring Cloud的关系

Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,可以不基于Spring Boot吗?不可以。

Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。

Spring -> Spring Boot > Spring Cloud 这样的关系。

回答

以下为我在知乎的回答。

首先楼主问的这些问题都挺好的,算是经过了自己的一番思考,我恰好经历了你所说的中小公司,且都使用Spring Cloud并且已经投产上线。第一家公司技术开发人员15人左右,项目实例 30多,第二家公司开发人员100人左右,项目实例达160多。

实话说Spring Boot、Spring Cloud仍在高速发展,技术生态不断的完善和扩张,不免也会有一些小的bug,但对于中小公司的使用来将,完全可以忽略,基本都可以找到解决方案,接下来回到你的问题。

1、市场

据我所知有很多知名互联网公司都已经使用了Spring Cloud,比如阿里、美团但都是小规模,没有像我经历的这俩家公司,业务线全部拥抱Spring Cloud;另外Spring Cloud并不是一套高深的技术,普通的Java程序员经过一到俩个月完全就可以上手,但前期需要一个比较精通人的来带队。

后记,找阿里的小马哥确认了下,阿里也在大规模使用。

2、学习

有很多种方式,现在Spring Cloud越来越火的情况下,各种资源也越来越丰富,查看官方文档和示例,现在很多优秀的博客在写spirng cloud的相关教程,我这里收集了一些Spring Boot和Spring Cloud的相关资源可以参考,找到博客也就找到人和组织了。

Spring Boot学习资料汇总:
Spring Cloud学习资料汇总 :

3、前后职责划分

其实这个问题是每个系统架构都应该考虑的问题,Spring Cloud只是后端服务治理的一套框架,唯一和前端有关系的是thymeleaf,Spring推荐使用它做模板引擎。一般情况下,前端app或者网页通过zuul来调用后端的服务,如果包含静态资源也可以使用nginx做一下代理转发。

4、测试

Spring-boot-starter-test支持项目中各层方法的测试,也支持controller层的各种属性。所以一般测试的步奏是这样,首先开发人员覆盖自己的所有方法,然后测试微服务内所有对外接口保证微服务内的正确性,再进行微服务之间集成测试,最后交付测试。

5、配置

session共享有很多种方式,比如使用tomcat sesion共享机制,但我比较推荐使用redis缓存来做session共享。完全可以分批引入,我在上一家公司就是分批过渡上线,新旧项目通过zuul进行交互,分批引入的时候,最好是新业务线先使用Spring Cloud,老业务做过渡,当完全掌握之后在全部替换。如果只是请求转发,zuul的性能不一定比nginx低,但是如果涉及到静态资源,还是建议在前端使用nginx做一下代理。另外Spring Cloud有配置中心,可以非常灵活的做所有配置的事情。

6、部署

多环境不同配置,Spring Boot最擅长做这个事情了,使用不同的配置文件来配置不同环境的参数,在服务启动的时候指明某个配置文件即可,例如:java -jar app.jar --spring.profiles.active=dev就是启动测试环境的配置文件;Spring Cloud 没有提供发布平台,因为jenkins已经足够完善了,推荐使用jenkins来部署Spring Boot项目,会省非常多的事情;灰度暂时不支持,可能需要自己来做,如果有多个实例,可以一个一个来更新;支持混合部署,一台机子部署多个是常见的事情。

7、开发

你说的包含html接口就是前端页面吧,Spring Boot可以支持,但其实也是Spring Mvc在做这个事情,Spring Cloud只做服务治理,其它具体的功能都是集成了各种框架来解决而已;excel报表可以,其实除过swing项目外,其它Java项目都可以想象;Spring Cloud和老项目可以混合使用,通过zuul来支持。是否支持callback,可以通过MQ来实现,还是强调Spring Cloud只是服务治理。

8、运维

Turbine、zipkin可以用来做熔断和性能监控;动态上下线某个节点可以通过jenkins来实现;provider下线后,会有其它相同的实例来提供服务,Eureka会间隔一段时间来检测服务的可用性;不同节点配置不同的流量权值目前还不支持。注册中心必须做高可用集群,注册中心挂掉之后,服务实例会全部停止。

总结,中小企业是否能用的起来Spring Cloud,完全取决于自己公司的环境,如果是一个技术活跃型的团队就大胆的去尝试吧,目前Spring Cloud是所有微服务治理中最优秀的方案,也是一个趋势,未来一两年可能就会像Spring一样流行,早接触早学习岂不更好。

希望能解答了你的疑问。

Spring Cloud 架构

我们从整体来看一下Spring Cloud主要的组件,以及它的访问流程





 
1、外部或者内部的非Spring Cloud项目都统一通过API网关(Zuul)来访问内部服务.
2、网关接收到请求后,从注册中心(Eureka)获取可用服务
3、由Ribbon进行均衡负载后,分发到后端的具体实例
4、微服务之间通过Feign进行通信处理业务
5、Hystrix负责处理服务超时熔断
6、Turbine监控服务间的调用和熔断相关指标

图中没有画出配置中心,配置中心管理各微服务不同环境下的配置文件。

以上就是一个完整的Spring Cloud生态图。 查看全部
今天吃完饭休息的时候瞎逛知乎,突然看到这个一个问题Spring Cloud在国内中小型公司能用起来吗?,吸引了我的注意。仔细的看了题主的问题,发现这是一个好问题,题主经过了一番思考,并且用图形全面的将自己的疑问表达了出来,作为一个研究并使用Spring Boot和Spring Cloud近两年的程序员,看的我手痒痒不答不快呀。

好问题

好问题必须配认真的回答,仔细的看了题主的问题,发现这个问题非常具有代表性,可能是广大网友想使用Spring Cloud却又对Spring Cloud不太了解的共同想法,题主对Spring Cloud使用的方方面面都进行过了思考,包括市场,学习、前后端、测试、配置、部署、开发以及运维,下面就是题主原本的问题:

想在公司推广Spring Cloud,但我对这项技术还缺乏了解,画了一张脑图,总结了种种问题。

1.png


微服务是这样一个结构吗?
前端或二方 - > ng集群 -> zuul集群 -> eureka-server集群 -> service provider集群(二方指其他业务部门)

想要明白这个问题,首先需要知道什么是Spring Boot,什么是Spring Cloud,以及两者之间有什么关系?

什么是Spring Boot

Spring Boot简化了基于Spring的应用开发,通过少量的代码就能创建一个独立的、产品级别的Spring应用。 Spring Boot为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数Spring Boot应用只需要很少的Spring配置。

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是Spring Boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,Spring Boot整合了所有的框架(不知道这样比喻是否合适)。

Spring Boot的核心思想就是约定大于配置,一切自动完成。采用Spring Boot可以大大的简化你的开发模式,所有你想集成的常用框架,它都有对应的组件支持。如果你对Spring Boot完全不了解,可以参考我的这篇文章:Springboot(一):入门篇

什么是Spring Cloud

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

微服务是可以独立部署、水平扩展、独立访问(或者有独立的数据库)的服务单元,Spring Cloud就是这些微服务的大管家,采用了微服务这种架构之后,项目的数量会非常多,Spring Cloud做为大管家就需要提供各种方案来维护整个生态。

Spring Cloud就是一套分布式服务治理的框架,既然它是一套服务治理的框架,那么它本身不会提供具体功能性的操作,更专注于服务之间的通讯、熔断、监控等。因此就需要很多的组件来支持一套功能,如果你对Spring Cloud组件不是特别了解的话,可以参考我的这篇文章:springcloud(一):大话Spring Cloud

Spring Boot和Spring Cloud的关系

Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,可以不基于Spring Boot吗?不可以。

Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。

Spring -> Spring Boot > Spring Cloud 这样的关系。

回答

以下为我在知乎的回答。

首先楼主问的这些问题都挺好的,算是经过了自己的一番思考,我恰好经历了你所说的中小公司,且都使用Spring Cloud并且已经投产上线。第一家公司技术开发人员15人左右,项目实例 30多,第二家公司开发人员100人左右,项目实例达160多。

实话说Spring Boot、Spring Cloud仍在高速发展,技术生态不断的完善和扩张,不免也会有一些小的bug,但对于中小公司的使用来将,完全可以忽略,基本都可以找到解决方案,接下来回到你的问题。

1、市场

据我所知有很多知名互联网公司都已经使用了Spring Cloud,比如阿里、美团但都是小规模,没有像我经历的这俩家公司,业务线全部拥抱Spring Cloud;另外Spring Cloud并不是一套高深的技术,普通的Java程序员经过一到俩个月完全就可以上手,但前期需要一个比较精通人的来带队。

后记,找阿里的小马哥确认了下,阿里也在大规模使用。

2、学习

有很多种方式,现在Spring Cloud越来越火的情况下,各种资源也越来越丰富,查看官方文档和示例,现在很多优秀的博客在写spirng cloud的相关教程,我这里收集了一些Spring Boot和Spring Cloud的相关资源可以参考,找到博客也就找到人和组织了。

Spring Boot学习资料汇总:
Spring Cloud学习资料汇总 :

3、前后职责划分

其实这个问题是每个系统架构都应该考虑的问题,Spring Cloud只是后端服务治理的一套框架,唯一和前端有关系的是thymeleaf,Spring推荐使用它做模板引擎。一般情况下,前端app或者网页通过zuul来调用后端的服务,如果包含静态资源也可以使用nginx做一下代理转发。

4、测试

Spring-boot-starter-test支持项目中各层方法的测试,也支持controller层的各种属性。所以一般测试的步奏是这样,首先开发人员覆盖自己的所有方法,然后测试微服务内所有对外接口保证微服务内的正确性,再进行微服务之间集成测试,最后交付测试。

5、配置

session共享有很多种方式,比如使用tomcat sesion共享机制,但我比较推荐使用redis缓存来做session共享。完全可以分批引入,我在上一家公司就是分批过渡上线,新旧项目通过zuul进行交互,分批引入的时候,最好是新业务线先使用Spring Cloud,老业务做过渡,当完全掌握之后在全部替换。如果只是请求转发,zuul的性能不一定比nginx低,但是如果涉及到静态资源,还是建议在前端使用nginx做一下代理。另外Spring Cloud有配置中心,可以非常灵活的做所有配置的事情。

6、部署

多环境不同配置,Spring Boot最擅长做这个事情了,使用不同的配置文件来配置不同环境的参数,在服务启动的时候指明某个配置文件即可,例如:java -jar app.jar --spring.profiles.active=dev就是启动测试环境的配置文件;Spring Cloud 没有提供发布平台,因为jenkins已经足够完善了,推荐使用jenkins来部署Spring Boot项目,会省非常多的事情;灰度暂时不支持,可能需要自己来做,如果有多个实例,可以一个一个来更新;支持混合部署,一台机子部署多个是常见的事情。

7、开发

你说的包含html接口就是前端页面吧,Spring Boot可以支持,但其实也是Spring Mvc在做这个事情,Spring Cloud只做服务治理,其它具体的功能都是集成了各种框架来解决而已;excel报表可以,其实除过swing项目外,其它Java项目都可以想象;Spring Cloud和老项目可以混合使用,通过zuul来支持。是否支持callback,可以通过MQ来实现,还是强调Spring Cloud只是服务治理。

8、运维

Turbine、zipkin可以用来做熔断和性能监控;动态上下线某个节点可以通过jenkins来实现;provider下线后,会有其它相同的实例来提供服务,Eureka会间隔一段时间来检测服务的可用性;不同节点配置不同的流量权值目前还不支持。注册中心必须做高可用集群,注册中心挂掉之后,服务实例会全部停止。

总结,中小企业是否能用的起来Spring Cloud,完全取决于自己公司的环境,如果是一个技术活跃型的团队就大胆的去尝试吧,目前Spring Cloud是所有微服务治理中最优秀的方案,也是一个趋势,未来一两年可能就会像Spring一样流行,早接触早学习岂不更好。

希望能解答了你的疑问。

Spring Cloud 架构

我们从整体来看一下Spring Cloud主要的组件,以及它的访问流程

2.png

 
1、外部或者内部的非Spring Cloud项目都统一通过API网关(Zuul)来访问内部服务.
2、网关接收到请求后,从注册中心(Eureka)获取可用服务
3、由Ribbon进行均衡负载后,分发到后端的具体实例
4、微服务之间通过Feign进行通信处理业务
5、Hystrix负责处理服务超时熔断
6、Turbine监控服务间的调用和熔断相关指标

图中没有画出配置中心,配置中心管理各微服务不同环境下的配置文件。

以上就是一个完整的Spring Cloud生态图。

Spring 官方周报9.19

最新动态maskwang520 发表了文章 • 0 个评论 • 760 次浏览 • 3 天前 • 来自相关话题

嗨,亲爱的Spring粉丝们!欢迎来到本周Spring周报的另一期,这周我一直在访问微软的Spring和Cloud Foundry团队(这次在华盛顿州雷德蒙德市),然后到加利福尼亚州的旧金山和德克萨斯州的圣安东尼奥去访问一些客户。所以,让我们看看这周有什么新的内容!

1: 我喜欢这个Pivotal 工程师发表的一篇名为《我们如何将我们托管的Cloud Foundry的多租户安装Pivotal Web Services转移到CredHub》的文章。 CredHub旨在为BOSH管理的环境存储密码,密钥,证书和其他敏感信息。

http://engineering.pivotal.io/post/credhub-on-pws/

注意: BOSH 是一款供我们用来将 Cloud Foundry 组件部署到分布式节点上的工具。BOSH的详细介绍请参考链接:https://github.com/cloudfoundr ... sh.md

2: Spring Boot大牛Brian Clozel刚刚发布了Spring Boot 1.5.7的更新,其中包括许多修复,依赖关系更新和改进。

https://spring.io/blog/2017/09 ... e-now

3: Spring集成领导和消息大牛Gary Russell刚刚发布了Spring AMQP 2.0 RC1。自上一个里程碑以来,RC1增加了一些小的改进。加里还发布,现在也可以使用1.7.4和1.6.11的维护版本。

https://spring.io/blog/2017/09 ... lable

4: 没有什么东西十全十美,加里也发布了Spring for Apache Kafka 2.0和1.3的候选版本。这两个版本都支持Kafka 0.11.x.x客户端,同时支持Spring Framework 4.3。新版本包括对Spring Framework事务同步的支持,KafkaAdmin对象以及AckMode.RECORD的正确处理。此外,这些版本还包括几个错误修复。

https://spring.io/blog/2017/09 ... lable

5: Spring Integration贡献者Artem Bilan刚刚发布了Spring Integration 5. M7和4.3.12。新版本将响应式Spring Webflux适配器提取到单独的模块中,spring-integration-webflux。它还支持在用于协议的消息的有效负载中编码消息头,例如AWS Kinesis,Apache Kafka的早期版本和TCP / IP - 不支持本机头部的概念。

https://spring.io/blog/2017/09 ... lable

6: Spring整合领导Gary Russell刚刚发布推出Spring Cloud Stream Ditmars / 1.3 RC1。新支持使用Kafka Streams KStream引用作为@StreamListener方法的输入和输出。换句话说,您可以使用Spring Cloud Stream连接应用程序,声明所有的绑定等等,就像平常一样,然后编写用于交互查询的Kafka Streams的消息代码。

https://spring.io/blog/2017/09 ... ement

7: Spring Boot提交者StéphaneNicoll刚刚发布了Spring Boot 2.0.0.M4。此版本是第一个包含新的网络运行时无关的致动器端点以及一系列更改以简化安全配置。

https://spring.io/blog/2017/09 ... e-now

8: Spring Session 领导 Rob Winch刚刚发布了Spring Session 2.0.0.M4。此版本简化了基于Spring WebFlux的应用程序的配置。它还支持会话ID解析策略。

https://spring.io/blog/2017/09 ... -0-m4

9: Spring大牛Greg Turnquist刚刚发布了Spring Session MongoDB 2.0.0.M3。新版本基于Spring Session 2.0.0.M4,Spring Data Kay RC3,Reactor Bismuth-M4和Spring Framework 5.0.0.RC4。如果你使用Spring Boot 2.0的spring-boot-starter-data-mongodb-reactive,那么你只需要使用@EnableMongoWebSession启用!

https://spring.io/blog/2017/09 ... eased

10: Spring Security主管Rob Winch刚刚发布了Spring Security 5.0.0.M4。此版本新增了许多新功能,包括OAUth 2 / OpenID Connect支持和Spring WebFlux的响应集成。

https://spring.io/blog/2017/09 ... eased

11: Spring web 专家 Rossen Stoyanchev刚刚发布Spring Web Flow 2.4.6。该版本包含影响默认绑定的安全修补补丁。

https://spring.io/blog/2017/09 ... eased

12: Spring Cloud Data Flow贡献者Eric Bottard刚刚发布了Spring Shell 2.0.M1! Spring Shell项目表示一个命令组件模型,以支持开发自定义shell。 Spring Shell是支持Spring Cloud Data Flow shell的项目。这个新版本有很多提供,包括位置参数,使用Spring转换API,JLine 3支持,与bean验证API的集成,多行命令等等。

https://spring.io/blog/2017/09 ... 2-0m1

13: 西蒙·巴斯利刚刚发布了Reactor 3.1 RC1。这是迈向Spring Framework 5.0的一大步。强烈建议用户抓住这些机会,尽快尝试!

https://spring.io/blog/2017/09 ... e-3-1

14: Spring Cloud Data Flow贡献者Glenn Renfro发布推出1.3.0.M2版本,包含了很多新功能。它包括支持批处理、任务和流操作的更新的Dashboard / Flo集成、 fan-in和 fan-out支持、应用程序注册表和Maven更新策略、安全更新、直接命名渠道、shell改进等等。

https://spring.io/blog/2017/09 ... eased

15: Spring Boot大牛Madhura Bhave表示Spring Boot 2.0.0.M4改进了与Spring Security的集成方式;这绝对值得一读!

https://spring.io/blog/2017/09 ... -0-m4

16:Tom Hombergs把Spring Boot和RabbitMQ应用在微服务消息方面做了一个很好的改进。

https://reflectoring.io/event- ... itmq/

17:另一个友好的提醒,我会在以 Reactive Spring为主题 Reactive峰会上发表演讲,希望能在那里见到你!

https://www.youtube.com/watch?v=GzebF1iKZPU

18:一个友好的提醒,我将在12月以Spring Boot和Kotlin为主题的Kotlin 大会上发表演讲,我很想在那里见到你。

https://kotlinconf.com/speakers/#speaker=josh-long

19:Damith Ganegoda在这篇博文对Spring Boot和Angular 4做了很好的介绍。

http://mydevgeek.com/angular-4 ... rt-1/

20:Ordina JWorks的博客非常详细的介绍了新的Micrometer monitoring abstraction(它也集成在Spring Boot 2.0.0.M4中)。

https://ordina-jworks.github.i ... .html

21:Atomist的Clay McCoy让你看到Atomist如何帮助您在Spring Boot应用程序中捕获REST API更改。

https://the-composition.com/ch ... 2301f

22: 我喜欢这篇发布在ZDNet上的Greenplum的文章(大数据是最好的保密)

http://www.zdnet.com/google-am ... king/

23:说到Spring Boot贡献者,以及令人赞叹的Madhura BHave,她还将对Spring Boot 2.0中的JavaZone 2017演示文稿进行了深入的介绍。

https://speakerdeck.com/mbhave ... dot-0

24:我喜欢Dan的帖子,在这其中特别介绍了超媒体和HATEOAS的概念,并且使用了一些基于Spring Boot和Spring HATEOAS的示例代码。

https://lankydanblog.com/2017/ ... /amp/

25:Facebook和Github刚刚发布推出了Atom IDE - 一个支持Java的新型IDE。我没有机会尝试,但它看起来很有趣。我不知道它是否会支持Maven或Gradle..

https://github.com/blog/2430-introducing-atom-ide 查看全部
嗨,亲爱的Spring粉丝们!欢迎来到本周Spring周报的另一期,这周我一直在访问微软的Spring和Cloud Foundry团队(这次在华盛顿州雷德蒙德市),然后到加利福尼亚州的旧金山和德克萨斯州的圣安东尼奥去访问一些客户。所以,让我们看看这周有什么新的内容!

1: 我喜欢这个Pivotal 工程师发表的一篇名为《我们如何将我们托管的Cloud Foundry的多租户安装Pivotal Web Services转移到CredHub》的文章。 CredHub旨在为BOSH管理的环境存储密码,密钥,证书和其他敏感信息。

http://engineering.pivotal.io/post/credhub-on-pws/

注意: BOSH 是一款供我们用来将 Cloud Foundry 组件部署到分布式节点上的工具。BOSH的详细介绍请参考链接:https://github.com/cloudfoundr ... sh.md

2: Spring Boot大牛Brian Clozel刚刚发布了Spring Boot 1.5.7的更新,其中包括许多修复,依赖关系更新和改进。

https://spring.io/blog/2017/09 ... e-now

3: Spring集成领导和消息大牛Gary Russell刚刚发布了Spring AMQP 2.0 RC1。自上一个里程碑以来,RC1增加了一些小的改进。加里还发布,现在也可以使用1.7.4和1.6.11的维护版本。

https://spring.io/blog/2017/09 ... lable

4: 没有什么东西十全十美,加里也发布了Spring for Apache Kafka 2.0和1.3的候选版本。这两个版本都支持Kafka 0.11.x.x客户端,同时支持Spring Framework 4.3。新版本包括对Spring Framework事务同步的支持,KafkaAdmin对象以及AckMode.RECORD的正确处理。此外,这些版本还包括几个错误修复。

https://spring.io/blog/2017/09 ... lable

5: Spring Integration贡献者Artem Bilan刚刚发布了Spring Integration 5. M7和4.3.12。新版本将响应式Spring Webflux适配器提取到单独的模块中,spring-integration-webflux。它还支持在用于协议的消息的有效负载中编码消息头,例如AWS Kinesis,Apache Kafka的早期版本和TCP / IP - 不支持本机头部的概念。

https://spring.io/blog/2017/09 ... lable

6: Spring整合领导Gary Russell刚刚发布推出Spring Cloud Stream Ditmars / 1.3 RC1。新支持使用Kafka Streams KStream引用作为@StreamListener方法的输入和输出。换句话说,您可以使用Spring Cloud Stream连接应用程序,声明所有的绑定等等,就像平常一样,然后编写用于交互查询的Kafka Streams的消息代码。

https://spring.io/blog/2017/09 ... ement

7: Spring Boot提交者StéphaneNicoll刚刚发布了Spring Boot 2.0.0.M4。此版本是第一个包含新的网络运行时无关的致动器端点以及一系列更改以简化安全配置。

https://spring.io/blog/2017/09 ... e-now

8: Spring Session 领导 Rob Winch刚刚发布了Spring Session 2.0.0.M4。此版本简化了基于Spring WebFlux的应用程序的配置。它还支持会话ID解析策略。

https://spring.io/blog/2017/09 ... -0-m4

9: Spring大牛Greg Turnquist刚刚发布了Spring Session MongoDB 2.0.0.M3。新版本基于Spring Session 2.0.0.M4,Spring Data Kay RC3,Reactor Bismuth-M4和Spring Framework 5.0.0.RC4。如果你使用Spring Boot 2.0的spring-boot-starter-data-mongodb-reactive,那么你只需要使用@EnableMongoWebSession启用!

https://spring.io/blog/2017/09 ... eased

10: Spring Security主管Rob Winch刚刚发布了Spring Security 5.0.0.M4。此版本新增了许多新功能,包括OAUth 2 / OpenID Connect支持和Spring WebFlux的响应集成。

https://spring.io/blog/2017/09 ... eased

11: Spring web 专家 Rossen Stoyanchev刚刚发布Spring Web Flow 2.4.6。该版本包含影响默认绑定的安全修补补丁。

https://spring.io/blog/2017/09 ... eased

12: Spring Cloud Data Flow贡献者Eric Bottard刚刚发布了Spring Shell 2.0.M1! Spring Shell项目表示一个命令组件模型,以支持开发自定义shell。 Spring Shell是支持Spring Cloud Data Flow shell的项目。这个新版本有很多提供,包括位置参数,使用Spring转换API,JLine 3支持,与bean验证API的集成,多行命令等等。

https://spring.io/blog/2017/09 ... 2-0m1

13: 西蒙·巴斯利刚刚发布了Reactor 3.1 RC1。这是迈向Spring Framework 5.0的一大步。强烈建议用户抓住这些机会,尽快尝试!

https://spring.io/blog/2017/09 ... e-3-1

14: Spring Cloud Data Flow贡献者Glenn Renfro发布推出1.3.0.M2版本,包含了很多新功能。它包括支持批处理、任务和流操作的更新的Dashboard / Flo集成、 fan-in和 fan-out支持、应用程序注册表和Maven更新策略、安全更新、直接命名渠道、shell改进等等。

https://spring.io/blog/2017/09 ... eased

15: Spring Boot大牛Madhura Bhave表示Spring Boot 2.0.0.M4改进了与Spring Security的集成方式;这绝对值得一读!

https://spring.io/blog/2017/09 ... -0-m4

16:Tom Hombergs把Spring Boot和RabbitMQ应用在微服务消息方面做了一个很好的改进。

https://reflectoring.io/event- ... itmq/

17:另一个友好的提醒,我会在以 Reactive Spring为主题 Reactive峰会上发表演讲,希望能在那里见到你!

https://www.youtube.com/watch?v=GzebF1iKZPU

18:一个友好的提醒,我将在12月以Spring Boot和Kotlin为主题的Kotlin 大会上发表演讲,我很想在那里见到你。

https://kotlinconf.com/speakers/#speaker=josh-long

19:Damith Ganegoda在这篇博文对Spring Boot和Angular 4做了很好的介绍。

http://mydevgeek.com/angular-4 ... rt-1/

20:Ordina JWorks的博客非常详细的介绍了新的Micrometer monitoring abstraction(它也集成在Spring Boot 2.0.0.M4中)。

https://ordina-jworks.github.i ... .html

21:Atomist的Clay McCoy让你看到Atomist如何帮助您在Spring Boot应用程序中捕获REST API更改。

https://the-composition.com/ch ... 2301f

22: 我喜欢这篇发布在ZDNet上的Greenplum的文章(大数据是最好的保密)

http://www.zdnet.com/google-am ... king/

23:说到Spring Boot贡献者,以及令人赞叹的Madhura BHave,她还将对Spring Boot 2.0中的JavaZone 2017演示文稿进行了深入的介绍。

https://speakerdeck.com/mbhave ... dot-0

24:我喜欢Dan的帖子,在这其中特别介绍了超媒体和HATEOAS的概念,并且使用了一些基于Spring Boot和Spring HATEOAS的示例代码。

https://lankydanblog.com/2017/ ... /amp/

25:Facebook和Github刚刚发布推出了Atom IDE - 一个支持Java的新型IDE。我没有机会尝试,但它看起来很有趣。我不知道它是否会支持Maven或Gradle..

https://github.com/blog/2430-introducing-atom-ide

「转」Spring Boot 2.0 - WebFlux framework

Spring Framework泥瓦匠BYSocket 发表了文章 • 0 个评论 • 238 次浏览 • 4 天前 • 来自相关话题

1、介绍
1.1 什么是响应式编程(Reactive Programming)?

简单来说,响应式编程是针对异步和事件驱动的非阻塞应用程序,并且需要少量线程来垂直缩放(即在 JVM 内)而不是水平(即通过集群)。

响应式应用的一个关键方面是“背压(backpressure)”的概念,这是确保生产者不会压倒消费者的机制。例如,当HTTP连接太慢时,从数据库延伸到HTTP响应的反应组件的流水线、数据存储库也可以减慢或停止,直到网络容量释放。

响应式编程也导致从命令式到声明异步组合逻辑的重大转变。与使用Java 8的 CompletableFuture 编写封锁代码相比,可以通过 lambda
表达式编写后续操作。

1.2 响应式 API(Reactive API)和 构建块(Building Blocks)

Spring Framework 5 将 Reactive Streams 作为通过异步组件和库进行背压通信的合同。Reactive Streams 是通过行业协作创建的规范,也已在Java 9中被采用为 java.util.concurrent.Flow。

Spring Framework 在内部使用 Reactor 自己的响应支持。Reactor 是一个 Reactive Streams 实现,进一步扩展基本的 Reactive Streams Publisher 、Flux 和 Mono 可组合的API类型,以提供对 0..N 和 0..1 的数据序列的声明性操作。

Spring Framework 在许多自己的 Reactive API 中暴露了 Flux 和
Mono。然而,在应用级别,一如既往,Spring 提供了选择,并完全支持使用RxJava。有关的更多信息,请查看 Sebastien Deleuze 发表的 "Understanding Reactive Types" 。

2、Spring WebFlux 模块

Spring Framework 5 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对REST,HTML浏览器和 WebSocket风格交互的响应式服务器Web应用程序的支持。

2.1、服务器端

在服务器端 WebFlux 支持2种不同的编程模型:

基于注解的 @Controller 和其他注解也支持 Spring MVC
Functional 、Java 8 lambda 风格的路由和处理





 

WebFlux 可以在支持 Servlet 3.1 非阻塞 IO API 以及其他异步运行时(如 Netty 和 Undertow )的 Servlet 容器上运行。每个运行时都适用于响应型 ServerHttpRequest 和 ServerHttpResponse,将请求和响应的正文暴露为 Flux<DataBuffer>,而不是具有响应背压的InputStream 和 OutputStream 。顶部作为 Flux<Object> 支持REST风格的 JSON 和 XML 序列化和反序列化,HTML视图呈现和服务器发送事件也是如此。

基于注解的编程模式

WebFlux中也支持相同的 @Controller 编程模型和 Spring MVC 中使用的相同注解。主要区别在于底层核心框架契约(即 HandlerMapping HandlerAdapter )是非阻塞的,并且在响应型 ServerHttpRequest
和 ServerHttpResponse 上运行,而不是在 HttpServletRequest 和HttpServletResponse 上运行。以下是一个响应式 Controller 的例子:
$(document).ready(function() {$('pre code').each(function(i, block) { hljs.highlightBlock( block); }); });@RestController
public class PersonController {

private final PersonRepository repository;

public PersonController(PersonRepository repository) {
this.repository = repository;
}

@PostMapping("/person")
Mono<Void> create(@RequestBody Publisher<Person> personStream) {
return this.repository.save(personStream).then();
}

@GetMapping("/person")
Flux<Person> list() {
return this.repository.findAll();
}

@GetMapping("/person/{id}")
Mono<Person> findById(@PathVariable String id) {
return this.repository.findOne(id);
}
}


 
函数式编程模式

HandlerFunctions

传入的HTTP请求由 HandlerFunction 处理,HandlerFunction 本质上是一个接收 ServerRequest 并返回 Mono<ServerResponse> 的函数。处理函数的注解对应方法将是一个 @RequestMapping 的方法。

ServerRequest 和 ServerResponse 是提供JDK-8友好访问底层HTTP消息的不可变接口。两者都通过在反应堆顶部建立完全反应:请求将身体暴露为 Flux 或 Mono; 响应接受任何 Reactive Streams Publisher 作为主体。

ServerRequest 可以访问各种HTTP请求元素:方法,URI,查询参数,以及通过单独的ServerRequest.Headers 接口 - 头。通过 body方法 提供对 body 的访问。例如,这是如何将请求体提取为 Mono <String>:
Mono<String> string = request.bodyToMono(String.class);
 
这里是如何将身体提取为 Flux,其中 Person 是可以从body内容反序列化的类(即如果body包含JSON,则由Jackson支持,或者如果是XML,则为JAXB)。
Flux<Person> people = request.bodyToFlux(Person.class);
 
上面的两个方法(bodyToMono 和 bodyToFlux)实际上是使用通用ServerRequest.body(BodyExtractor)函数的便利方法。
BodyExtractor 是一个功能策略界面,允许您编写自己的提取逻辑,但在 BodyExtractors 实用程序类中可以找到常见的 BodyExtractor 实例。所以,上面的例子可以替换为:
Mono<String> string = request.body(BodyExtractors.toMono(String.class);
Flux<Person> people = request.body(BodyExtractors.toFlux(Person.class);
 
类似地,ServerResponse 提供对HTTP响应的访问。由于它是不可变的,您可以使用构建器创建一个 ServerResponse 。构建器允许您设置响应状态,添加响应标题并提供正文。例如,这是如何使用200 OK状态创建响应,JSON内容类型和正文:Mono<Person> person = ... ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person);这里是如何使用201创建的状态,位置标题和空白体来构建响应:
URI location = ...
ServerResponse.created(location).build();
将这些组合在一起可以创建一个 HandlerFunction。例如,这里是一个简单的“Hello World”处理程序 lambda 的示例,它返回一个200状态的响应和一个基于 String 的主体:
HandlerFunction<ServerResponse> helloWorld = request -> ServerResponse.ok().body(fromObject("Hello World"));
 
使用 lambda 写处理函数,就像我们上面所说的那样很方便,但是在处理多个函数时可能缺乏可读性,变得不那么容易维护。因此,建议将相关处理函数分组到一个处理程序或控制器类中。例如,这是一个暴露了一个响应式的 Person 存储库的类:
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;

public class PersonHandler {

private final PersonRepository repository;

public PersonHandler(PersonRepository repository) {
this.repository = repository;
}

// 1
public Mono<ServerResponse> listPeople(ServerRequest request) {
Flux<Person> people = repository.allPeople();
return ServerResponse.ok().contentType(APPLICATION_JSON).body(people, Person.class);
}

// 2
public Mono<ServerResponse> createPerson(ServerRequest request) {
Mono<Person> person = request.bodyToMono(Person.class);
return ServerResponse.ok().build(repository.savePerson(person));
}

// 3
public Mono<ServerResponse> getPerson(ServerRequest request) {
int personId = Integer.valueOf(request.pathVariable("id"));
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
Mono<Person> personMono = this.repository.getPerson(personId);
return personMono
.flatMap(person -> ServerResponse.ok().contentType(APPLICATION_JSON).body(fromObject(person)))
.switchIfEmpty(notFound);
}
}
1/ listPeople 是一个处理函数,它将数据库中发现的所有 Person
对象返回为JSON。

2/ createPerson 是一个处理函数,用于存储请求正文中包含的新Person。请注意,PersonRepository.savePerson(Person) 返回Mono<Void>:发出完成信号的空 Mono,当人从请求中读取并存储时,发出完成信号。因此,当接收到完成信号时,即当 Person 已被保存时,我们使用 build(Publisher<Void>) 方法来发送响应。

3/ getPerson 是一个处理函数,它通过路径变量id来标识一个人。我们通过数据库检索该Person,并创建一个JSON响应(如果找到)。如果没有找到,我们使用 switchIfEmpty(Mono<T>) 来返回 404 Not Found 响应。

RouterFunctions

传入请求将路由到处理函数,并使用一个 RouterFunction,它是一个服务器 ServerRequest 的函数,并返回一个 Mono<HandlerFunction>。如果请求与特定路由匹配,则返回处理函数; 否则返回一个空的 Mono。RouterFunction 与 @Controller 类中的 @RequestMapping 注解类似。

通常,您不要自己编写路由器功能,而是使用
RouterFunctions.route(RequestPredicate, HandlerFunction), 使用请求谓词和处理函数创建一个。如果谓词适用,请求将路由到给定的处理函数; 否则不执行路由,导致 404 Not Found 响应。虽然您可以编写自己的 RequestPredicate ,但是您不需要:RequestPredicates 实用程序类提供常用的谓词,基于路径,HTTP方法,内容类型等进行匹配。使用路由,我们可以路由到我们的 “Hello World” 处理函数:
RouterFunction<ServerResponse> helloWorldRoute =
RouterFunctions.route(RequestPredicates.path("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")));

 
两个路由功能可以组成一个新的路由功能,路由到任一处理函数:如果第一个路由的谓词不匹配,则第二个被评估。组合的路由器功能按顺序进行评估,因此在通用功能之前放置特定功能是有意义的。您可以通过调用 RouterFunction.and(RouterFunction) 或通过调用
RouterFunction.andRoute(RequestPredicate, HandlerFunction) 来组成两个路由功能,这是 RouterFunction.and() 与 RouterFunctions.route() 的一种方便组合。

给定我们上面显示的 PersonH​​andler,我们现在可以定义路由功能,路由到相应的处理函数。我们使用 方法引用(method-references) 来引用处理函数:
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;

PersonRepository repository = ...
PersonHandler handler = new PersonHandler(repository);

RouterFunction<ServerResponse> personRoute =
route(GET("/person/{id}").and(accept(APPLICATION_JSON)), handler::getPerson)
.andRoute(GET("/person").and(accept(APPLICATION_JSON)), handler::listPeople)
.andRoute(POST("/person").and(contentType(APPLICATION_JSON)), handler::createPerson);

 
除路由功能之外,您还可以通过调用
RequestPredicate.and(RequestPredicate) 或
RequestPredicate.or(RequestPredicate) 来构成请求谓词。这些工作正如预期的那样:如果给定的谓词匹配,则生成的谓词匹配; 或者如果任一谓词都匹配。RequestPredicates 中发现的大多数谓词是组合的。例如,RequestPredicates.GET(String) 是
RequestPredicates.method(HttpMethod) 和RequestPredicates.path(String) 的组合。

启动服务器

现在只有一个难题遗留:在HTTP服务器中运行路由功能。您可以使用
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
 
对于 Tomcat ,它看起来像这样:
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("", System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();
 
待完成:DispatcherHandler
HandlerFilterFunction
路由功能映射的路由可以通过调用
RouterFunction.filter(HandlerFilterFunction) 进行过滤,其中
HandlerFilterFunction 本质上是一个接收 ServerRequest 和
HandlerFunction 的函数,并返回一个 ServerResponse 。处理函数参数表示链中的下一个元素:通常是路由到的 HandlerFunction ,但是如果应用了多个过滤器,也可以是另一个 FilterFunction 。使用注解,可以使用 @ControllerAdvice 和 / 或 ServletFilter 来实现类似的功能。让我们在我们的路由中添加一个简单的安全过滤器,假设我们有一个 SecurityManager 可以确定是否允许特定的路径:
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

SecurityManager securityManager = ...
RouterFunction<ServerResponse> route = ...

RouterFunction<ServerResponse> filteredRoute =
route.filter(request, next) -> {
if (securityManager.allowAccessTo(request.path())) {
return next.handle(request);
}
else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});
 
在这个例子中可以看到,调用 next.handle(ServerRequest) 是可选的:我们只允许在允许访问时执行处理函数。

2.2 客户端(Client Side)

WebFlux 包括一个 functional, reactive WebClient,它为 RestTemplate 提供了一种完全无阻塞和响应式的替代方案。
它将网络输入和输出公开为客户端 HttpRequest 和ClientHttpResponse ,其中请求和响应的主体是 Flux <DataBuffer>而不是 InputStream 和 OutputStream。此外,它还支持与服务器端相同的响应式 JSON,XML和SSE 序列化机制,因此您可以使用类型化对象。以下是使用需要 ClientHttpConnector 实现的 WebClient 插入特定HTTP客户端(如 Reactor Netty)的示例:
WebClient client = WebClient.create("http://example.com");

Mono<Account> account = client.get()
.url("/accounts/{id}", 1L)
.accept(APPLICATION_JSON)
.exchange(request)
.flatMap(response -> response.bodyToMono(Account.class));
 
AsyncRestTemplate 还支持非阻塞交互。主要区别在于它不支持非阻塞流,例如 Twitter one ,因为它基本上仍然依赖于 InputStream 和
OutputStream。

2.4 请求体和响应体的转换(Request and Response Body Conversion)

spring-core 模块提供了响应式 Encoder (编码器) 和 Decoder (解码器),使得能够串行化字符串与类型对象的转换。spring-web 模块添加了 JSON(Jackson)和 XML(JAXB)实现,用于Web应用程序以及其他用于SSE流和零拷贝文件传输。

支持以下 Reactive API:

Reactor 3.x 支持开箱即用
io.reactivex.rxjava2:rxjava 依赖项在类路径上时支持 RxJava 2.x
当 ·io.reactivex:rxjava和io.reactivex:rxjava-reactive-streams`(RxJava 和 Reactive Streams 之间的适配器)依赖关系在类路径上时,支持 RxJava 1.x

例如,请求体可以是以下方式之一,它将在注解和功能编程模型中自动解码:

Account account - 在调用控制器之前,account 将无阻塞地被反序列化。
Mono<Account> account - controller 可以使用 Mono 来声明在反序列化 account 后执行的逻辑。
Single<Account> account - 和 Mono 类似,但是用的是 RxJava
Flux<Account> accounts - 输入流场景
Observable<Account> accounts - RxJava 的 输入流场景

响应体(response body)可以是以下之一:

Mono<Account> - 当 Mono 完成时,序列化而不阻塞给定的Account。
Single<Account> - 与上类似,但是使用的 RxJava
Flux<Account> - 流式场景,可能是SSE,具体取决于所请求的内容类型。
Observable<Account> - 与上类似, 但是使用的 RxJava Observable 类型
Flowable<Account> - 与上类似, 但是使用的 RxJava 2 Flowable 类型。
Publisher<Account> 或 Flow.Publisher<Account> - 支持任何实现Reactive Streams Publisher 的类型。
Flux<ServerSentEvent> - SSE 流。
Mono<Void> - 当 Mono 完成时,请求处理完成。
Account - 序列化而不阻塞给定的Account; 意味着同步、非阻塞的
Controller 方法。
Void - 特定于基于注解的编程模型,方法返回时,请求处理完成;
意味着同步、非阻塞的 Controller 方法。

当使用像 Flux 或 Observable 这样的流类型时,请求/响应或映射/路由级别中指定的媒体类型用于确定数据应如何序列化和刷新。例如,返回 Flux<Account> 的REST端点将默认序列化如下:

application/json : Flux<Account> 作为异步集合处理,并在完成事件发布时将其序列化为具有显式刷新的JSON数组。
application/stream+json : 一个 Flux<Account> 将作为一系列的Account 元素处理,作为以新行分隔的单个JSON对象,并在每个元素之后显式刷新。WebClient 支持JSON流解码,因此这对于服务器到服务器的用例来说是一个很好的用例。
text/event-stream : 一个 Flux<Account> 或 Flux<ServerSentEvent<Account >> 将作为一个 Stream 或ServerSentEvent 元素的流处理,作为单独的 SSE 元素,使用默认的JSON进行数据编码和每个元素之间的显式刷新。这非常适合将流暴露给浏览器客户端。WebClient 也支持读取SSE流。

2.4 响应式 Websocket 支持

WebFlux 包括响应式 WebSocket 客户端和服务器支持。Java WebSocket API(JSR-356),Jetty,Undertow和Reactor Netty都支持客户端和服务器。

在服务器端,声明一个 WebSocketHandlerAdapter,然后简单地添加映射到基于 WebSocketHandler 的端点:
@Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/foo", new FooWebSocketHandler());
map.put("/bar", new BarWebSocketHandler());

SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(10);
mapping.setUrlMap(map);
return mapping;
}

@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
在客户端,为上面列出的支持的库之一创建一个 WebSocketClient:
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute("ws://localhost:8080/echo"), session -> {... }).blockMillis(5000);
 
2.5 测试

spring-test 模块包括一个 WebTestClient,可用于测试具有或不具有正在运行的服务器的 WebFlux 服务器端点。

没有运行服务器的测试与来自Spring MVC的 MockMvc 相当,其中使用模拟请求和响应,而不是使用套接字通过网络连接。然而,WebTestClient 也可以针对正在运行的服务器执行测试。

更多请查看 sample tests

3、开始入门
3.1 Spring Boot Starter

通过 http://start.spring.io 提供的 Spring Boot WebFlux 启动器是最快的入门方式。它做所有必要的,所以你开始像Spring MVC一样编写@Controller类。只需转到 http://start.spring.io ,选择版本
2.0.0.BUILD-SNAPSHOT,并在依赖关系框中键入 respond。
默认情况下,启动器使用 Reactor Netty 运行,但依赖关系可以像往常一样通过 Spring Boot 更改为不同的运行时。有关更多详细信息和说明,请参阅 Spring Boo t参考文档页面。

3.2 手动引导(Manual Bootstrapping)

对于依赖关系,从 spring-webflux 和 spring-context 开始。
然后添加jackson-databind 和 io.netty:netty-buffer(暂时见SPR-14528)以获得JSON支持。最后添加一个支持的运行时的依赖项:

Tomcat — org.apache.tomcat.embed:tomcat-embed-core
Jetty — org.eclipse.jetty:jetty-server 和 org.eclipse.jetty:jetty-servlet
Reactor Netty — io.projectreactor.ipc:reactor-netty
Undertow — io.undertow:undertow-core

基于注解编程模式的引导:
ApplicationContext context = new AnnotationConfigApplicationContext(DelegatingWebFluxConfiguration.class); // (1)
HttpHandler handler = DispatcherHandler.toHttpHandler(context); // (2)
 
以上加载默认的 Spring Web 框架配置(1),然后创建一个DispatcherHandler,主类驱动请求处理(2),并适应 HttpHandler - 响应式HTTP请求处理的最低级别的Spring抽象。

函数编程模式的引导:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // (1)
context.registerBean(FooBean.class, () -> new FooBeanImpl()); // (2)
context.registerBean(BarBean.class); // (3)
context.refresh();

HttpHandler handler = WebHttpHandlerBuilder
.webHandler(RouterFunctions.toHttpHandler(...))
.applicationContext(context)
.build(); // (4)
以上创建了一个 AnnotationConfigApplicationContext 实例(1),可以利用新的功能 bean 注册API(2)使用 Java 8 供应商注册 bean,或者只需通过指定其类(3)即可。HttpHandler 是使用WebHttpHandlerBuilder(4)创建的。

然后可以将 HttpHandler 安装在支持的运行服务器之一中:
// Tomcat and Jetty (also see notes below)
HttpServlet servlet = new ServletHttpHandlerAdapter(handler);
...

// Reactor Netty
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create(host, port).newHandler(adapter).block();

// Undertow
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();
对于特别是使用 WAR 部署的 Servlet 容器,可以使用作为WebApplicationInitializer 的
AbstractAnnotationConfigDispatcherHandlerInitializer,并由 Servlet容器自动检测。它负责注册 ServletHttpHandlerAdapter ,如上所示。您将需要实现一个抽象方法来指向您的 Spring 配置。

3.3 Examples

您将在以下项目中找到有助于构建反应式 Web 应用程序的代码示例:

Functional programming model sample
Spring Reactive Playground: playground for most Spring Web reactive features
Reactor website: the spring-functional
branch is a Spring 5 functional, Java 8 lambda-style application
Spring Reactive University session: live-coded project from this Devoxx BE 2106 university talk
Reactive Thymeleaf Sandbox
Mix-it 2017 website: Kotlin + Reactive + Functional web and bean registration API application
Reactor by example: code snippets coming from this InfoQ article
Spring integration tests: various features tested with Reactor StepVerifier


Webflux 实战项目

demo地址: https://anyim.cfapps.io/

作者:Anoyi
链接:http://www.jianshu.com/p/f4ff6d74ad4a

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  查看全部
1、介绍
1.1 什么是响应式编程(Reactive Programming)?

简单来说,响应式编程是针对异步和事件驱动的非阻塞应用程序,并且需要少量线程来垂直缩放(即在 JVM 内)而不是水平(即通过集群)。

响应式应用的一个关键方面是“背压(backpressure)”的概念,这是确保生产者不会压倒消费者的机制。例如,当HTTP连接太慢时,从数据库延伸到HTTP响应的反应组件的流水线、数据存储库也可以减慢或停止,直到网络容量释放。

响应式编程也导致从命令式到声明异步组合逻辑的重大转变。与使用Java 8的 CompletableFuture 编写封锁代码相比,可以通过 lambda
表达式编写后续操作。

1.2 响应式 API(Reactive API)和 构建块(Building Blocks)

Spring Framework 5 将 Reactive Streams 作为通过异步组件和库进行背压通信的合同。Reactive Streams 是通过行业协作创建的规范,也已在Java 9中被采用为 java.util.concurrent.Flow。

Spring Framework 在内部使用 Reactor 自己的响应支持。Reactor 是一个 Reactive Streams 实现,进一步扩展基本的 Reactive Streams Publisher 、Flux 和 Mono 可组合的API类型,以提供对 0..N 和 0..1 的数据序列的声明性操作。

Spring Framework 在许多自己的 Reactive API 中暴露了 Flux 和
Mono。然而,在应用级别,一如既往,Spring 提供了选择,并完全支持使用RxJava。有关的更多信息,请查看 Sebastien Deleuze 发表的 "Understanding Reactive Types" 。

2、Spring WebFlux 模块

Spring Framework 5 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对REST,HTML浏览器和 WebSocket风格交互的响应式服务器Web应用程序的支持。

2.1、服务器端

在服务器端 WebFlux 支持2种不同的编程模型:

基于注解的 @Controller 和其他注解也支持 Spring MVC
Functional 、Java 8 lambda 风格的路由和处理

3424642-7922d13b6c20ee6e.png

 

WebFlux 可以在支持 Servlet 3.1 非阻塞 IO API 以及其他异步运行时(如 Netty 和 Undertow )的 Servlet 容器上运行。每个运行时都适用于响应型 ServerHttpRequest 和 ServerHttpResponse,将请求和响应的正文暴露为 Flux<DataBuffer>,而不是具有响应背压的InputStream 和 OutputStream 。顶部作为 Flux<Object> 支持REST风格的 JSON 和 XML 序列化和反序列化,HTML视图呈现和服务器发送事件也是如此。

基于注解的编程模式

WebFlux中也支持相同的 @Controller 编程模型和 Spring MVC 中使用的相同注解。主要区别在于底层核心框架契约(即 HandlerMapping HandlerAdapter )是非阻塞的,并且在响应型 ServerHttpRequest
和 ServerHttpResponse 上运行,而不是在 HttpServletRequest 和HttpServletResponse 上运行。以下是一个响应式 Controller 的例子:
@RestController
public class PersonController {

private final PersonRepository repository;

public PersonController(PersonRepository repository) {
this.repository = repository;
}

@PostMapping("/person")
Mono<Void> create(@RequestBody Publisher<Person> personStream) {
return this.repository.save(personStream).then();
}

@GetMapping("/person")
Flux<Person> list() {
return this.repository.findAll();
}

@GetMapping("/person/{id}")
Mono<Person> findById(@PathVariable String id) {
return this.repository.findOne(id);
}
}


 
函数式编程模式

HandlerFunctions

传入的HTTP请求由 HandlerFunction 处理,HandlerFunction 本质上是一个接收 ServerRequest 并返回 Mono<ServerResponse> 的函数。处理函数的注解对应方法将是一个 @RequestMapping 的方法。

ServerRequest 和 ServerResponse 是提供JDK-8友好访问底层HTTP消息的不可变接口。两者都通过在反应堆顶部建立完全反应:请求将身体暴露为 Flux 或 Mono; 响应接受任何 Reactive Streams Publisher 作为主体。

ServerRequest 可以访问各种HTTP请求元素:方法,URI,查询参数,以及通过单独的ServerRequest.Headers 接口 - 头。通过 body方法 提供对 body 的访问。例如,这是如何将请求体提取为 Mono <String>:
Mono<String> string = request.bodyToMono(String.class);

 
这里是如何将身体提取为 Flux,其中 Person 是可以从body内容反序列化的类(即如果body包含JSON,则由Jackson支持,或者如果是XML,则为JAXB)。
Flux<Person> people = request.bodyToFlux(Person.class);

 
上面的两个方法(bodyToMono 和 bodyToFlux)实际上是使用通用ServerRequest.body(BodyExtractor)函数的便利方法。
BodyExtractor 是一个功能策略界面,允许您编写自己的提取逻辑,但在 BodyExtractors 实用程序类中可以找到常见的 BodyExtractor 实例。所以,上面的例子可以替换为:
Mono<String> string = request.body(BodyExtractors.toMono(String.class); 
Flux<Person> people = request.body(BodyExtractors.toFlux(Person.class);

 
类似地,ServerResponse 提供对HTTP响应的访问。由于它是不可变的,您可以使用构建器创建一个 ServerResponse 。构建器允许您设置响应状态,添加响应标题并提供正文。例如,这是如何使用200 OK状态创建响应,JSON内容类型和正文:Mono<Person> person = ... ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person);这里是如何使用201创建的状态,位置标题和空白体来构建响应:
URI location = ... 
ServerResponse.created(location).build();

将这些组合在一起可以创建一个 HandlerFunction。例如,这里是一个简单的“Hello World”处理程序 lambda 的示例,它返回一个200状态的响应和一个基于 String 的主体:
HandlerFunction<ServerResponse> helloWorld = request -> ServerResponse.ok().body(fromObject("Hello World"));

 
使用 lambda 写处理函数,就像我们上面所说的那样很方便,但是在处理多个函数时可能缺乏可读性,变得不那么容易维护。因此,建议将相关处理函数分组到一个处理程序或控制器类中。例如,这是一个暴露了一个响应式的 Person 存储库的类:
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;

public class PersonHandler {

private final PersonRepository repository;

public PersonHandler(PersonRepository repository) {
this.repository = repository;
}

// 1
public Mono<ServerResponse> listPeople(ServerRequest request) {
Flux<Person> people = repository.allPeople();
return ServerResponse.ok().contentType(APPLICATION_JSON).body(people, Person.class);
}

// 2
public Mono<ServerResponse> createPerson(ServerRequest request) {
Mono<Person> person = request.bodyToMono(Person.class);
return ServerResponse.ok().build(repository.savePerson(person));
}

// 3
public Mono<ServerResponse> getPerson(ServerRequest request) {
int personId = Integer.valueOf(request.pathVariable("id"));
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
Mono<Person> personMono = this.repository.getPerson(personId);
return personMono
.flatMap(person -> ServerResponse.ok().contentType(APPLICATION_JSON).body(fromObject(person)))
.switchIfEmpty(notFound);
}
}

1/ listPeople 是一个处理函数,它将数据库中发现的所有 Person
对象返回为JSON。

2/ createPerson 是一个处理函数,用于存储请求正文中包含的新Person。请注意,PersonRepository.savePerson(Person) 返回Mono<Void>:发出完成信号的空 Mono,当人从请求中读取并存储时,发出完成信号。因此,当接收到完成信号时,即当 Person 已被保存时,我们使用 build(Publisher<Void>) 方法来发送响应。

3/ getPerson 是一个处理函数,它通过路径变量id来标识一个人。我们通过数据库检索该Person,并创建一个JSON响应(如果找到)。如果没有找到,我们使用 switchIfEmpty(Mono<T>) 来返回 404 Not Found 响应。

RouterFunctions

传入请求将路由到处理函数,并使用一个 RouterFunction,它是一个服务器 ServerRequest 的函数,并返回一个 Mono<HandlerFunction>。如果请求与特定路由匹配,则返回处理函数; 否则返回一个空的 Mono。RouterFunction 与 @Controller 类中的 @RequestMapping 注解类似。

通常,您不要自己编写路由器功能,而是使用
RouterFunctions.route(RequestPredicate, HandlerFunction), 使用请求谓词和处理函数创建一个。如果谓词适用,请求将路由到给定的处理函数; 否则不执行路由,导致 404 Not Found 响应。虽然您可以编写自己的 RequestPredicate ,但是您不需要:RequestPredicates 实用程序类提供常用的谓词,基于路径,HTTP方法,内容类型等进行匹配。使用路由,我们可以路由到我们的 “Hello World” 处理函数:
RouterFunction<ServerResponse> helloWorldRoute =
RouterFunctions.route(RequestPredicates.path("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")));

 
两个路由功能可以组成一个新的路由功能,路由到任一处理函数:如果第一个路由的谓词不匹配,则第二个被评估。组合的路由器功能按顺序进行评估,因此在通用功能之前放置特定功能是有意义的。您可以通过调用 RouterFunction.and(RouterFunction) 或通过调用
RouterFunction.andRoute(RequestPredicate, HandlerFunction) 来组成两个路由功能,这是 RouterFunction.and() 与 RouterFunctions.route() 的一种方便组合。

给定我们上面显示的 PersonH​​andler,我们现在可以定义路由功能,路由到相应的处理函数。我们使用 方法引用(method-references) 来引用处理函数:
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;

PersonRepository repository = ...
PersonHandler handler = new PersonHandler(repository);

RouterFunction<ServerResponse> personRoute =
route(GET("/person/{id}").and(accept(APPLICATION_JSON)), handler::getPerson)
.andRoute(GET("/person").and(accept(APPLICATION_JSON)), handler::listPeople)
.andRoute(POST("/person").and(contentType(APPLICATION_JSON)), handler::createPerson);

 
除路由功能之外,您还可以通过调用
RequestPredicate.and(RequestPredicate) 或
RequestPredicate.or(RequestPredicate) 来构成请求谓词。这些工作正如预期的那样:如果给定的谓词匹配,则生成的谓词匹配; 或者如果任一谓词都匹配。RequestPredicates 中发现的大多数谓词是组合的。例如,RequestPredicates.GET(String) 是
RequestPredicates.method(HttpMethod) 和RequestPredicates.path(String) 的组合。

启动服务器

现在只有一个难题遗留:在HTTP服务器中运行路由功能。您可以使用
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();

 
对于 Tomcat ,它看起来像这样:
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("", System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();

 
待完成:DispatcherHandler
HandlerFilterFunction
路由功能映射的路由可以通过调用
RouterFunction.filter(HandlerFilterFunction) 进行过滤,其中
HandlerFilterFunction 本质上是一个接收 ServerRequest 和
HandlerFunction 的函数,并返回一个 ServerResponse 。处理函数参数表示链中的下一个元素:通常是路由到的 HandlerFunction ,但是如果应用了多个过滤器,也可以是另一个 FilterFunction 。使用注解,可以使用 @ControllerAdvice 和 / 或 ServletFilter 来实现类似的功能。让我们在我们的路由中添加一个简单的安全过滤器,假设我们有一个 SecurityManager 可以确定是否允许特定的路径:
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

SecurityManager securityManager = ...
RouterFunction<ServerResponse> route = ...

RouterFunction<ServerResponse> filteredRoute =
route.filter(request, next) -> {
if (securityManager.allowAccessTo(request.path())) {
return next.handle(request);
}
else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});

 
在这个例子中可以看到,调用 next.handle(ServerRequest) 是可选的:我们只允许在允许访问时执行处理函数。

2.2 客户端(Client Side)

WebFlux 包括一个 functional, reactive WebClient,它为 RestTemplate 提供了一种完全无阻塞和响应式的替代方案。
它将网络输入和输出公开为客户端 HttpRequest 和ClientHttpResponse ,其中请求和响应的主体是 Flux <DataBuffer>而不是 InputStream 和 OutputStream。此外,它还支持与服务器端相同的响应式 JSON,XML和SSE 序列化机制,因此您可以使用类型化对象。以下是使用需要 ClientHttpConnector 实现的 WebClient 插入特定HTTP客户端(如 Reactor Netty)的示例:
WebClient client = WebClient.create("http://example.com";);

Mono<Account> account = client.get()
.url("/accounts/{id}", 1L)
.accept(APPLICATION_JSON)
.exchange(request)
.flatMap(response -> response.bodyToMono(Account.class));

 
AsyncRestTemplate 还支持非阻塞交互。主要区别在于它不支持非阻塞流,例如 Twitter one ,因为它基本上仍然依赖于 InputStream 和
OutputStream。

2.4 请求体和响应体的转换(Request and Response Body Conversion)

spring-core 模块提供了响应式 Encoder (编码器) 和 Decoder (解码器),使得能够串行化字符串与类型对象的转换。spring-web 模块添加了 JSON(Jackson)和 XML(JAXB)实现,用于Web应用程序以及其他用于SSE流和零拷贝文件传输。

支持以下 Reactive API:

Reactor 3.x 支持开箱即用
io.reactivex.rxjava2:rxjava 依赖项在类路径上时支持 RxJava 2.x
当 ·io.reactivex:rxjava和io.reactivex:rxjava-reactive-streams`(RxJava 和 Reactive Streams 之间的适配器)依赖关系在类路径上时,支持 RxJava 1.x

例如,请求体可以是以下方式之一,它将在注解和功能编程模型中自动解码:

Account account - 在调用控制器之前,account 将无阻塞地被反序列化。
Mono<Account> account - controller 可以使用 Mono 来声明在反序列化 account 后执行的逻辑。
Single<Account> account - 和 Mono 类似,但是用的是 RxJava
Flux<Account> accounts - 输入流场景
Observable<Account> accounts - RxJava 的 输入流场景

响应体(response body)可以是以下之一:

Mono<Account> - 当 Mono 完成时,序列化而不阻塞给定的Account。
Single<Account> - 与上类似,但是使用的 RxJava
Flux<Account> - 流式场景,可能是SSE,具体取决于所请求的内容类型。
Observable<Account> - 与上类似, 但是使用的 RxJava Observable 类型
Flowable<Account> - 与上类似, 但是使用的 RxJava 2 Flowable 类型。
Publisher<Account> 或 Flow.Publisher<Account> - 支持任何实现Reactive Streams Publisher 的类型。
Flux<ServerSentEvent> - SSE 流。
Mono<Void> - 当 Mono 完成时,请求处理完成。
Account - 序列化而不阻塞给定的Account; 意味着同步、非阻塞的
Controller 方法。
Void - 特定于基于注解的编程模型,方法返回时,请求处理完成;
意味着同步、非阻塞的 Controller 方法。

当使用像 Flux 或 Observable 这样的流类型时,请求/响应或映射/路由级别中指定的媒体类型用于确定数据应如何序列化和刷新。例如,返回 Flux<Account> 的REST端点将默认序列化如下:

application/json : Flux<Account> 作为异步集合处理,并在完成事件发布时将其序列化为具有显式刷新的JSON数组。
application/stream+json : 一个 Flux<Account> 将作为一系列的Account 元素处理,作为以新行分隔的单个JSON对象,并在每个元素之后显式刷新。WebClient 支持JSON流解码,因此这对于服务器到服务器的用例来说是一个很好的用例。
text/event-stream : 一个 Flux<Account> 或 Flux<ServerSentEvent<Account >> 将作为一个 Stream 或ServerSentEvent 元素的流处理,作为单独的 SSE 元素,使用默认的JSON进行数据编码和每个元素之间的显式刷新。这非常适合将流暴露给浏览器客户端。WebClient 也支持读取SSE流。

2.4 响应式 Websocket 支持

WebFlux 包括响应式 WebSocket 客户端和服务器支持。Java WebSocket API(JSR-356),Jetty,Undertow和Reactor Netty都支持客户端和服务器。

在服务器端,声明一个 WebSocketHandlerAdapter,然后简单地添加映射到基于 WebSocketHandler 的端点:
@Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/foo", new FooWebSocketHandler());
map.put("/bar", new BarWebSocketHandler());

SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(10);
mapping.setUrlMap(map);
return mapping;
}

@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}

在客户端,为上面列出的支持的库之一创建一个 WebSocketClient:
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute("ws://localhost:8080/echo"), session -> {... }).blockMillis(5000);

 
2.5 测试

spring-test 模块包括一个 WebTestClient,可用于测试具有或不具有正在运行的服务器的 WebFlux 服务器端点。

没有运行服务器的测试与来自Spring MVC的 MockMvc 相当,其中使用模拟请求和响应,而不是使用套接字通过网络连接。然而,WebTestClient 也可以针对正在运行的服务器执行测试。

更多请查看 sample tests

3、开始入门
3.1 Spring Boot Starter

通过 http://start.spring.io 提供的 Spring Boot WebFlux 启动器是最快的入门方式。它做所有必要的,所以你开始像Spring MVC一样编写@Controller类。只需转到 http://start.spring.io ,选择版本
2.0.0.BUILD-SNAPSHOT,并在依赖关系框中键入 respond。
默认情况下,启动器使用 Reactor Netty 运行,但依赖关系可以像往常一样通过 Spring Boot 更改为不同的运行时。有关更多详细信息和说明,请参阅 Spring Boo t参考文档页面。

3.2 手动引导(Manual Bootstrapping)

对于依赖关系,从 spring-webflux 和 spring-context 开始。
然后添加jackson-databind 和 io.netty:netty-buffer(暂时见SPR-14528)以获得JSON支持。最后添加一个支持的运行时的依赖项:

Tomcat — org.apache.tomcat.embed:tomcat-embed-core
Jetty — org.eclipse.jetty:jetty-server 和 org.eclipse.jetty:jetty-servlet
Reactor Netty — io.projectreactor.ipc:reactor-netty
Undertow — io.undertow:undertow-core

基于注解编程模式的引导:
ApplicationContext context = new AnnotationConfigApplicationContext(DelegatingWebFluxConfiguration.class);  // (1)
HttpHandler handler = DispatcherHandler.toHttpHandler(context); // (2)

 
以上加载默认的 Spring Web 框架配置(1),然后创建一个DispatcherHandler,主类驱动请求处理(2),并适应 HttpHandler - 响应式HTTP请求处理的最低级别的Spring抽象。

函数编程模式的引导:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // (1)
context.registerBean(FooBean.class, () -> new FooBeanImpl()); // (2)
context.registerBean(BarBean.class); // (3)
context.refresh();

HttpHandler handler = WebHttpHandlerBuilder
.webHandler(RouterFunctions.toHttpHandler(...))
.applicationContext(context)
.build(); // (4)

以上创建了一个 AnnotationConfigApplicationContext 实例(1),可以利用新的功能 bean 注册API(2)使用 Java 8 供应商注册 bean,或者只需通过指定其类(3)即可。HttpHandler 是使用WebHttpHandlerBuilder(4)创建的。

然后可以将 HttpHandler 安装在支持的运行服务器之一中:
// Tomcat and Jetty (also see notes below)
HttpServlet servlet = new ServletHttpHandlerAdapter(handler);
...

// Reactor Netty
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create(host, port).newHandler(adapter).block();

// Undertow
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();

对于特别是使用 WAR 部署的 Servlet 容器,可以使用作为WebApplicationInitializer 的
AbstractAnnotationConfigDispatcherHandlerInitializer,并由 Servlet容器自动检测。它负责注册 ServletHttpHandlerAdapter ,如上所示。您将需要实现一个抽象方法来指向您的 Spring 配置。

3.3 Examples

您将在以下项目中找到有助于构建反应式 Web 应用程序的代码示例:

Functional programming model sample
Spring Reactive Playground: playground for most Spring Web reactive features
Reactor website: the spring-functional
branch is a Spring 5 functional, Java 8 lambda-style application
Spring Reactive University session: live-coded project from this Devoxx BE 2106 university talk
Reactive Thymeleaf Sandbox
Mix-it 2017 website: Kotlin + Reactive + Functional web and bean registration API application
Reactor by example: code snippets coming from this InfoQ article
Spring integration tests: various features tested with Reactor StepVerifier


Webflux 实战项目

demo地址: https://anyim.cfapps.io/

作者:Anoyi
链接:http://www.jianshu.com/p/f4ff6d74ad4a

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

Spring Cloud Config测试对称加密的时候一直提示NO_KEY

回复

Spring Cloudwayne 发起了问题 • 1 人关注 • 0 个回复 • 111 次浏览 • 5 天前 • 来自相关话题

Spring For All 社区周报 20170918

最新动态strongant 发表了文章 • 0 个评论 • 111 次浏览 • 5 天前 • 来自相关话题

「社区开源项目」
个人小站CodeSheep新增后台管理功能,欢迎使用(网址http://113.209.119.170/)
http://spring4all.com/article/229
简化Swagger使用的自制Starter:spring-boot-starter-swagger,欢迎使用和吐槽
http://spring4all.com/article/177
SonarQube中文插件安装
http://spring4all.com/article/170
使用Docker搭建代码质量检测平台SonarQube
http://spring4all.com/article/169
我的第一款开发作品--CodeSheep功能完善并重构完成后全部开源,先来贴个图
http://spring4all.com/article/167
skywalking开发文档(一),编译工程
http://spring4all.com/article/155
SpringBoot编写自己的Starter项目(battcn-starter-swagger)
http://spring4all.com/article/153
可能是东半球最好用的DruidSpringBootStarter
http://spring4all.com/article/134

「每周热门文章」
从SpringBootStarters学习如何解决JAR依赖冲突问题
http://spring4all.com/article/231
Spring官方周报 2017.9.12
http://spring4all.com/article/230
Spring学习(一): 使用AbstractRoutingDataSource类进行多数据源配置
http://spring4all.com/article/228
spring boot 理解
http://spring4all.com/article/226

「每周热门议题」
eureka多节点,节点都在unavailable-replicas
http://spring4all.com/question/458
服务重启zuul不能及时发现
http://spring4all.com/question/407
SpringCloud环境下的鉴权操作应该放在网关这层还是资源服务器?
http://spring4all.com/question/457
spring目录中mainclass主入口类在包的位置有什么特别要注意的吗?
http://spring4all.com/question/449
想搞个个人博客,有谁可以给我提供页面模板?
http://spring4all.com/question/414
Spring的xml配置问题
http://spring4all.com/question/456
Springboot定时任务
http://spring4all.com/question/455
初学者怎么看spring的源码?比如mvc的resolver
http://spring4all.com/question/454
SpringCloudBus/bus/refresh无效
http://spring4all.com/question/429 查看全部
「社区开源项目」
个人小站CodeSheep新增后台管理功能,欢迎使用(网址http://113.209.119.170/
http://spring4all.com/article/229
简化Swagger使用的自制Starter:spring-boot-starter-swagger,欢迎使用和吐槽
http://spring4all.com/article/177
SonarQube中文插件安装
http://spring4all.com/article/170
使用Docker搭建代码质量检测平台SonarQube
http://spring4all.com/article/169
我的第一款开发作品--CodeSheep功能完善并重构完成后全部开源,先来贴个图
http://spring4all.com/article/167
skywalking开发文档(一),编译工程
http://spring4all.com/article/155
SpringBoot编写自己的Starter项目(battcn-starter-swagger)
http://spring4all.com/article/153
可能是东半球最好用的DruidSpringBootStarter
http://spring4all.com/article/134

「每周热门文章」
从SpringBootStarters学习如何解决JAR依赖冲突问题
http://spring4all.com/article/231
Spring官方周报 2017.9.12
http://spring4all.com/article/230
Spring学习(一): 使用AbstractRoutingDataSource类进行多数据源配置
http://spring4all.com/article/228
spring boot 理解
http://spring4all.com/article/226

「每周热门议题」
eureka多节点,节点都在unavailable-replicas
http://spring4all.com/question/458
服务重启zuul不能及时发现
http://spring4all.com/question/407
SpringCloud环境下的鉴权操作应该放在网关这层还是资源服务器?
http://spring4all.com/question/457
spring目录中mainclass主入口类在包的位置有什么特别要注意的吗?
http://spring4all.com/question/449
想搞个个人博客,有谁可以给我提供页面模板?
http://spring4all.com/question/414
Spring的xml配置问题
http://spring4all.com/question/456
Springboot定时任务
http://spring4all.com/question/455
初学者怎么看spring的源码?比如mvc的resolver
http://spring4all.com/question/454
SpringCloudBus/bus/refresh无效
http://spring4all.com/question/429