目录

    十五.WebFlux中的视图解析和渲染方式


    十五.WebFlux中的视图解析和渲染方式

    在使用Spring WebFlux构建响应式Web应用程序时,视图解析和渲染是至关重要的一部分。本文将深入探讨WebFlux中的视图解析和渲染方式,包括Thymeleaf、Freemarker、Mustache等常用的模板引擎,以及响应式的Server-Sent Events(SSE)和WebSocket推送技术。

    1.引言

    Spring WebFlux是Spring框架的响应式编程扩展,提供了一种基于反应式流的方式来构建Web应用程序。与传统的Servlet API不同,WebFlux采用了异步非阻塞的处理模式,能够更好地支持高并发和大规模的数据处理。在构建Web应用程序时,视图解析和渲染是至关重要的一部分,影响着用户的使用体验和系统的性能表现。因此,了解WebFlux中的视图解析和渲染方式具有重要的意义。

    2.Thymeleaf

    Thymeleaf是一种用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML、XML、JavaScript、CSS和文本。在Spring WebFlux中,可以通过Thymeleaf来实现视图解析和渲染。

    2.1.配置Thymeleaf

    首先,需要在Spring Boot项目的 pom.xml 文件中添加Thymeleaf依赖:

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

    然后,在Spring Boot应用程序的配置文件(如 application.propertiesapplication.yml )中配置Thymeleaf相关属性:

    spring:
      thymeleaf:
        enabled: true
        prefix: classpath:/templates/
        suffix: .html
    

    2.2.创建Thymeleaf模板

    src/main/resources/templates 目录下创建Thymeleaf模板文件,例如 index.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Spring WebFlux Thymeleaf Demo</title>
    </head>
    <body>
        <h1 th:text="'Hello, ' + ${name} + '!'"></h1>
    </body>
    </html>
    

    2.3.渲染Thymeleaf模板

    在WebFlux的控制器中,可以使用 ServerResponse.ok().render() 方法来渲染Thymeleaf模板:

    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.reactive.result.view.Rendering;
    
    @Controller
    public class HelloController {
    
        @GetMapping("/")
        public Rendering index(@RequestParam(defaultValue = "World") String name, Model model) {
            model.addAttribute("name", name);
            return Rendering.view("index").model(model).build();
        }
    }
    

    3.Freemarker

    Freemarker是一种模板引擎,与Thymeleaf类似,也可以用于视图解析和渲染。下面我们来介绍如何在Spring WebFlux中使用Freemarker。

    3.1.配置Freemarker

    首先,需要在Spring Boot项目的 pom.xml 文件中添加Freemarker依赖:

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

    然后,在Spring Boot应用程序的配置文件中配置Freemarker相关属性:

    spring:
      freemarker:
        enabled: true
        template-loader-path: classpath:/templates/
        suffix: .ftl
    

    3.2.创建Freemarker模板

    src/main/resources/templates 目录下创建Freemarker模板文件,例如 index.ftl

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Spring WebFlux Freemarker Demo</title>
    </head>
    <body>
        <h1>Hello, ${name}!</h1>
    </body>
    </html>
    

    3.3.渲染Freemarker模板

    在WebFlux的控制器中,使用 ServerResponse.ok().render() 方法来渲染Freemarker模板:

    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.reactive.result.view.Rendering;
    
    @Controller
    public class HelloController {
    
        @GetMapping("/")
        public Rendering index(@RequestParam(defaultValue = "World") String name, Model model) {
            model.addAttribute("name", name);
            return Rendering.view("index").model(model).build();
        }
    }
    

    4.Mustache

    Mustache是一种逻辑-less模板语言,可以用于HTML、配置文件等。下面介绍如何在Spring WebFlux中使用Mustache。

    4.1.配置Mustache

    首先,在Spring Boot项目的 pom.xml 文件中添加Mustache依赖:

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

    然后,在Spring Boot应用程序的配置文件中配置Mustache相关属性:

    spring:
      mustache:
        enabled: true
        prefix: classpath:/templates/
        suffix: .mustache
    

    4.2.创建Mustache模板

    src/main/resources/templates 目录下创建Mustache模板文件,例如 index.mustache

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Spring WebFlux Mustache Demo</title>
    </head>
    <body>
        <h1>Hello, {{name}}!</h1>
    </body>
    </html>
    

    4.3.渲染Mustache模板

    在WebFlux的控制器中,使用 ServerResponse.ok().render() 方法来渲染Mustache模板:

    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.reactive.result.view.Rendering;
    
    @Controller
    public class HelloController {
    
        @GetMapping("/")
        public Rendering index(@RequestParam(defaultValue = "World") String name, Model model) {
            model.addAttribute("name", name);
            return Rendering.view("index").model(model).build();
        }
    }
    

    5.SSE和WebSocket

    在Spring WebFlux中,Server-Sent Events(SSE)和WebSocket都是用于实现实时推送的技术。它们可以让服务器端主动向客户端发送数据,而不需要客户端发起请求。这两种技术在实时性和推送性方面有所不同,下面将详细介绍它们的特点和使用方法。

    5.1.Server-Sent Events(SSE)

    Server-Sent Events是一种基于HTTP协议的实时推送技术,它允许服务器端单向向客户端发送数据。SSE建立在HTTP长连接之上,通过将多个数据块依次发送给客户端来实现数据推送,这些数据块以文本格式发送,每个数据块以一个特定的MIME类型(text/event-stream)标识。

    5.1.1.SSE的特点

    • 单向通信 :SSE只支持服务器端向客户端的单向通信,客户端无法向服务器端发送消息。
    • 基于HTTP :SSE建立在HTTP协议之上,使用标准的HTTP连接和头部。
    • 文本格式 :SSE发送的数据以文本格式发送,可以是任意格式的文本数据。
    • 事件驱动 :SSE基于事件模型,服务器端可以发送不同类型的事件给客户端,客户端通过监听这些事件来处理数据。

    5.1.2.在Spring WebFlux中使用SSE

    在Spring WebFlux中,可以通过使用 SseEmitterFlux 来实现SSE。下面分别介绍这两种方法:

    5.1.2.1.使用SseEmitter

    import org.springframework.http.codec.ServerSentEvent;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
    import reactor.core.publisher.Flux;
    import java.time.Duration;
    
    @RestController
    public class SSEController {
    
        @GetMapping("/sse")
        public SseEmitter sseEmitter() {
            SseEmitter emitter = new SseEmitter();
            Flux.interval(Duration.ofSeconds(1))
                .map(seq -> ServerSentEvent.builder(seq).data("SSE message " + seq).build())
                .subscribe(emitter::send);
            return emitter;
        }
    }
    

    在上面的示例中,我们创建了一个 SseEmitter 对象,并使用 Flux.interval() 来定时发送数据。每隔一秒钟,就会发送一条SSE消息给客户端。

    5.1.2.2.使用Flux

    import org.springframework.http.codec.ServerSentEvent;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import reactor.core.publisher.Flux;
    import java.time.Duration;
    
    @RestController
    public class SSEController {
    
        @GetMapping(value = "/sse", produces = "text/event-stream")
        public Flux<ServerSentEvent<String>> sse() {
            return Flux.interval(Duration.ofSeconds(1))
                    .map(seq -> ServerSentEvent.<String>builder()
                            .id(String.valueOf(seq))
                            .event("sse-event")
                            .data("SSE message " + seq)
                            .build());
        }
    }
    

    在上面的示例中,我们直接返回一个 Flux 对象,并设置 producestext/event-stream ,告诉Spring该接口产生的是SSE事件流。然后使用 Flux.interval() 来定时发送SSE消息。

    5.2.WebSocket

    WebSocket是一种全双工通信协议,可以在客户端和服务器端之间建立持久连接,并允许双方在任意时刻发送数据。WebSocket建立在TCP协议之上,相比HTTP协议具有更低的延迟和更高的效率。

    5.2.1.WebSocket的特点

    • 双向通信 :WebSocket支持客户端和服务器端之间的双向通信,双方可以随时发送和接收数据。
    • 基于TCP :WebSocket建立在TCP协议之上,使用长连接来保持通信。
    • 二进制和文本数据 :WebSocket既支持文本数据,也支持二进制数据。
    • 低延迟 :WebSocket具有低延迟和高效率的特点,适用于实时性要求较高的应用场景。

    5.2.2.在Spring WebFlux中使用WebSocket

    在Spring WebFlux中,可以通过 WebSocketHandler 来处理WebSocket连接和消息。下面是一个简单的示例:

    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.reactive.socket.WebSocketHandler;
    import org.springframework.web.reactive.socket.WebSocketMessage;
    import org.springframework.web.reactive.socket.WebSocketSession;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    import java.time.Duration;
    
    @RestController
    public class WebSocketController {
    
        @GetMapping("/websocket")
        public WebSocketHandler handleWebSocket() {
            return session -> {
                Flux<WebSocketMessage> messageFlux = Flux.interval(Duration.ofSeconds(1))
                        .map(seq -> session.textMessage("WebSocket message " + seq));
                return session.send(messageFlux);
            };
        }
    }
    

    在上面的示例中,我们创建了一个 WebSocketHandler 对象,并使用 Flux.interval() 来定时发送WebSocket消息。

    5.3.SSE vs WebSocket

    • SSE :适用于服务器单向向客户端推送数据,例如实时通知、实时监控等场景。
    • WebSocket :适用于双向通信的场景,例如实时聊天、在线游戏、股票交易等,需要客户端和服务器端进行实时交互的场景。

    5.4.示例代码

    下面是一个简单的示例,演示了如何在Spring WebFlux中实现SSE和WebSocket:

    import org.springframework.http.codec.ServerSentEvent;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.reactive.socket.WebSocketHandler;
    import org.springframework.web.reactive.socket.WebSocketMessage;
    import org.springframework.web.reactive.socket.WebSocketSession;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import java.time.Duration;
    
    @RestController
    public class RealtimeController {
    
        // SSE
        @GetMapping("/sse")
        public Flux<ServerSentEvent<String>> sse() {
            return Flux.interval(Duration.ofSeconds(1))
                    .map(seq -> ServerSentEvent.<String>builder()
                            .id(String.valueOf(seq))
                            .event("sse-event")
                            .data("SSE message " + seq)
                            .build());
        }
    
        // WebSocket
        @GetMapping("/websocket")
        public WebSocketHandler handleWebSocket() {
            return session -> {
                Flux<WebSocketMessage> messageFlux = Flux.interval(Duration.ofSeconds(1))
                        .map(seq -> session.textMessage("WebSocket message " + seq));
                return session.send(messageFlux);
            };
        }
    }
    

    在这个示例中,我们分别定义了两个接口,一个用于SSE(/sse),另一个用于WebSocket(/websocket)。通过访问这两个接口,客户端可以实时接收到服务器端发送的消息。

    6.总结

    本文介绍了在Spring WebFlux中使用Thymeleaf、Freemarker和Mustache等模板引擎进行视图解析和渲染的方法,同时也介绍了基于SSE和WebSocket的实时推送技术。选择合适的视图解析和渲染方式取决于项目的需求和团队的偏好,开发者可以根据具体情况进行选择。同时,了解实时推送技术也有助于构建更加动态和交互性的Web应用程序。

    end
    站长头像 知录

    你一句春不晚,我就到了真江南!

    文章0
    浏览0

    文章分类

    标签云