1. 程式人生 > >聊聊 Spring Boot 2.x 那些事兒

聊聊 Spring Boot 2.x 那些事兒

640.gif?wxfrom=5&wx_lazy=1

本文來自作者泥瓦匠 在 GitChat 上分享「聊聊 Spring Boot 2.x 那些事兒」,閱讀原文」檢視交流實錄

文末高能

編輯 | 文道

本文目錄:

即將的 Spring 2.0

 - Spring 2.0 是什麼

 - 開發環境和 IDE

 - 使用 Spring Initializr 快速入門

Starter 元件

 - Web:REST API & 模板引擎

 - Data:JPA -> H2

 - ...

生產指標監控 Actuator

內嵌式容器 Tomcat / Jetty / Undertow

Spring 5 & Spring WebFlux

大家看到目錄,這麼多內容,簡直一本書的節奏。如果很詳細,確實是。 可是隻有一篇文章我大致講講每個點,其是什麼,其主要業界的使用場景是什麼,然後具體會有對應的部落格教程。恩,下面我們聊聊 Spring 2.0。

一、即將的 Spring 2.0

spring.io 官網有句醒目的話是:

BUILD ANYTHING WITH SPRING BOOT

Java 程式設計師都知道 Spring 是什麼,Spring 走過了這麼多個年頭。Spring 是 Java 應用程式平臺開發框架,肯定也是跨平臺的。

同樣,它也是 Java EE 輕量級框架,為 Java 開發這提供了全面的基礎設施支援。

從 SSH(Strusts / Spring / Hibernate) 到 SSM(Spring MVC / Spring / Mabtis) ,到現在一個 S (Spring)就夠了的年代。 可見 Spring 越來越重要了。那 Spring Boot 是什麼?

1. Spring 2.0 是什麼

先看看世界上最好的文件來源自官方的《Spring Boot Reference Guide》,是這樣介紹的:

0?wx_fmt=png

Spring Boot(英文中是“引導”的意思),是用來簡化 Spring 應用的搭建到開發的過程。應用開箱即用,只要通過 “just run”(可能是 java -jar 或 tomcat 或 maven 外掛 run 或 shell 指令碼),就可以啟動專案。

二者,Spring Boot 只要很少的 Spring 配置檔案(例如那些xml,property)。

因為“習慣優先於配置”的原則,使得 Spring Boot 在快速開發應用和微服務架構實踐中得到廣泛應用。

Spring 目前是 2.0.0 M5 版本,馬上 2.0 release 了。如圖:Spring 2.0 架構圖

0?wx_fmt=png

最明顯的是 Reactor 模型。

插個小故事,曾經有人問:Spring 這種阻塞的程式設計技術以及金字塔的結構已經開始被很多公司所擯棄?

我的回答自然是那個圖。Spring Boot 2.0 基於 Spring 5 Framework ,提供了非同步非阻塞 IO 的響應式 Stream 、非堵塞的函式式 Reactive Web 框架 Spring WebFlux。本文最後我會詳細介紹的。

0?wx_fmt=png

2. 開發環境和 IDE

大致介紹了 Spring Boot 2.0 是什麼,下面我們快速入門下 Spring Boot 2.0。常言道,磨刀不誤砍柴工砍柴工。在搭建一個 Spring Boot 工程應用前,需要配置好開發環境及安裝好開發工具:

  • JDK 1.8+
    Spring Boot 2.x 要求 JDK 1.8 環境及以上版本。另外,Spring Boot 2.x 只相容 Spring Framework 5.0 及以上版本。

  • Maven 3.2+
    為 Spring Boot 2.x 提供了相關依賴構建工具是 Maven,版本需要 3.2 及以上版本。使用 Gradle 則需要 1.12 及以上版本。Maven 和 Gradle 大家各自挑選下喜歡的就好。

  • IntelliJ IDEA
    IntelliJ IDEA (簡稱 IDEA)是常用的開發工具,也是本書推薦使用的。同樣使用 Eclipse IDE 自然也是可以的。

這裡額外介紹下,對於 Java 新手或者剛剛認識 Spring 的小夥伴。Spring Boot CLI  是一個學習 Spring Boot 的很好的工具。Spring Boot CLI 是 Spring Boot Commad Line 的縮寫,是 Spring Boot 命令列工具。

在 Spring Boot CLI 可以跑 Groovy 指令碼,通過簡單的 Java 語法就可以快速而又簡單的學習 Spring Boot 原型。

