SpringWebFlux-2(控制器配置学习笔记2021.11.09)

SpringWebFlux -2(5.3.12版学习笔记2021.11.09)

1.4 Annotated Controllers(带注释的控制器)

与 Spring MVC 中的相同

Spring WebFlux 提供了一个基于 Comments 的编程模型,其中@Controller@RestController组件使用 Comments 来表达请求 Map,请求 Importing,处理异常等。带 Comments 的控制器具有灵活的方法签名,无需扩展 Base Class 或实现特定的接口。

以下 Lists 显示了一个基本示例:

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String handle() {
        return "Hello WebFlux";
    }
}

1.4.1. @Controller

与 Spring MVC 中的相同

您可以使用标准的 Spring bean 定义来定义控制器 bean。 @Controller原型允许自动检测,并且与 Spring 常规支持保持一致,以支持在 Classpath 中检测@Component类并为其自动注册 Bean 定义。它还充当带 Comments 类的构造型,表明其作为 Web 组件的作用。

要启用对此类@Controller bean 的自动检测,可以将组件扫描添加到 Java 配置中,如以下示例所示:

@Configuration
@ComponentScan("org.example.web") (1)
public class WebConfig {

    // ...
}

@RestController是本身由@Controller@ResponseBody进行元 Comments 的composed annotation,表示其每个方法都继承了类型级别@ResponseBodyComments 的控制器,因此直接将其写入响应主体(与视图分辨率和 HTML 模板渲染相比)。

1.4.2. 请求映射

与 Spring MVC 中的相同

@RequestMapping注解用于将请求 Map 到控制器方法。它具有各种属性,可以通过 URL,HTTP 方法,请求参数,Headers 和媒体类型进行匹配。您可以在类级别使用它来表示共享的 Map,也可以在方法级别使用它来缩小到特定的端点 Map。

也有@RequestMapping的 HTTP 方法特定的快捷方式:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

提供前面的 Comments 是Custom Annotations,因为可以说,大多数控制器方法应该 Map 到特定的 HTTP 方法,而不是使用@RequestMapping,默认情况下,@RequestMapping匹配所有 HTTP 方法。同时,在类级别仍需要@RequestMapping来表示共享 Map。

以下示例使用类型和方法级别的 Map:

@RestController
@RequestMapping("/persons")
class PersonController {

    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}
URI Patterns (url模式)

与 Spring MVC 中的相同

您可以使用全局模式和通配符来 映射请求:

通配符描述例子
?匹配一个字符"/pages/t?st.html"匹配"/pages/test.html""/pages/t3st.html"
*匹配路径段中的零个或多个字符"/resources/*.png" 火柴 "/resources/file.png"``"/projects/*/versions"匹配"/projects/spring/versions"但不匹配"/projects/spring/boot/versions"
**匹配零个或多个路径段直到路径结束"/resources/**"匹配"/resources/file.png""/resources/images/file.png"``"/resources/**/file.png"无效,因为**只允许在路径的末尾。
{name}匹配路径段并将其捕获为名为“name”的变量"/projects/{project}/versions"匹配"/projects/spring/versions"和捕获project=spring
{name:[a-z]+}将正则表达式匹配"[a-z]+"为名为“name”的路径变量"/projects/{project:[a-z]+}/versions"匹配"/projects/spring/versions"但不匹配"/projects/spring1/versions"
{*path}匹配零个或多个路径段,直到路径结束并将其捕获为名为“path”的变量"/resources/{*file}"匹配"/resources/images/file.png"和捕获file=/images/file.png

您还可以声明 URI 变量并使用@PathVariable访问其值,如以下示例所示:

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
    // ...
}

您可以在类和方法级别声明 URI 变量,如以下示例所示:

@Controller
@RequestMapping("/owners/{ownerId}") (1 = 类级url映射)
public class OwnerController {

    @GetMapping("/pets/{petId}") (2 = 方法级 url映射)
    public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
        // ...
    }
}

