日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

响应式web(四):使用Netty作为web容器,基于注解的WebFlux阻塞式与响应式实现

發布時間:2024/2/28 HTML 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 响应式web(四):使用Netty作为web容器,基于注解的WebFlux阻塞式与响应式实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

使用 WebFlux,針對IO密集度比較高的系統,性能會有提升。

  • 使用 Netty 作為 web 容器:注釋掉spring-boot-starter-web,啟動就默認用的 netty 而不是 tomcat 了
  • 基于注解的 WebFlux 阻塞式與響應式實現
  • WebFlux + SSE 服務器推:下面的案例3
  • WebFlux 中的 ServerHttpRequest 與 SpringMVC 的區別

源碼地址

GitHub 地址:https://github.com/HanquanHq/TestReactive

運行效果

本地運行項目后,瀏覽器輸入:

案例1:http://127.0.0.1:8080/person


控制臺輸出:

=========here get===== before return, mono: MonoPeekTerminal return方法線程名稱:reactor-http-nio-4 1. doOnSubscribe...MonoSink getPerson線程名稱:reactor-http-nio-4 getPerson(): Person{id=1, name='person1'} 2. data:Person{id=1, name='person1'} 3. onSuccess:Person{id=1, name='person1'}
案例2:http://127.0.0.1:8080/person/xxoo?name=Tom


控制臺輸出:

In get01, name = Tom In get01, serverHttpRequest = org.springframework.http.server.reactive.ReactorServerHttpRequest@77c0f877 In get01, headers = [Host:"127.0.0.1:8080", Connection:"keep-alive", Cache-Control:"max-age=0", Upgrade-Insecure-Requests:"1", User-Agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36", Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", Sec-Fetch-Site:"none", Sec-Fetch-Mode:"navigate", Sec-Fetch-User:"?1", Sec-Fetch-Dest:"document", Accept-Encoding:"gzip, deflate, br", Accept-Language:"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6", Cookie:"remember_token=11|5ab3b64f1bb566f8155003f396cc0361c8957adb4267161b275bceb5f174ea53015491cbd90f06a5aa38606455a717790a60efe719fa1fbd314a6905027ca6f8; SESSION=7b53f3e5-6059-42fe-a4b6-9dac524364d7"] In get01, parameters = [Tom]
案例3:http://127.0.0.1:8080/person/sse

實現了 WebFlux + SSE 服務器推,不用刷新頁面,也能實時拿到數據,原理類似于瀏覽器下載文件。
下面這9條數據,不是一次加載出來的,是逐個輸出的。

控制臺輸出:

1. sub is: reactor.core.publisher.FluxIterable$IterableSubscription@4ec8ff31 3. data is: haha, 1 3. data is: haha, 2 3. data is: haha, 3 3. data is: haha, 4 3. data is: haha, 5 3. data is: haha, 6 3. data is: haha, 7 3. data is: haha, 8 3. data is: haha, 9 doOnComplete,全部完成了!這里傳一個新線程

附:代碼

目錄結構

PersonController.java(重點)

package com.mashibing.admin.controller;import com.mashibing.admin.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.WebSession; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono;import java.util.Random; import java.util.stream.IntStream;// 使用WebFlux,針對IO密集度比較高的系統,性能會有提升。 @RestController @RequestMapping("/person") public class PersonController {@AutowiredPersonService personService;@GetMapping("")Mono<Object> get() {System.out.println("=========here get=====");Mono<Object> mono = Mono.create(sink -> {//組裝數據序列sink.success(personService.getPerson());}).doOnSubscribe(sub -> {//訂閱數據System.out.println("1. doOnSubscribe..." + sub);}).doOnNext(data -> {//得到數據System.out.println("2. data:" + data);}).doOnSuccess(onSuccess -> {//整體完成System.out.println("3. onSuccess:" + onSuccess);});System.out.println("before return, mono: " + mono);// 得到一個包裝的數據序列,return給了容器// 容器拿到這個序列,再去執行序列里的方法// 這和 ajax 很像// 1. 寫回調接口,讓b調用// 2. 將方法傳過去,看起來像是異步,實質上,阻塞過程在容器內部// 并不是提高效率,只是將阻塞延后System.out.println("return方法線程名稱:" + Thread.currentThread().getName());return mono; // 組織數據的過程,是netty容器做的,獲取數據的過程不依賴controller了}@GetMapping("xxoo")//serverHttpRequest是webFlux特有的,用法也不一樣//拓展思維,SpringCloud Gateway函數式,比zuul的性能高,底層是基于netty的Mono<Object> get01(String name, ServerHttpRequest serverHttpRequest, WebSession webSession) {System.out.println("In get01, name = " + name);System.out.println("In get01, serverHttpRequest = " + serverHttpRequest);//org.springframework.http.server.reactive.ReactorServerHttpRequestSystem.out.println("In get01, headers = " + serverHttpRequest.getHeaders());// [Host:"127.0.0.1:8080", User-Agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0", ...System.out.println("In get01, parameters = " + serverHttpRequest.getQueryParams().get("name"));//[gongluyang]// session 的使用方法if (StringUtils.isEmpty(webSession.getAttribute("code"))) {System.out.println("第一次請求,我要set session 了");webSession.getAttributes().put("code", 111222333);}return Mono.just("me me da!");}// 不引入 spring-webmvc,僅使用 netty 實現@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> sse() {Flux<String> flux = Flux.fromStream(IntStream.range(1, 10).mapToObj(i -> {// map 是映射,理解為遍歷,但是不是遍歷try {Thread.sleep(new Random().nextInt(3000));} catch (InterruptedException e) {e.printStackTrace();}return "haha, " + i;})).doOnSubscribe(sub -> {System.out.println("1. sub is: " + sub);// reactor.core.publisher.FluxIterable$IterableSubscription}).doOnComplete(() -> {System.out.println("doOnComplete,全部完成了!這里傳一個新線程");}).doOnNext(data -> {System.out.println("3. data is: " + data);});return flux;} }

Person.java

package com.mashibing.admin.pojo;public class Person {int id;String name;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;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +'}';} }

PersonService.java

package com.mashibing.admin.service;import com.mashibing.admin.pojo.Person; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux;import java.util.concurrent.ConcurrentHashMap;@Service public class PersonService {static ConcurrentHashMap<Integer, Person> map = new ConcurrentHashMap();static {for (int i = 0; i < 100; i++) {Person person = new Person();person.setId(i);person.setName("person" + i);map.put(i, person);}}public Person getPerson() {try {System.out.println("getPerson線程名稱:" + Thread.currentThread().getName());Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("getPerson(): " + map.get(1));return map.get(1);}public Flux<Person> getPersons() {// 需要讓數據自己變成響應式的,我們關注的是前后端的響應式Flux<Person> personFlux = Flux.fromIterable(map.values());return personFlux;}}

TestReactiveApplication.java

package com.mashibing.admin;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class TestReactiveApplication {public static void main(String[] args) {SpringApplication.run(TestReactiveApplication.class, args);} }

pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>TeatReactive</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies> <!-- 注釋掉這個,啟動就默認用的 netty 而不是 tomcat 了--> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-web</artifactId>--> <!-- </dependency>--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

總結

以上是生活随笔為你收集整理的响应式web(四):使用Netty作为web容器,基于注解的WebFlux阻塞式与响应式实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。