请求与响应说明
在使用SpringBootWebFlux编写Web服务应用程序下,ServerRequest和ServerResponse是不可变接口,提供 JDK 8 友好的 HTTP 请求和响应访问。
WebFlux的请求和响应都提供针对Reactive Streams数据流的背压模式。
- ServerRequest提供对HTTP方法、URI、标头和查询参数的访问,而对body主体访问则通过特点方法提供。请求主体用 Reactor Flux或Mono表示;
- ServerResponse提供对HTTP响应的访问,可以使用构建器设置响应状态、添加响应标头或提供正文。响应主体用任何 Reactive Streams 表示Publisher,包括Flux和Mono。
数据与结构示例
前端请求字符串,示例:
{"name": "local","ip": "127.0.0.1"
}
后端SpringBootWebFlux通过ServerRequest对象获取请求body和参数数据流,处理完后通过ServerResponse对象返回响应结果数据流,示例:
/*** 示例:初始化路由对象* @return*/
@Bean
public RouterFunction<ServerResponse> exampleRouterFunction() {return route().GET("/api/example", JSON_ACCEPT, (request)->{return ServerResponse.ok().body(request.bodyToFlux(String.class).doOnNext(item -> System.out.println("receive: " + item)).map(item -> "handle: " + item),String.class);}).build();
}
后端java数据参数映射对象,主要用于序例化与反序例实例对象;
@Data
public class IpVo {private String name;private String ip;
}
获取请求body数据
获取前端body里的字符串
Flux<String> bodyFlux = request.bodyToFlux(String.class);
return ServerResponse.ok().body(bodyFlux.doOnNext(item -> System.out.println("receive: " + item)).map(item -> "handle: " + item),String.class
);
获取前端body中的json数据,用对象接收
return request.bodyToMono(IpVo.class).flatMap(item -> {System.out.println("exec: " + item);Assert.isTrue(isNotEmpty(item.getName()), "The parameter 'name' cannot be empty or null!");Assert.isTrue(isNotEmpty(item.getIp()), "The parameter 'ip' cannot be empty or null!");return this.bodyValue(item);}).onErrorResume(this::errorValue);
获取前端body中的json数据,用map接收
return request.bodyToMono(Map.class).flatMap(item -> {System.out.println("exec: " + item);Assert.isTrue(isNotEmpty(String.valueOf(item.get("name"))), "The parameter 'name' cannot be empty or null!");Assert.isTrue(isNotEmpty(String.valueOf(item.get("ip"))), "The parameter 'ip' cannot be empty or null!");return this.bodyValue(item);}).onErrorResume(this::errorValue);
获取前端body里的字符串流,由于是从exchange交换器中获取原始数据流,则需要对流进行解析与转换成字符串;
return request.exchange().getRequest().getBody().flatMap(dataBuffer -> {String value = null;int count = dataBuffer.readableByteCount();if (count > 0) {byte[] bytes = new byte[count];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);value = new String(bytes, StandardCharsets.UTF_8);}System.out.println("receive:" + value);IpVo vo = null;try {vo = objectMapper.readValue(value, IpVo.class);} catch (JsonProcessingException e) {e.printStackTrace();}return this.bodyValue(vo);
}).next().onErrorResume(this::errorValue);
获取请求参数
获取前端请求url中的参数,方法一
return Mono.empty().flatMap(formData -> {String name = request.queryParam("name").orElse(null);Assert.isTrue(isNotEmpty(name) , "The parameter 'name' cannot be empty or null!");String ip = request.queryParam("ip").orElse(null);Assert.isTrue(isNotEmpty(ip) , "The parameter 'ip' cannot be empty or null!");IpVo vo = new IpVo();vo.setName(name);vo.setIp(ip);return this.bodyValue(vo);}).onErrorResume(this::errorValue);
获取前端请求url中的参数,方法二
return Mono.just(new IpVo()).flatMap(vo -> {String name = request.queryParam("name").orElse("");Assert.isTrue(isNotEmpty(name) , "The parameter 'name' cannot be empty or null!");String ip = request.queryParam("ip").orElse(""); Assert.isTrue(isNotEmpty(ip) , "The parameter 'ip' cannot be empty or null!");vo.setName(name);vo.setIp(ip);return this.bodyValue(vo);
}).onErrorResume(this::errorValue);
获取前端请求表单中的参数
//Content-Type: application/x-www-form-urlencoded
return request.formData().flatMap(form -> {String name = form.getFirst("name");Assert.isTrue(isNotEmpty(name), "The parameter 'name' cannot be empty or null!");String ip = form.getFirst("ip");Assert.isTrue(isNotEmpty(ip), "The parameter 'ip' cannot be empty or null!");return bodyValue(ipService.getIps());
}).onErrorResume(this::errorValue);
响应与数据流处理
返回正常响应和失败响应数据
public Mono<ServerResponse> bodyValue(Object body){return ServerResponse.status(HttpStatus.OK).contentType(new MediaType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8))).bodyValue(Optional.ofNullable(body).orElse(""));
}public Mono<ServerResponse> errorValue(Throwable throwable){log.error("Error:", throwable);return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(new MediaType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8))).bodyValue("{\"message\":\"Error: " + throwable.getMessage() + "\"}");
}public boolean isNotEmpty(String param){return param != null && param.trim().length() > 0;
}