URI 变量会自动转换为适当的类型,或者引发TypeMismatchException。默认情况下支持简单类型(intlongDate等),您可以注册对任何其他数据类型的支持。参见Type ConversionDataBinder

URI 变量可以显式命名(例如@PathVariable("customId")),但是如果名称相同,则可以省略该详细信息,并使用调试信息或 Java 8 上的-parameters编译器标志编译代码。

语法{*varName}声明了一个与零个或多个剩余路径段匹配的 URI 变量。例如,/resources/{*path}匹配所有文件/resources/,并且"path"变量捕获完整的相对路径。

语法{varName:regex}声明带有正则表达式的 URI 变量,语法为{varName:regex}。例如,给定 URL /spring-web-3.0.5 .jar,以下方法将提取名称,版本和文件 extensions:

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String ext) {
    // ...
}

URI 路径模式也可以嵌入${…}占位符,这些占位符在启动时通过PropertyPlaceHolderConfigurer会针对本地,系统,环境和其他属性源进行解析。您可以使用它来例如基于某些外部配置参数化基本 URL。

Spring WebFlux 使用PathPatternPathPatternParser来获得 URI 路径匹配支持。这两个类都位于spring-web中,并且专门设计用于 Web 应用程序中的 HTTP URL 路径,在 Web 应用程序中,在运行时会匹配大量 URI 路径模式。

Spring WebFlux 不支持后缀模式匹配-与 Spring MVC 不同,在 Spring MVC 中,诸如/person的 Map 也匹配到/person.*。对于基于 URL 的内容协商,如果需要,我们建议使用查询参数,该参数更简单,更明确,并且不易受到基于 URL 路径的攻击。

Pattern Comparison (模式比较)

与 Spring MVC 中的相同

当多个模式与 URL 匹配时,必须将它们进行比较以找到最佳匹配。这是通过PathPattern.SPECIFICITY_COMPARATOR完成的,该PathPattern.SPECIFICITY_COMPARATOR查找更具体的模式。

对于每个模式,都会根据 URI 变量和通配符的数量计算得分,其中 URI 变量的得分低于通配符。总得分较低的模式将获胜。如果两个模式的分数相同,则选择更长的时间。

包罗万象的模式(例如**{*varName})不计入评分,而是始终排在最后。如果两种模式都适用,则选择较长的模式。

可消费媒体类型

与 Spring MVC 中的相同

您可以根据请求的Content-Type缩小请求 Map,如下例所示:

@PostMapping(path = "/pets", consumes = "application/json")
public void addPet(@RequestBody Pet pet) {
    // ...
}

消耗属性还支持否定表达式-例如,!text/plain表示text/plain以外的任何 Content Type。

您可以在类级别声明共享的consumes属性。但是,与大多数其他请求 映射 属性不同,在类级别使用时,方法级别的consumes属性会覆盖而不是扩展类级别的声明。

MediaType提供常用媒体类型的常量,例如APPLICATION_JSON_VALUEAPPLICATION_XML_VALUE

可生产的媒体类型

与 Spring MVC 中的相同

您可以根据Accept请求 Headers 和控制器方法生成的 Content Type 列表来缩小请求 映射,如下例所示:

@GetMapping(path = "/pets/{petId}", produces = "application/json;charset=UTF-8")
@ResponseBody
public Pet getPet(@PathVariable String petId) {
    // ...
}

媒体类型可以指定字符集。支持否定的表达式。例如,!text/plain表示text/plain以外的任何 Content Type。      您可以produces在类级别声明共享属性。然而,与大多数其他请求映射属性不同,当在类级别使用时,方法级别的produces属性会覆盖而不是扩展类级别的声明。

参数和标题

与 Spring MVC 中的相同

您可以根据查询参数条件来缩小请求 映射。您可以测试是否存在查询参数(myParam),查询参数是否不存在(!myParam)或特定值(myParam=myValue)。

以下示例测试具有值的参数:

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue")  // (1 = 检查myParam等于myValue。)
public void findPet(@PathVariable String petId) {
    // ...
}

您还可以将其与请求 Headers 条件一起使用,如以下示例所示:

@GetMapping(path = "/pets", headers = "myHeader=myValue") // (1 =检查myHeader等于myValue。)
public void findPet(@PathVariable String petId) {
    // ...
}
HTTP 头,选项

与 Spring MVC 中的相同

@GetMapping@RequestMapping(method=HttpMethod.GET)透明地支持 HTTP HEAD,以进行请求 映射。控制器方法无需更改。 HttpHandler服务器适配器中应用的响应包装器可确保将Content-LengthHeaders 设置为写入的字节数,而无需实际写入响应。

默认情况下,通过将Allow响应 Headers 设置为所有具有匹配 URL 模式的@RequestMapping方法中列出的 HTTP 方法列表来处理 HTTP OPTIONS。

对于没有 HTTP 方法声明的@RequestMappingAllowHeaders 设置为GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS。控制器方法应始终声明支持的 HTTP 方法(例如,使用 HTTP 方法特定的变体@GetMapping@PostMapping等)。

您可以将@RequestMapping方法显式 Map 到 HTTP HEAD 和 HTTP OPTIONS,但这在通常情况下不是必需的。

自定义注解

与 Spring MVC 中的相同

Spring WebFlux 支持使用composed annotations进行请求 映射。这些注解本身用@RequestMapping进行元注解,并组成它们以更狭窄,更具体的用途重新声明@RequestMapping属性的子集(或全部)。

@GetMapping@PostMapping@PutMapping@DeleteMapping@PatchMapping是组合 Comments 的示例。之所以提供它们,是因为大多数控制器方法应该 Map 到特定的 HTTP 方法,而不是使用@RequestMapping,默认情况下,@RequestMapping匹配所有 HTTP 方法。如果需要组合 Comments 的示例,请查看如何声明它们。

Spring WebFlux 还支持具有自定义请求匹配逻辑的自定义请求 映射 属性。这是一个更高级的选项,它需要子类化RequestMappingHandlerMapping并覆盖getCustomMethodCondition方法,您可以在其中检查 custom 属性并返回自己的RequestCondition

Explicit Registrations (显式注册)

与 Spring MVC 中的相同

您可以以编程方式注册 Handler 方法,这些方法可用于动态注册或高级用例,例如同一处理程序在不同 URL 下的不同实例。以下示例显示了如何执行此操作:

@Configuration
public class MyConfig {

    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) //(1注入目标处理程序和控制器的处理程序映射)
            throws NoSuchMethodException {

        RequestMappingInfo info = RequestMappingInfo
                .paths("/user/{id}").methods(RequestMethod.GET).build(); // (2准备请求 映射 元数据)

        Method method = UserHandler.class.getMethod("getUser", Long.class); // (3获取处理程序方法)

        mapping.registerMapping(info, handler, method); // (4添加注册)
    }
}

1.4.3 处理程序方法

与 Spring MVC 中的相同

@RequestMapping处理程序方法具有灵活的签名,可以从一系列受支持的控制器方法参数和返回值中进行选择。

方法参数

与 Spring MVC 中的相同

需要解析 I/O(例如,读取请求正文)的参数支持 Reactive 类型(Reactor,RxJava,or other)。这在“描述”列中进行了标记。不需要阻塞的参数不应使用 Reactive 类型。

支持 JDK 1.8 的java.util.Optional作为方法参数,并与具有required属性(例如@RequestParam@RequestHeader等)的注解结合使用,并且与required=false等效。

下表显示了受支持的控制器方法参数。