Spring Boot CLI  具體快速入門看下我寫的地址:https://www.bysocket.com/?p=1982

那最常用,最推薦的入門當然是使用 Spring Initializr 。下面介紹下如何使用 Spring Initializr。

3. 使用 Spring Initializr 快速入門

開啟  start.spring.io  進行很快速的,Spring Boot 骨架工程生成吧。

Spring 官方提供了名為 Spring Initializr 的網站,去引導你快速生成 Spring Boot 應用。網站地址為:https://start.spring.io,操作步驟如下:

第一步,選擇 Maven 或者 Gradle 構建工具,開發語言 Java 、Kotlin 或者 Groovy,最後確定 Spring Boot 版本號。

這裡預設選擇 Maven 構建工具、Java 開發語言和 Spring Boot 2.0.0。

第二步,輸入 Maven 工程資訊,即專案組 groupId 和名字 artifactId。這裡對應 Maven 資訊為:

  • groupId:demo.springboot

  • artifactId:spring-boot-quickstart
    這裡預設版本號 version 為 0.0.1-SNAPSHOT 。三個屬性在 Maven 依賴倉庫是唯一標識的。

第三步,選擇工程需要的 Starter 元件和其他依賴。最後點選生成按鈕,即可獲得骨架工程壓縮包。如圖 :

0?wx_fmt=png

在對應的 *Application 增加對應的程式碼如下:(這來自是官方 demo)

@Controller @EnableAutoConfiguration public class Application {    @RequestMapping("/")    @ResponseBody    String home() {        return "Hello World!";    }    public static void main(String[] args) throws Exception {        SpringApplication.run(Application.class, args);    } }

在 IDEA 中直接執行應用啟動類,來執行 Spring Boot 應用,會得到下面成功的控制檯輸出:

... 省略 2017-10-15 10:05:19.994  INFO 17963 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) 2017-10-15 10:05:20.000  INFO 17963 --- [           main] demo.springboot.QuickStartApplication    : Started QuickStartApplication in 5.544 seconds (JVM running for 6.802)

訪問地址 localhost:8080 ,成功返回 “Hello World!” 的字串。

這就是 Spring Boot 使用,是不是很方便。介紹下工程的目錄結構:

├── pom.xml └── src    ├── main    │   ├── java    │   │   └── demo    │   │       └── springboot    │   │           └── Application.java    │   └── resources    │       ├── application.properties    │       ├── static    │       └── templates    └── test        └── java            └── demo                └── springboot                    └── QuickstartApplication Tests.java

這是預設的工程結構,java 目錄中是編寫程式碼的源目錄,比如三層模型大致會新建三個包目錄,web 包負責 web 服務,service 包負責業務邏輯,domain 包資料來源服務。對應 java 目錄的是 test 目錄,編寫單元測試的目錄。

resources 目錄會有 application.properties 應用配置檔案,還有預設生成的 static 和 templates 目錄,static 用於存放靜態資原始檔,templates 用於存放模板檔案。可以在 application.properties 中自定義配置資源和模板目錄

二、Starter 元件

什麼是 Starter 元件?

Starter 元件是可被載入在應用中的 Maven 依賴項。Spring Boot 提供了很多 “開箱即用” 的 Starter 元件。只需要在 Maven 配置中新增對應的依賴配置,即可使用對應的 Starter 元件。

例如,新增 spring-boot-starter-web 依賴,就可用於構建 RESTful Web 服務,其包含了 Spring MVC 和 Tomcat 內嵌容器等。

開發中,很多功能是通過新增 Starter 元件的方式來進行實現。下面都是常用的元件,還有很多事務、訊息、安全、監控、大資料等支援,這裡就不介紹了。大家可以同理可得去學習哈。

1. Web:REST API & 模板引擎

在 Web 開發中,常見的場景有傳統的 Web MVC 架構和前後端分離架構。

Web MVC 架構

Web MVC 模式很適合 Spring Boot 來開發,View 使用 JSP 或者其他模板引擎(預設支援:FreeMarker 、 Groovy 、 Thymeleaf 、 Mustache)。

傳統模式比如獲取使用者,是從使用者 view 層傳送獲取使用者請求到 Spring Boot 提供的使用者控制層,然後獲取資料封裝進 Model,最後將 model 返回到 View。

因為 Spring Boot 基於 Spring ,所以 Spring 能做的,Spring Boot 就能做,而且更加方便,更近快速。

