教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

spring5.0響應(yīng)式編程入門

更新時(shí)間:2018年12月07日13時(shí)28分 來源:傳智播客 瀏覽次數(shù):

Spring5.0響應(yīng)式編程入門

引言

響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。使用它可以在編程語言中很方便地表達(dá)靜態(tài)或動(dòng)態(tài)的數(shù)據(jù)流,而相關(guān)的計(jì)算模型會(huì)自動(dòng)將變化的值通過數(shù)據(jù)流進(jìn)行傳播。我們可以使用聲明的方式構(gòu)建應(yīng)用程序的能力,形成更加敏感和有彈性的應(yīng)用,所以Spring 5在其核心框架中增加了反應(yīng)系統(tǒng),已經(jīng)開始向聲明式編程的范式轉(zhuǎn)變。

響應(yīng)式編程的優(yōu)勢

• 提高了代碼的可讀性,因此開發(fā)人員只需要關(guān)注定義業(yè)務(wù)邏輯。

• 在高并發(fā)環(huán)境中,可以自然的處理消息。

• 可以控制生產(chǎn)者和消費(fèi)者之間的流量,避免內(nèi)存不足。

• 對(duì)于一個(gè)或多個(gè)線程,IO綁定任務(wù)可以通過異步和非阻塞方式執(zhí)行,而且不阻塞當(dāng)前線程。

• 可以有效的管理多個(gè)連接系統(tǒng)之間的通信。

應(yīng)用場景

• 大量的交易處理服務(wù),如銀行部門。

• 大型在線購物應(yīng)用程序的通知服務(wù),如亞馬遜。

• 股票價(jià)格同時(shí)變動(dòng)的股票交易業(yè)務(wù)。

Spring 5.0前瞻

作為Java中的首個(gè)響應(yīng)式Web框架,Spring 5.0最大的亮點(diǎn)莫過于提供了完整的端到端響應(yīng)式編程的支持。

Spring5.0響應(yīng)式編程入門

如上圖所示左側(cè)是傳統(tǒng)的基于Servlet的Spring Web MVC框架,右側(cè)是spring 5.0新引入的基于Reactive Streams的Spring WebFlux框架,從上往下依次是:Router Functions,WebFlux,Reactive Streams三個(gè)新組件,其中:

• Router Functions: 對(duì)標(biāo)@Controller,@RequestMapping等標(biāo)準(zhǔn)的Spring MVC注解,提供一套函數(shù)式風(fēng)格的API,用于創(chuàng)建Router,Handler和Filter。

• WebFlux: 核心組件,協(xié)調(diào)上下游各個(gè)組件提供響應(yīng)式編程支持。

• Reactive Streams: 一種支持背壓(Backpressure)的異步數(shù)據(jù)流處理標(biāo)準(zhǔn),主流實(shí)現(xiàn)有RxJava和Reactor,Spring WebFlux默認(rèn)集成的是Reactor。

示例代碼

1.創(chuàng)建項(xiàng)目

spring響應(yīng)式開發(fā),需要結(jié)合spring boot來完成,所以使用idea創(chuàng)建springboot項(xiàng)目,選擇Spring Initializr選項(xiàng),jdk選擇1.8以上。

Spring5.0響應(yīng)式編程入門

選擇下一步,設(shè)置groupId和artifactId。

Spring5.0響應(yīng)式編程入門

選擇下一步,選擇web選項(xiàng)中的Reactive web選項(xiàng),表明要?jiǎng)?chuàng)建響應(yīng)式項(xiàng)目,注意Spring Boot的版本為2.0.2。

spring編程入門

選擇下一步,設(shè)置項(xiàng)目的目錄,點(diǎn)擊finish創(chuàng)建項(xiàng)目。

Spring5.0響應(yīng)式編程入門

2.設(shè)置服務(wù)端口

為了避免端口沖突,我們可以在項(xiàng)目的application.properties文件中配置服務(wù)端口。

server.port=9002

3.相關(guān)依賴包

打開項(xiàng)目的pom.xml文件,會(huì)發(fā)現(xiàn)以下幾個(gè)依賴包

org.springframework.boot

spring-boot-starter-webflux

org.springframework.boot

spring-boot-starter-test

test

io.projectreactor

reactor-test

test

其中:

• spring-boot-starter-webflux:webflux依賴包,是響應(yīng)式開發(fā)的核心依賴包,其中包含了spring-boot-starter-reactor-netty 、spring 5 webflux 包,默認(rèn)是通過netty啟動(dòng)的。

• spring-boot-starter-test:springboot的單元測試工具庫。

• reactor-test:Spring 5提供的官方針對(duì)RP框架測試工具庫。

小結(jié)

spring響應(yīng)式開發(fā)需要結(jié)合spring boot來完成,同時(shí)需要引入spring-boot-starter-webflux和reactor-test兩個(gè)依賴包來支持響應(yīng)式開發(fā)。

4.使用webflux創(chuàng)建web應(yīng)用

webflux的使用有兩種方式,基于注解和函數(shù)式編程。這里使用函數(shù)式編程,具體操作如下:

4.1.創(chuàng)建實(shí)體類