控制器方法参数描述
ServerWebExchange访问完整的ServerWebExchange — 用于 HTTP 请求和响应、请求和会话属性、checkNotModified方法等的容器。
ServerHttpRequest, ServerHttpResponse访问 HTTP 请求或响应。
WebSession访问会话。除非添加属性,否则这不会强制启动新会话。支持反应式。
java.security.Principal当前经过身份验证的用户 -Principal如果已知,可能是特定的实现类。支持反应式。
org.springframework.http.HttpMethod请求的 HTTP 方法。
java.util.Locale当前请求区域设置,由最具体的LocaleResolver可用确定- 实际上是配置的LocaleResolver/ LocaleContextResolver
java.util.TimeZone + java.time.ZoneId与当前请求关联的时区,由 确定LocaleContextResolver
@PathVariable用于访问 URI 模板变量。请参阅URI 模式
@MatrixVariable用于访问 URI 路径段中的名称-值对。请参阅矩阵变量
@RequestParam用于访问 Servlet 请求参数。参数值被转换为声明的方法参数类型。见@RequestParam。请注意,使用@RequestParam是可选的——例如,设置其属性。请参阅此表后面的“任何其他参数”。
@RequestHeader用于访问请求标头。标头值转换为声明的方法参数类型。见@RequestHeader
@CookieValue用于访问 cookie。Cookie 值被转换为声明的方法参数类型。见@CookieValue
@RequestBody用于访问 HTTP 请求正文。正文内容通过使用HttpMessageReader实例转换为声明的方法参数类型。支持反应式。见@RequestBody
HttpEntity<B>用于访问请求标头和正文。身体是用HttpMessageReader实例转换的。支持反应式。见HttpEntity
@RequestPart用于访问multipart/form-data请求中的一部分。支持反应式。请参阅多部分内容多部分数据
java.util.Maporg.springframework.ui.Model、 和org.springframework.ui.ModelMap用于访问在 HTML 控制器中使用的模型,并作为视图呈现的一部分公开给模板。
@ModelAttribute用于访问模型中的现有属性(如果不存在则实例化)并应用数据绑定和验证。见@ModelAttribute以及ModelDataBinder。请注意,使用@ModelAttribute是可选的——例如,设置其属性。请参阅此表后面的“任何其他参数”。
Errors, BindingResult用于访问来自命令对象(即@ModelAttribute参数)的验证和数据绑定的错误 。一种ErrorsBindingResult参数必须立即有效的方法论证后声明。
SessionStatus + 班级 @SessionAttributes用于标记表单处理完成,这会触发对通过类级@SessionAttributes注释声明的会话属性的清理。有关@SessionAttributes更多详细信息,请参阅。
UriComponentsBuilder用于准备相对于当前请求的主机、端口、方案和上下文路径的 URL。请参阅URI 链接
@SessionAttribute用于访问任何会话属性 - 与作为类级@SessionAttributes声明的结果存储在会话中的模型属性相反。有关@SessionAttribute更多详细信息,请参阅 。
@RequestAttribute用于访问请求属性。有关@RequestAttribute更多详细信息,请参阅。
任何其他论点如果方法参数与上述任何一个都不匹配,则默认情况下,@RequestParam如果它是简单类型,则解析为 a ,由BeanUtils#isSimpleProperty确定 @ModelAttribute,否则解析为 a 。
返回值

与 Spring MVC 中的相同

下表显示了受支持的控制器方法返回值。请注意,所有返回值通常都支持 Reactor,RxJava,or other之类的库中的反应类型。

