响应式编程-Spring Web Flux理论.一

本文住主要分析SpringFlux的响应式与Servelet阻塞式有优缺点

1、关键词

响应式:异步、观察、高吞吐量、弹性、消息驱动、符合利用现代处理器利用多核、阻塞代码转向非阻塞代码、反应式代码用更少的资源做更多的工作

基于异步的开发模式是相对于同步的开发模式而言。结合具体场景而言,所谓同步是指程序使用者发出请求后,无法使用其他功能而只能等待直到该请求程序处理结果返回;而异步是指程序使用者发出某个请求后,不用等待该请求的程序处理结果返回,而是可正常使用其他功能,待使用其他功能后回过头来可正常查看原有请求的程序处理结果。无论作为开发者还是程序使用者,都不希望程序处理总是处于等待、在等待的状态,通过异步编程模式,程序使用者可以在明知某个任务会耗时较长的情况下,无等待的使用其他功能,从而获得良好的使用体验

SpringMVC 方式实现,同步阻塞的方式,基于 SpringMVC+Servlet+Tomcat
SpringWebflux 方式实现,异步非阻塞 方式,基于 SpringWebflux+Reactor+Netty

第一 两个框架都可以使用注解方式,都运行在 Tomcat 等容器中
第二 SpringMVC 采用命令式编程,Webflux 采用异步响应式编程

无论是从底层数据库,向上到达服务层,最后到 Web 服务层,抑或是在这个流程中所包含的任意中间层组件,整个数据传递链路都应该是采用事件驱动的方式来进行运作的。我们就可以不同步调用方式来处理数据,而是由处于数据库上游的各层组件自动来执行事件。这就是响应式编程的核心特点

相较传统开发所普遍采用的“拉”模式,在响应式编程下,基于事件的触发和订阅机制,这就形成了一种类似“推”的工作方式。这种工作方式的优势就在于,生成事件和消费事件的过程是异步执行的,所以线程的生命周期都很短,也就意味着资源之间的竞争关系较少,服务器的响应能力也就越高。

2、Reactor框架

1.传统的方式
        String name = "Simon";
        String capitalName = name.toUpperCase();
        String greeting = "Hello " + capitalName + "!";
        System.out.println(greeting );

以上是命令式编程的写法,有两个特征:

  1. 串行化
  2. 独占线程
2.Reactor
//单数据
        Mono<String> simon = Mono.just("①")
                .map(s -> s.toUpperCase())
                .map(s -> "Hello " + s + "!");
        System.out.println("执行其他业务");
        simon.subscribe(gn -> System.out.println(gn));

以上是用Reactor的写法,有点像Stream流一样,在处理字符串哪些后,只有调用subscribe()方法才会去最终处理
调用 just 或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才会触发数据流,不订阅什么都不会发生的

//多数据
		Flux<String> filter = Flux.just("①", "②", "③", "④", "⑤", "⑥")
		        .map(s -> s.toLowerCase())
		        .map(s -> "Hello " + s + "!")
		        .distinct()//去重
		        .filter(s -> !s.equals("Hello ③!"));//过滤
		System.out.println("执行其他业务");
		filter.subscribe(s -> System.out.println(s));

以上是有多个数据的写法用的是Flux,Mono是单数据的;

3、Spring Flux

Client代码


import com.lsy.reactor.pojo.User;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

public class Client {

    public static void main(String[] args) {
        //调用服务器地址
        WebClient webClient = WebClient.create("http://127.0.0.1:5794");

        //根据id查询
        String id = "1";
        User userresult = webClient.get().uri("/users/{id}", id)
                .accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
                .block();
        System.out.println(userresult.getName());

        //查询所有
        Flux<User> results = webClient.get().uri("/users")
                .accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);

        results.map(stu -> stu.getName())
                .buffer().doOnNext(System.out::println).blockFirst();
    }
}
Server代码
```java
import com.lsy.reactor.handler.UserHandler;
import com.lsy.reactor.service.UserService;
import com.lsy.reactor.service.UserServiceImpl;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.netty.http.server.HttpServer;


import static org.springframework.http.MediaType.APPLICATION_JSON;
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.toHttpHandler;

public class Server {

    public static void main(String[] args) throws Exception{
        Server server = new Server();
        server.createReactorServer();
        System.out.println("enter to exit");
        System.in.read();
    }

    //1 创建Router路由
    public RouterFunction<ServerResponse> routingFunction() {
        //创建hanler对象
        UserService userService = new UserServiceImpl();
        UserHandler handler = new UserHandler(userService);
        //设置路由
        return RouterFunctions.route(
                GET("/users/{id}").and(accept(APPLICATION_JSON)),handler::getUserById)
                .andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers);
    }

    //2 创建服务器完成适配
    public void createReactorServer() {
        //路由和handler适配
        RouterFunction<ServerResponse> route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);
        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
        //创建服务器
        HttpServer httpServer = HttpServer.create();
        httpServer.handle(adapter).bindNow();
    }
}

响应式需要双方的支持,目前Mysql不支持,Redis已经支持了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值