前後端分離架構

前後端分離架構,免不了的是 API 文件作為中間的橋樑。Spring Boot 很方便的開發 REST API,前端通過呼叫 REST API 獲取資料。資料形式可能是 JSON 或者 XML 等。

然後進行檢視渲染,這裡前端也有對應的前端模板引擎。其實 H5 ,PC,APP 都可採取類似的方式實現。這裡的 API 文件可以使用 Swagger2 或者 APIDOC 來實現。

那具體聊聊 REST API

RESTful 是什麼?RESTful(Representational State Transfer)架構風格,是一個 Web 自身的架構風格,底層主要基於 HTTP 協議(ps:提出者就是HTTP協議的作者),是分散式應用架構的偉大實踐理論。

RESTful 架構是無狀態的,表現為請求-響應的形式,有別於基於 Bower 的SessionId 不同。Spring Boot 的註解 @RestController 支援實現 RESTful 控制層。

那有個問題?許可權怎麼控制?
RESTful是無狀態的,所以每次請求就需要對起進行認證和授權。

  • 認證
    身份認證,即登入驗證使用者是否擁有相應的身份。簡單的說就是一個Web頁面點選登入後,服務端進行使用者密碼的校驗。

  • 許可權驗證(授權)
    也可以說成授權,就是在身份認證後,驗證該身份具體擁有某種許可權。即針對於某種資源的 CRUD,不同使用者的操作許可權是不同的。

    一般簡單專案:做個sign(加密加鹽引數)+ 針對使用者的 access_token 複雜的話,加入  SLL ,並使用 OAuth2 進行對 token 的安全傳輸。

再聊聊模板引擎

有人在我部落格上評論 模板語言 現在沒人用了吧。我們還是先了解下,什麼是模板語言再說吧。

常見的模板語言都包含以下幾個概念:資料(Data)、模板(Template)、模板引擎(Template Engine)和結果文件(Result Documents)。

  • 資料
    資料是資訊的表現形式和載體,可以是符號、文字、數字、語音、影象、視訊等。

    資料和資訊是不可分離的,資料是資訊的表達,資訊是資料的內涵。資料本身沒有意義,資料只有對實體行為產生影響時才成為資訊。

  • 模板
    模板,是一個藍圖,即一個與型別無關的類。編譯器在使用模板時,會根據模板實參對模板進行例項化,得到一個與型別相關的類。

  • 模板引擎
    模板引擎(這裡特指用於Web開發的模板引擎)是為了使使用者介面與業務資料(內容)分離而產生的,它可以生成特定格式的文件,用於網站的模板引擎就會生成一個標準的HTML文件。

  • 結果文件
    一種特定格式的文件,比如用於網站的模板引擎就會生成一個標準的HTML文件。

模板語言用途廣泛,常見的用途如下:

  • 頁面渲染

  • 文件生成

  • 程式碼生成

  • 所有 “資料+模板=文字” 的應用場景

所以大家看到這個用途,應該不會說沒有用了吧。具體按模板語言 Thymeleaf 為例,使用如下

pom.xml Thymeleaf 依賴

使用模板引擎,就在 pom.xml 加入 Thymeleaf 元件依賴:

<!-- 模板引擎 Thymeleaf 依賴 --> <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>

Thymeleaf 依賴配置

在 Spring Boot 專案中加入 Thymeleaf 依賴,即可啟動其預設配置。如果想要自定義配置,可以在 application.properties 配置如下

spring.thymeleaf.cache=true # Enable template caching. spring.thymeleaf.check-template=true # Check that the template exists before rendering it. spring.thymeleaf.check-template-location=true # Check that the templates location exists. spring.thymeleaf.enabled=true # Enable Thymeleaf view resolution for Web frameworks. spring.thymeleaf.encoding=UTF-8 # Template files encoding. spring.thymeleaf.excluded-view-names= # Comma-separated list of view names that should be excluded from resolution. spring.thymeleaf.mode=HTML5 # Template mode to be applied to templates. See also StandardTemplateModeHandlers. spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL. spring.thymeleaf.reactive.max-chunk-size= # Maximum size of data buffers used for writing to the response, in bytes. spring.thymeleaf.reactive.media-types= # Media types supported by the view technology. spring.thymeleaf.servlet.content-type=text/html # Content-Type value written to HTTP responses. spring.thymeleaf.suffix=.html # Suffix that gets appended to view names when building a URL. spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.