控制器方法返回值描述
@ResponseBody返回值通过HttpMessageWriter实例编码并写入响应。见@ResponseBody
HttpEntity<B>, ResponseEntity<B>返回值指定完整的响应,包括 HTTP 标头,主体通过HttpMessageWriter实例编码并写入响应。见ResponseEntity
HttpHeaders用于返回带有标题但没有正文的响应。
String要与ViewResolver实例解析并与隐式模型一起使用的视图名称- 通过命令对象和@ModelAttribute方法确定。处理程序方法还可以通过声明一个Model参数(前面描述)以编程方式丰富模型。
ViewView实例以使用用于与所述隐式模型一起渲染-通过命令对象和确定@ModelAttribute方法。处理程序方法还可以通过声明一个Model参数(前面描述)以编程方式丰富模型。
java.util.Map, org.springframework.ui.Model要添加到隐式模型的属性,根据请求路径隐式确定视图名称。
@ModelAttribute要添加到模型的属性,视图名称根据请求路径隐式确定。请注意,这@ModelAttribute是可选的。请参阅此表后面的“任何其他返回值”。
Rendering用于模型和视图渲染场景的 API。
void如果方法具有void,可能是异步的(例如,Mono<Void>),返回类型(或null返回值),则被视为已完全处理响应,如果它也有ServerHttpResponseServerWebExchange参数或@ResponseStatus注释。如果控制器进行了正面的 ETag 或lastModified时间戳检查,情况也是如此。// TODO:有关详细信息,请参阅控制器。如果以上都不为真,则void返回类型还可以指示 REST 控制器的“无响应正文”或 HTML 控制器的默认视图名称选择。
Flux<ServerSentEvent>, Observable<ServerSentEvent>, 或其他反应式发出服务器发送的事件。的ServerSentEvent可以在将要写入的数据仅需要被省略包装物(但是,text/event-stream必须要求或在通过映射声明produces属性)。
任何其他返回值如果返回值与上述任何一项都不匹配,则默认情况下将其视为视图名称,如果是Stringvoid(适用默认视图名称选择),或作为要添加到模型的模型属性,除非它是一个简单类型,由BeanUtils#isSimpleProperty确定 ,在这种情况下它仍未解析。
类型转换

与 Spring MVC 中的相同

如果参数声明为String以外的其他内容,则表示基于字符串的请求 Importing 的某些带 Comments 的控制器方法参数(例如@RequestParam@RequestHeader@PathVariable@MatrixVariable@CookieValue)可能需要类型转换。

在这种情况下,将根据配置的转换器自动应用类型转换。默认情况下,支持简单类型(例如intlongDate等)。可以通过WebDataBinder(请参见[mvc-ann-initbinder])或通过向FormattingConversionService注册Formatters(请参见Spring 字段格式)来自定义类型转换。

类型转换中的一个实际问题是空字符串源值的处理。如果null作为类型转换的结果,则将此类值视为缺失值。这可能是对的情况下LongUUID其他目标类型,和。如果要允许null 注入,请required在参数注释上使用标志,或将参数声明为@Nullable.

矩阵变量

与 Spring MVC 中的相同, 需要的自己去官网自行观看, 使用场景很少

@RequestParam

与 Spring MVC 中的使用方式相同

Servlet API“请求参数”概念将查询参数、表单数据和多部分合二为一。但是,在 WebFlux 中,每个都通过 ServerWebExchange. 虽然@RequestParam仅绑定到查询参数,但您可以使用数据绑定将查询参数、表单数据和多部分应用于 命令对象

@RequestParam默认情况下,使用注释的方法参数是必需的,但您可以通过设置 a 的 required 标志@RequestParam tofalse或通过使用java.util.Optional 包装器声明参数来指定方法参数是可选的。

如果目标方法参数类型不是 ,则自动应用类型转换 String。请参阅类型转换

在or 参数@RequestParam上声明注释时,映射将填充所有查询参数。Map<String, String>``MultiValueMap<String, String>

请注意,使用@RequestParam是可选的——例如,设置其属性。默认情况下,任何属于简单值类型(由BeanUtils#isSimpleProperty确定 )且未被任何其他参数解析器解析的参数都被视为使用@RequestParam.

@RequestHeader

与 Spring MVC 中的使用方式相同

您可以使用@RequestHeader注解将请求 Headers 绑定到控制器中的方法参数。

以下示例显示了带有 Headers 的请求:

Host                    localhost:8080
Accept-Encoding         gzip,deflate
........
// 下面的示例获取Accept-Encoding和Host 的值:
@GetMapping("/demo")
public void handle(
        @RequestHeader("Accept-Encoding") String encoding, (1)
        @RequestHeader("Host") long keepAlive) { (2)
    //...
}

如果目标方法参数类型不是String,则会自动应用类型转换。参见[mvc-ann-typeconversion]

Map<String, String>MultiValueMap<String, String>HttpHeaders参数上使用@RequestHeaderComments 时,将使用所有 Headers 值填充 Map。

内置支持可用于将逗号分隔的字符串转换为数组或字符串集合或类型转换系统已知的其他类型。例如,带有@RequestHeader("Accept")Comments 的方法参数可以是String类型,也可以是String[]List<String>类型。

@CookieValue

与 Spring MVC 中使用的方式相同

您可以使用@CookieValue注解将 HTTP cookie 的值绑定到控制器中的方法参数。

如果目标方法参数类型不是String,则会自动应用类型转换。参见[mvc-ann-typeconversion]

// 带有 cookie 的请求: JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
@GetMapping("/demo")
public void handle(@CookieValue("JSESSIONID") String cookie) { (1)
    //...
}
@ModelAttribute

与 Spring MVC 中的相同

您可以在方法参数上使用@ModelAttribute注解来访问模型中的属性,或将其实例化(如果不存在)。 model 属性还覆盖了查询参数的值和名称与字段名称匹配的表单字段。这称为数据绑定,它使您不必处理解析和转换单个查询参数和表单字段的工作。下面的示例绑定Pet的实例:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } (1)

