spring webflux view forward

   Spring5 supports reactive programming based on Spring Reactor3, and provides reactive web development in its spring-webflux module, which can be divided into two styles of programming api: similar to spring-webmvc's annotation-based controller style and functions style.

 

     We know that for the view forward, the request can be forwarded to the xx url by returning a string similar to "forward:xx" in the handler method of the spring-webmvc controller. webflux supports the controller method to return "redirect:xx" for redirection, but until the latest spring 5.0.4, spring-webflux controller still does not support the forward function similar to spring-mvc, see Reactive HTTP request forwarding for related jira , combined with thymeleaf test View forward is indeed not supported, and an error is reported when forward. The org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver.resolveViewName(String, Locale) method in thymeleaf-spring5-3.0.9.RELEASE.jar has the following TODO hint:

    if (viewName.startsWith(FORWARD_URL_PREFIX)) {

            vrlogger.trace("[THYMELEAF] View \"{}\" is a forward, and will not be handled directly by ThymeleafReactiveViewResolver.", viewName);

            // TODO * No view forwarding in Spring WebFlux yet. See https://jira.spring.io/browse/SPR-14537

            return Mono.error(new UnsupportedOperationException("Forwards are not currently supported by ThymeleafReactiveViewResolver"));

        }

 

      Recently, I used spring boot2 (version 2.0.0.M7, relying on spring 5.0.2) to do several projects, such as rest api gateway and image download service. It feels good, the programming style is suitable for human mental model, and the overall throughput is good. Spring-webflux is used instead of spring-webmvc. Of course, spring5 still supports the spring-webmvc module. The reason for using webflux is that its full stack supports asynchronous non-blocking, almost from the front-end control layer--"service layer--"data layer. Asynchronous (mongo/redis, etc. are asynchronous, JDBC does not support asynchronous at present, and some are missing, but asynchronous JDBC is estimated to appear in 19 years), unlike spring-webmvc in high concurrency scenarios, asynchrony relies on one or more Many threads in the thread pool process synchronous tasks to achieve pseudo-asynchrony. Webflux also has a thread pool, but its thread pool capacity is small. It recommends using asynchronous api to write asynchronous tasks. These asynchronous tasks will not block threads when performing io, so as long as A small number of threads can handle many requests. Asynchronous servlet and asynchronous servlet io are temporary solutions to patch the original servlet blocking api, suitable for applications with little business logic, especially io-type applications that may have high latency and high concurrency scenarios , such as api gateway, an application that requires efficient network io forwarding. Of course, the newly designed webflux is more suitable for this application than asynchronous servlet, and its application is wider, and it is also suitable for applications with complex business logic.

    The webflux module abandons the servlet programming model. It does not have concepts and classes such as servlet, servlet filter, context path, and HttpServletRequest. It provides webfilter (it is an interface, not to be confused with the WebFilter annotation in spring-webmvc) and the two mentioned above. different styles of api. The view forward function in webflux controller can be implemented through webflux webfilter.

  

   view forwarding implementation

   fork了github上最新的spring-framework,见https://github.com/wangguobo/spring-framework

   修改涉及到两个模块spring-web和spring-webflux。代码在master分支上,我另开了个分支v5.0.2.RELEASE.patch 也有相应的功能,可以下载编译该分支,使用v5.0.2.RELEASE.patch 版本的spring-web和spring-webflux。

 

   webflux  controller 视图forward演示

    项目使用的pom文件包含如下依赖

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.0.0.M7</version>

        <relativePath/> 

    </parent>

 

    <dependencies>

        <dependency>

              <groupId>org.springframework.boot</groupId>

              <artifactId>spring-boot-starter-thymeleaf</artifactId>

     </dependency>

 

     <dependency>

          <groupId>org.springframework.boot</groupId>

          <artifactId>spring-boot-starter-webflux</artifactId>

     </dependency>

 

      <dependency>

          <groupId>org.springframework</groupId>

          <artifactId>spring-webflux</artifactId>

           <!-- 要使用该版本-->

         <version>5.0.2.RELEASE.patch</versio> 

      </dependency>

 

      <dependency>

          <groupId>org.springframework</groupId>

          <artifactId>spring-web</artifactId>

          <!-- 要使用该版本-->

          <version>5.0.2.RELEASE.patch</version> 

       </dependency>

        ...

  </dependencies>

 

 

   

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

 

@Controller
public class WebfluxForwardDemoController {

@GetMapping("/")
public String home(ServerWebExchange exchange) {
    System.out.println("/");
    //forward:index为相对路径,forward:/index为绝对路径,和servlet forward类似
    return "forward:index";
}

@GetMapping("index")
public String index(Model model,ServerWebExchange exchange) {
    System.out.println("index");
    model.addAttribute("content", "hello");
    return "index";
}

@GetMapping("webflux")
public Mono<String> webflux(ServerWebExchange exchange) {
    System.out.println("webflux");
    return Mono.just("forward:demo");
}

@GetMapping("demo")
public String index(Model model,ServerWebExchange exchange) {
    System.out.println("forward-view");
    model.addAttribute("content", "webflux forward view");
    return "view1";
}

}

   forward会重放请求,请求会重新经过所有webfilter最后到controller(如果根据请求mapping能找到控制器的情况下),如果forward时希望跳过所有webfilter直接转到另一个controller方法,可以返回带前缀through:的字符串,例如 "through:index"。这个through功能也是这次一并实现的。

   

 

Test:
curl http://127.0.0.1:8080/
curl http://127.0.0.1:8080/webflux

   

   

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326287914&siteId=291194637