Controller 的使用方式,和以前的 Spring 方式一致,具體的Tymeleaf 的語法糖,大家可以看看官方文件 http://www.thymeleaf.org/documentation.html。本案例具體整合教程:https://www.bysocket.com/?p=1973

2. Data:JPA 、Mybatis

Data,顧名思義是資料。資料儲存有 SQL 和 NoSQL:

  • SQL:MySQL 、H2 等

  • NoSQL:Redis、MongoDB、Cassandra、Elasticsearch 等
    自然網際網路常見使用的 SQL 關係型資料庫是 MySQL。ORM 框架流行的有 Hibernate 和 Mybatis 等,JPA 底層實現使用 Hibernate。下面分別介紹下兩者的使用方式

Spring Data JPA 依賴 spring-boot-starter-data-jpa

Spring Data JPA 是 Spring Data 的子專案,用於簡化資料訪問層的實現,可以方便的實現增刪改查、分頁、排序。

還有很多常見的其他依賴:Spring Data MongoDB、Spring Data Redis 等。這裡 Spring Boot 也有對應的 Starter 元件,名為 spring-boot-starter-data-jpa。

具體整合教程:https://www.bysocket.com/?p=1950

Spring Boot Mybatis 依賴 mybatis-spring-boot-starter

Mybatis 也是業界網際網路流行的資料操作層框架。有兩種形式進行使用 Mybatis。

第一、純 Annotation,第二、使用 xml 配置 SQL。個人推薦使用 xml 配置 SQL,  SQL 和業務程式碼應該隔離,方便和 DBA 校對 SQL。二者 XML 對較長的 SQL 比較清晰。

雖然 XML 形式是我比較推薦的,但是註解形式也是方便的。尤其一些小系統,快速的 CRUD 輕量級的系統。這裡可見,mybatis-spring-boot-starter依賴是非官方提供的。

Springboot 整合 Mybatis 的完整 Web 案例教程:https://www.bysocket.com/?p=1610

Spring Boot 整合 Mybatis Annotation 註解的完整 Web 案例教程:https://www.bysocket.com/?p=1811

另外,搜尋常用 ES,spring-data-elasticsearch 是 Spring Data 的 Community modules 之一,是 Spring Data 對 Elasticsearch 引擎的實現。 

Elasticsearch 預設提供輕量級的 HTTP Restful 介面形式的訪問。相對來說,使用 HTTP Client 呼叫也很簡單。

但 spring-data-elasticsearch 可以更快的支援構建在 Spring 應用上,比如在 application.properties 配置 ES 節點資訊和 spring-boot-starter-data-elasticsearch 依賴,直接在 Spring Boot 應用上使用。

我也寫了點系列部落格在:https://www.bysocket.com/?tag=elasticsearch

還有很多元件無法一一介紹了,比如常用的 Redis 做快取操作等。

三、生產指標監控 Actuator

Starter 元件 Actuator 提供了生產級監控的特性,可以使用 Actuator 來監控應用的一切。

使用方式也很簡單,加入對應的依賴,然後訪問各個 HTTP 請求就可以獲取需要的資訊。具體提供的資訊有

autoconfig    自動配置相關資訊 beans            Spring 容器中的 Bean 相關資訊 configprops     配置項資訊 dump            當前執行緒資訊 env                當前環境變數資訊 health            應用的健康資訊 info            應用基本資訊 metrics            效能指標資訊 mappings        請求路徑資訊 trace            請求呼叫資訊

至於視覺化的話,可以使用 http/ssh/telnet 等方式拉監控資料到視覺化 UI 上即可。進一步可以使用 prometheus 採集 springboot  應用指標,用 Grafana 視覺化監控資料。

這裡我師弟寫一遍教程不錯:http://www.jianshu.com/p/7ecb57a3f326

四、內嵌式容器 Tomcat / Jetty / Undertow

Spring Boot 執行的應用是獨立的一個 Jar 應用,實際上在執行時啟動了應用內部的內嵌容器,容器初始化 Spring 環境及其元件並啟動應用。

但我們也可以自定義配置 內嵌式容器,比如將 Tomcat 換成 Jetty。Spring Boot 能這樣工作,主要靠下面兩點:自動配置和外化配置。

自動配置

Spring Boot 在不需要任何配置情況下,就直接可以執行一個應用。實際上,Spring Boot 框架的 spring-boot-autoconfigure 依賴做了很多預設的配置項,即應用預設值。這種模式叫做 “自動配置”。