上例中的Pet实例按以下方式解析:

  • 从模型(如果已通过Model添加)。
  • 从 HTTP 会话通过@SessionAttributes
  • 从默认构造函数的调用开始。
  • 从带有匹配查询参数或表单字段的参数的“主要构造函数”的调用开始。参数名称是通过 JavaBeans @ConstructorProperties或字节码中运行时保留的参数名称确定的。

获取模型属性实例后,将应用数据绑定。 WebExchangeDataBinder类将查询参数和表单字段的名称与目标Object上的字段名称匹配。在必要时应用类型转换后,将填充匹配字段。有关数据绑定(和验证)的更多信息,请参见Validation。有关自定义数据绑定的更多信息,请参见DataBinder

数据绑定可能会导致错误。默认情况下,引发WebExchangeBindException,但是,要检查 controller 方法中的此类错误,可以在@ModelAttribute的紧后面添加BindingResult参数,如以下示例所示:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { (1)
    if (result.hasErrors()) {
        return "petForm";
    }
    // ...
}

您可以在数据绑定之后通过添加javax.validation.ValidComments 或 Spring 的@ValidatedComments 来自动应用验证(另请参见Bean validationSpring validation)。

与 Spring MVC 不同,Spring WebFlux 在模型 supports 中支持反应类型,例如Mono<Account>io.reactivex.Single<Account>。您可以声明带有或不带有 Reactive 类型包装器的@ModelAttribute参数,并将根据需要将其解析为实际值。但是,请注意,要使用BindingResult参数,您必须在@ModelAttribute参数之前声明它而不使用反应式类型包装器,如先前所示。另外,您可以通过反应式处理任何错误,如以下示例所示:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public Mono<String> processSubmit(@Valid @ModelAttribute("pet") Mono<Pet> petMono) {
    return petMono
        .flatMap(pet -> {
            // ...
        })
        .onErrorResume(ex -> {
            // ...
        });
}

请注意,使用@ModelAttribute是可选的,例如用于设置其属性。默认情况下,任何不是简单值类型(由BeanUtils#isSimpleProperty确定)且未被其他任何参数解析器解析的参数都将被视为已用@ModelAttributeComments。

@SessionAttributes

与 Spring MVC 中的相同

@SessionAttributes用于在两次请求之间的WebSession中存储模型属性。它是类型级别的 Comments,用于声明特定控制器使用的会话属性。这通常列出应透明地存储在会话中以供后续访问请求的模型属性名称或模型属性类型。

以下示例:

@Controller
@SessionAttributes("pet") // (1使用@SessionAttributesComments。)
public class EditPetForm {
    // ...
}

在第一个请求中,将名称为pet的模型属性添加到模型后,该属性会自动提升为WebSession并保存在其中。它会一直保留在那里,直到另一个控制器方法使用SessionStatus方法参数来清除存储,如以下示例所示:

@Controller
@SessionAttributes("pet")  // (1 使用@SessionAttributesComments。)
public class EditPetForm {

    // ...

    @PostMapping("/pets/{id}")
    public String handle(Pet pet, BindingResult errors, SessionStatus status) { // (2 使用SessionStatus变量。)
        if (errors.hasErrors) {
            // ...
        }
            status.setComplete();
            // ...
        }
    }
}
@SessionAttribute