public class Good {

private int id;

private String name;

private String price;

public Good(int id,String name,String price){

this.id=id;

this.name=name;

this.price=price;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPrice() {

return price;

}

public void setPrice(String price) {

this.price = price;

}

@Override

public String toString() {

return "Good{" +

"id=" + id +

", name='" + name + '\'' +

", price='" + price + '\'' +

'}';

}

}

分析: 實(shí)體類沒有什么特殊的操作,原來怎么操作現(xiàn)在還是怎么操作。

4.2.創(chuàng)建GoodGenerator

@Configuration

public class GoodGenerator {

public Flux findGoods(){

List goods = new ArrayList<>();

goods.add(new Good(1,"小米","2000"));

goods.add(new Good(2,"華為","4000"));

goods.add(new Good(3,"蘋果","8000"));

return Flux.fromIterable(goods);

}

}

分析: 這里的方法返回的是Flux類型的數(shù)據(jù),F(xiàn)lux是RP中最基礎(chǔ)的數(shù)據(jù)類型之一,對(duì)應(yīng)的是多值數(shù)據(jù)的返回操作,在RP中還有Mono數(shù)據(jù)類型,也是最基礎(chǔ)的數(shù)據(jù)類型之一,對(duì)應(yīng)單值數(shù)據(jù)的返回操作。

注意:這里的GoodGenerator類要加上@Configuration注解。

4.3.創(chuàng)建GoodHandler

@Component

@Configuration

public class GoodHandler {

private final Flux goods;

public GoodHandler(GoodGenerator goodGenerator) {

this.goods = goodGenerator.findGoods();

}

public Mono hello(ServerRequest request) {

return ok().contentType(TEXT_PLAIN)

.body(BodyInserters.fromObject("Hello Spring!"));

}

public Mono echo(ServerRequest request) {

return ok().contentType(APPLICATION_STREAM_JSON)

.body(this.goods,Good.class);

}

}

分析: Handler主要用來處理請(qǐng)求操作,并將Mono返回,Mono中會(huì)封裝響應(yīng)數(shù)據(jù),響應(yīng)數(shù)據(jù)如果是字符串可以使用:

ok().contentType(TEXT_PLAIN).body(BodyInserters.fromObject("Hello Spring!"));

操作,如果是集合數(shù)據(jù)可以使用:

ok().contentType(APPLICATION_STREAM_JSON).body(this.goods,Good.class)

操作。

4.4.創(chuàng)建GoodRouter

@Configuration

public class GoodRouter {

@Bean

public RouterFunction route(GoodHandler goodHandler) {

return RouterFunctions

.route(RequestPredicates.GET("/good")

.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),goodHandler::hello)

.andRoute(RequestPredicates.GET("/goods")

.and(RequestPredicates.accept(MediaType.APPLICATION_STREAM_JSON)),goodHandler::echo);

}

}

分析: GoodRouter主要用來設(shè)置請(qǐng)求路徑和轉(zhuǎn)化HTTP請(qǐng)求,可以使用route()方法和andRoute方法設(shè)置多個(gè)請(qǐng)求路徑和轉(zhuǎn)化操作。

小結(jié)

HTTP請(qǐng)求會(huì)由GoodRouter轉(zhuǎn)發(fā)給對(duì)應(yīng)的Handler,Handler處理請(qǐng)求,并返回Mono,這里的Router類似@RequestMapping,Handler類似Controller

4.4.運(yùn)行測試

實(shí)體類、GoodGenerator、GoodHandler、GoodRouter都已經(jīng)創(chuàng)建完成了,我們可以運(yùn)行項(xiàng)目打開瀏覽器進(jìn)行測試.

瀏覽器輸入http://localhost:9002/good,即可獲取到"Hello Spring!"文本信息

瀏覽器輸入http://localhost:9002/goods,即可獲取到集合信息

到目前為止,一個(gè)簡單的webflux示例已經(jīng)完成。

4.5.單元測試

在項(xiàng)目中我們也可以使用使用一個(gè)Spring 5新引入的測試工具類,WebTestClient,專門用于測試RP應(yīng)用,具體代碼如下:

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class Spring5demoApplicationTests {

@Autowired

private WebTestClient webTestClient;

@Test

public void helloTest() {

String s= webTestClient

.get().uri("/good")

.accept(MediaType.TEXT_PLAIN).exchange()

.expectStatus().isOk().returnResult(String.class)

.getResponseBody().blockFirst();

System.out.println(s);

}

@Test

public void findGoodsTest(){

webTestClient.get().uri("/goods")

.accept(MediaType.APPLICATION_STREAM_JSON)

.exchange().expectStatus().isOk()

.expectHeader().contentType(MediaType.APPLICATION_STREAM_JSON)

.returnResult(Good.class)

.getResponseBody().collectList();

}

}

創(chuàng)建WebTestClient實(shí)例時(shí)可以看到,編寫RP應(yīng)用的單元測試,同樣也是數(shù)據(jù)不落地的流式風(fēng)格

總結(jié)

到此,spring 5.0的響應(yīng)式編程就給大家介紹到這里,這里只是簡單進(jìn)行了一個(gè)響應(yīng)式入門操作,但是也能夠體現(xiàn)出響應(yīng)式編程的特點(diǎn)。當(dāng)然spring 5.0響應(yīng)式編程也不是完美的,它在故障診斷、依賴庫集成、數(shù)據(jù)存儲(chǔ)以及Spring Security安全權(quán)限框架支持等方面還是有局限性的。

0 分享到:
和我們?cè)诰€交談!