Spring Boot 自動配置會根據新增的依賴,自動載入依賴相關的配置屬性並啟動依賴。例如,預設用的內嵌式容器是 Tomcat ,埠預設設定為 8080。

外化配置

Spring Boot 簡化了配置,在 application.properties 檔案配置常用的應用屬性。Spring Boot 可以將配置外部化,這種模式叫做 “外化配置”。

將配置從程式碼中分離外接,最明顯的作用是隻要簡單地修改下外化配置檔案,就可以在不同環境中,可以執行相同的應用程式碼。

所以,Spring Boot 啟動應用,預設情況下是自動啟動了內嵌容器 Tomcat,並且自動設定了預設埠為 8080。

另外還提供了對 Jetty、Undertow 等容器的支援。開發者自行在新增對應的容器 Starter 元件依賴,即可配置並使用對應內嵌容器例項。具體操作如下:

第一步,將 tomcat 依賴排除:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    <exclusions>        <exclusion>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-tomcat</artifactId>        </exclusion>    </exclusions> </dependency>

spring-boot-starter-web 依賴預設使用 Tomcat 作為內嵌容器

第二步,加入對應的 jetty 依賴(這裡也可以是 Undertow 依賴)

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

上面大致介紹了 Spring Boot 2.0 有的那些特性,也就是那些事,最後入門介紹下 WebFlux。

五、Spring 5 & Spring WebFlux

最後,Spring Boot 2.0 支援 Spring 5,Spring 5 具有了強大的特性:WebFlux/Reactor。所以最後來聊聊 WebFlux ,就算入個門吧。

對照下 Spring Web MVC ,Spring Web MVC 是基於 Servlet API 和 Servlet 容器設計的。那麼 Spring WebFlux 肯定不是基於前面兩者,它基於 Reactive Streams API  和 Servlet 3.1+ 容器設計。

那 Reactive Streams API 是什麼?

先理解 Stream 流是什麼?流是序列,是生產者生產,一個或多個消費者消費的元素序列。這種具體的設計模式成為釋出訂閱模式。常見的流處理機制是 pull / push 模式。背壓是一種常用策略,使得釋出者擁有無限制的緩衝區儲存 item,用於確保釋出者釋出 item 太快時,不會去壓制訂閱者。

Reactive Streams (響應式流)是提供處理非阻塞背壓非同步流的一種標準。主要針對的場景是執行時環境(包括 JVM 和 JS)和網路。同樣,JDK 9 java.util.concurrent 包提供了兩個主要的 API 來處理響應流:

  • Flow

  • SubmissionPublisher

為啥只能執行在 Servlet 3.1+ 容器?

大家知道,3.1 規範其中一個新特性是非同步處理支援。

非同步處理支援:Servlet 執行緒不需一直阻塞,即不需要到業務處理完畢再輸出響應,然後結束 Servlet執行緒。

非同步處理的作用是在接收到請求之後,Servlet 執行緒可以將耗時的操作委派給另一個執行緒來完成,在不生成響應的情況下返回至容器。

主要應用場景是針對業務處理較耗時的情況,可以減少伺服器資源的佔用,並且提高併發處理速度。

所以 WebFlux 支援的容器有 Tomcat、Jetty(Non-Blocking IO API) ,也可以像 Netty 和 Undertow 的本身就支援非同步容器。在容器中 Spring WebFlux 會將輸入流適配成 Mono 或者 Flux 格式進行統一處理。

Spring WebFlux 是什麼

0?wx_fmt=png

先看這張圖,上面我們瞭解了容器、響應流。這裡介紹下 Spring WebFlux 是什麼? Spring WebFlux 是 Spring 5 的一個新模組,包含了響應式 HTTP 和 WebSocket 的支援,另外在上層服務端支援兩種不同的程式設計模型:

  • 基於 Spring MVC 註解 @Controller 等

  • 基於 Functional 函式式路由

下面是兩個實現小案例,首先在 pom.xml 加入對應的依賴:

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

基於 Spring MVC 註解 RESTful API

官方案例很簡單,如下:

@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);        } }

但是 PersonRepository 這種 Spring Data Reactive Repositories 不支援 MySQL,進一步也不支援 MySQL 事務。所以用了 Reactivey 原來的 spring 事務管理就不好用了。