与 Spring MVC 中的相同

如果您需要访问全局存在(例如,在控制器外部(例如,通过过滤器)Management)并且可能存在或可能不存在的预先存在的会话属性,则可以在方法参数上使用@SessionAttributeComments,作为以下示例显示:

@GetMapping("/")
public String handle(@SessionAttribute User user) {  (1 使用@SessionAttribute)
    // ...
}

对于需要添加或删除会话属性的用例,请考虑将WebSession注入控制器方法。

要将模型属性临时存储在会话中作为控制器工作流的一部分,请考虑使用SessionAttributes,如@SessionAttributes中所述。

@RequestAttribute

与 Spring MVC 中的相同

@SessionAttribute相似,您可以使用@RequestAttribute注解来访问先前创建的预先存在的请求属性(例如WebFilter),如以下示例所示:

@GetMapping("/")
public String handle(@RequestAttribute Client client) { 	(1使用@RequestAttribute)
    // ...
}
Multipart Content (文件上传)

与 Spring MVC 中的相同

Multipart Data中所述,ServerWebExchange提供对 Multipart 内容的访问。在控制器中处理文件上传表单(例如,从浏览器)的最佳方法是通过将数据绑定到command object,如以下示例所示:

class MyForm {

    private String name;

    private MultipartFile file;

    // ...

}

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(MyForm form, BindingResult errors) {
        // ...
    }

}

您还可以在 RESTful 服务方案中从非浏览器 Client 端提交 Multipart 请求。以下示例将文件与 JSON 一起使用:

POST /someUrl
Content-Type: multipart/mixed

--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit

{
    "name": "value"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...

您可以使用@RequestPart来访问各个部分,如以下示例所示:

@PostMapping("/")
public String handle(@RequestPart("meta-data") Part metadata, (1-使用@RequestPart获取元数据)
        @RequestPart("file-data") FilePart file) { (2-使用@RequestPart获取文件)
    // ...
}

要反序列化原始 Component 的内容(例如,类似于@RequestBody的 JSON),可以声明一个具体的目标Object,而不是Part,如以下示例所示:

@PostMapping("/")
public String handle(@RequestPart("meta-data") MetaData metadata) { (1-使用@RequestPart获取元数据)
    // ...
}

您可以@RequestPartjavax.validation.Valid或 Spring 的 @Validated注解结合使用,这会导致应用标准 Bean 验证。验证错误导致WebExchangeBindException400 (BAD_REQUEST) 响应。异常包含BindingResult错误详细信息,也可以在控制器方法中通过使用异步包装器声明参数然后使用与错误相关的运算符来处理:

@PostMapping("/")
public String handle(@Valid @RequestPart("meta-data") Mono<MetaData> metadata){ (1-使用@ValidComments)
    // use one of the onError* operators...    // account.onError
}

要以MultiValueMap的形式访问所有 Multipart 数据,可以使用@RequestBody,如以下示例所示:

@PostMapping("/")
public String handle(@RequestBody Mono<MultiValueMap<String, Part>> parts) { (1-使用@RequestBody)
    // ...
}

要以流方式 Sequences 访问 Multipart 数据,可以将@RequestBodyFlux<Part>结合使用,如以下示例所示:

@PostMapping("/")
public String handle(@RequestBody Flux<Part> parts) { (1-使用@RequestBody)
    // ...
}
@RequestBody

与 Spring MVC 中的使用方式相同

您可以使用@RequestBody注解将请求正文读取并通过HttpMessageReader反序列化为Object

与 Spring MVC 不同点,在 WebFlux 中,@RequestBody方法参数支持响应类型以及完全无阻塞的读取和(Client 端到服务器)流。以下示例使用Mono

@PostMapping("/accounts")
public void handle(@RequestBody Mono<Account> account) {
    // ...
}

您可以使用WebFlux ConfigHTTP 消息编解码器选项来配置或自定义消息阅读器。

您可以将@RequestBodyjavax.validation.Valid或 Spring 的@Validated注解结合使用,这将导致应用标准 Bean 验证。这会导致应用标准 Bean 验证。验证错误会导致WebExchangeBindException,从而导致 400 (BAD_REQUEST) 响应。异常包含BindingResult错误详细信息,可以通过使用异步包装器声明参数然后使用与错误相关的运算符在控制器方法中进行处理:

@PostMapping("/accounts")
public void handle(@Valid @RequestBody Mono<Account> account) {
    // use one of the onError* operators...    // account.onError
}
HttpEntity (请求参数)

与 Spring MVC 中的使用方式相同

HttpEntity与使用@RequestBody大致相同,但基于一个容器对象,该对象公开了请求 Headers 和正文。以下示例使用HttpEntity

@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
    // ...
@ResponseBody

与 Spring MVC 中的使用方式相同

您可以在方法上使用@ResponseBody注解,以使返回值通过HttpMessageWriter序列化到响应主体。以下示例显示了如何执行此操作:

@ResponseBody在类级别上也受支持,在这种情况下,它被所有控制器方法继承。这就是@RestController的效果,它不过是用@Controller@ResponseBody标记的元 Comments。

@ResponseBody支持反应式类型,这意味着您可以返回 Reactor 或 RxJava 类型,并将它们产生的异步值呈现给响应。有关更多详细信息,请参见StreamingJSON rendering

您可以将@ResponseBody方法与 JSON 序列化视图结合使用。有关详情,请参见Jackson JSON

您可以使用WebFlux ConfigHTTP 消息编解码器选项来配置或自定义消息编写。

ResponseEntity (响应参数)

与 Spring MVC 中的使用方式相同

ResponseEntity类似于@ResponseBody,但具有状态和标题。例如:

@GetMapping("/something")
public ResponseEntity<String> handle() {
    String body = ... ;
    String etag = ... ;
    return ResponseEntity.ok().eTag(etag).build(body);
}

WebFlux支持使用单个值的反应性类型,以产生ResponseEntity异步,和/或单和多值的反应性类型的本体。这允许各种异步响应ResponseEntity如下:

  • ResponseEntity<Mono<T>>或者ResponseEntity<Flux<T>>在稍后异步提供主体时立即知道响应状态和标头。使用Mono如果身体由0…1值,或者Flux如果它可以产生多个值。
  • Mono<ResponseEntity<T>>提供所有三个 - 响应状态、标头和正文,稍后异步提供。这允许响应状态和标头根据异步请求处理的结果而变化。
  • Mono<ResponseEntity<Mono<T>>>或者Mono<ResponseEntity<Flux<T>>>是另一种可能,尽管不太常见的选择。它们首先异步提供响应状态和标头,然后是响应正文,也是异步的,其次。
Jackson JSON

Spring 提供了对 Jackson JSON 库的支持。

Jackson 序列化视图

与 Spring MVC 中的使用方式相同

Spring WebFlux 提供对Jackson 的序列化视图的内置支持,该支持仅渲染Object中所有字段的一部分。要将它与@ResponseBodyResponseEntity控制器方法一起使用,可以使用 Jackson 的@JsonView注解来激活序列化视图类,如以下示例所示:

@RestController
public class UserController {

    @GetMapping("/user")
    @JsonView(User.WithoutPasswordView.class)
    public User getUser() {
        return new User("eric", "7!jd#h23");
    }
}

public class User {

    public interface WithoutPasswordView {};
    public interface WithPasswordView extends WithoutPasswordView {};

    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @JsonView(WithoutPasswordView.class)
    public String getUsername() {
        return this.username;
    }

    @JsonView(WithPasswordView.class)
    public String getPassword() {
        return this.password;
    }
}

@JsonView允许一组视图类,但每个控制器方法只能指定一个。如果需要激活多个视图,请使用复合界面。

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值