jdbc jpa 的事務是基於阻塞 IO 模型的,如果 Spring Data Reactive  沒有升級 IO 模型去支援 JDBC,生產上的應用只能使用不強依賴事務的。

也可以使用透明的事務管理,即每次操作的時候以回撥形式去傳遞資料庫連線 connection。

Spring Data Reactive Repositories  目前支援 Mongo、Cassandra、Redis、Couchbase 。

如果應用只能使用不強依賴資料事務,依舊使用 MySQL ,可以使用下面的實現,程式碼如下:

@RestController @RequestMapping(value = "/city") public class CityRestController {    @Autowired    private CityService cityService;    @RequestMapping(value = "/{id}", method = RequestMethod.GET)    public Mono<City> findOneCity(@PathVariable("id") Long id) {        return Mono.create(cityMonoSink -> cityMonoSink.success(cityService.findCityById(id)));    }    @RequestMapping(method = RequestMethod.GET)    public Flux<City> findAllCity() {        return Flux.create(cityFluxSink -> {            cityService.findAllCity().forEach(city -> {                cityFluxSink.next(city);            });            cityFluxSink.complete();        });    }    @RequestMapping(method = RequestMethod.POST)    public Mono<Long> createCity(@RequestBody City city) {        return Mono.create(cityMonoSink -> cityMonoSink.success(cityService.saveCity(city)));    }    @RequestMapping(method = RequestMethod.PUT)    public Mono<Long> modifyCity(@RequestBody City city) {        return Mono.create(cityMonoSink -> cityMonoSink.success(cityService.updateCity(city)));    }    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)    public Mono<Long> modifyCity(@PathVariable("id") Long id) {        return Mono.create(cityMonoSink -> cityMonoSink.success(cityService.deleteCity(id)));    } }

findAllCity 方法中,利用 Flux.create 方法對響應進行建立封裝成 Flux 資料。並且使用 lambda 寫資料流的處理函式會十分的方便。

Service 層依舊是以前那套邏輯,業務服務層介面如下:

public interface CityService {    /**     * 獲取城市資訊列表     *     * @return     */    List<City> findAllCity();    /**     * 根據城市 ID,查詢城市資訊     *     * @param id     * @return     */    City findCityById(Long id);    /**     * 新增城市資訊     *     * @param city     * @return     */    Long saveCity(City city);    /**     * 更新城市資訊     *     * @param city     * @return     */    Long updateCity(City city);    /**     * 根據城市 ID,刪除城市資訊     *     * @param id     * @return     */    Long deleteCity(Long id); }

具體案例在我的 Github:https://github.com/JeffLi1993/springboot-learning-example

基於 Functional 函式式路由實現 RESTful API

建立一個 Route 類來定義 RESTful HTTP 路由:

import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.accept; import static org.springframework.web.reactive.function.server.RouterFunctions.route; @Configuration public class Routes {    private CityService cityService;    public Routes(CityService cityService) {        this.cityService = cityService;    }    @Bean    public RouterFunction<?> routerFunction() {        return route(                       GET("/api/city").and(accept(MediaType.APPLICATION_JSON)), cityService:: findAllCity).and(route(                       GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)), cityService:: findCityById)                );    } }

RoouterFunction 類似 Spring Web MVC 的 @RequestMapping ,用來定義路由資訊,每個路由會對映到一個處理方法,當接受 HTTP 請求時候會呼叫該處理方法。

建立 HttpServerConfig 自定義 Http Server,這裡建立一個 Netty HTTP 伺服器:

import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; import reactor.ipc.netty.http.server.HttpServer; @Configuration public class HttpServerConfig {    @Autowired    private Environment environment;    @Bean    public HttpServer httpServer(RouterFunction<?> routerFunction) {        HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction);        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);        HttpServer server = HttpServer.create("localhost", Integer.valueOf(environment.getProperty("server.port")));        server.newHandler(adapter);        return server;    } }

自然推薦 Netty 來執行 Reactive 應用,因為 Netty 是基於非同步和事件驅動的。

從案例中,大家也簡單入門瞭解 WebFlux

小結

謝謝大家的閱讀,本文寫的不是那麼精緻。期待過幾天和大家微信溝通交流學習。

by the way , 最近在寫一本小小書,《Spring Boot 2.x 核心技術實戰(上)基礎篇》,針對基礎實踐,精緻地寫了 demo 和講解。

最後還是謝謝。

福利

0?wx_fmt=png

閱讀原文看交流實錄,你想知道的都在這裡