我对反应编程非常陌生,我有一个REST服务,它接受一个请求,然后使用WebFlux WebClient调用另一个API。当API以4xx或5xx响应进行响应时,我希望将响应体记录在我的服务中,然后将响应传递给调用方。我已经找到了许多处理响应日志记录的方法,但它们通常会将mono.error返回给调用方,这不是我想要做的。我几乎可以做到这一点,但是当我向我的服务发出请求时,当我返回API返回的4xx代码时,我的客户机只是挂起等待响应的正文,而服务似乎从未完成对流的处理。我使用的是Spring Boot版本2.2.4.发行版。
我得到的是:
@PostMapping(path = "create-order")
public Mono<ResponseEntity<OrderResponse>> createOrder(@Valid @RequestBody CreateOrderRequest createOrderRequest) {
return orderService.createOrder(createOrderRequest);
}
public Mono<ResponseEntity<OrderResponse>> createOrder(CreateOrderRequest createOrderRequest) {
return this.webClient
.mutate()
.filter(OrderService.errorHandlingFilter(ORDERS_URI, createOrderRequest))
.build()
.post()
.uri(ORDERS_URI)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(createOrderRequest)
.exchange()
.flatMap(response -> response.toEntity(OrderResponse.class));
}
public static ExchangeFilterFunction errorHandlingFilter(String uri, CreateOrderRequest request) {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if (clientResponse.statusCode() != null && (clientResponse.statusCode().is5xxServerError() || clientResponse.statusCode().is4xxClientError())) {
return clientResponse.bodyToMono(String.class)
.flatMap(errorBody -> OrderService.logResponseError(clientResponse, uri, request, errorBody));
} else {
return Mono.just(clientResponse);
}
});
}
static Mono<ClientResponse> logResponseError(ClientResponse response, String attemptedUri, CreateOrderRequest orderRequest, String responseBody) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
try {
log.error("Response code {} received when attempting to hit {}, request:{}, response:{}",
response.rawStatusCode(), attemptedUri, objectMapper.writeValueAsString(orderRequest),
responseBody);
} catch (JsonProcessingException e) {
log.error("Error attempting to serialize request object when reporting on error for request to {}, with code:{} and response:{}",
attemptedUri, response.rawStatusCode(), responseBody);
}
return Mono.just(response);
}
return Mono.error(new Exception("Some error"));
我在客户端收到一个500,请求就完成了。如果有人知道为什么当我尝试发回响应时它不会完成,我很想知道我做错了什么。
鱼与熊掌不可兼得!
这里的问题是,您正在尝试消耗响应的主体两次,这是不允许的。通常这样做会得到一个错误。
一旦进入
return clientResponse.bodyToMono(String.class)
response.toEntity(OrderResponse.class)
@Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
return WebClientUtils.toEntity(this, bodyToMono(bodyType));
}
public Mono<ResponseEntity<OrderResponse>> createOrder(CreateOrderRequest createOrderRequest) {
return this.webClient
//no need for mutate unless you already have things specified in
//base webclient?
.post()
.uri(ORDERS_URI)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(createOrderRequest)
.exchange()
//Here you map the response to an entity first
.flatMap(response -> response.toEntity(OrderResponse.class))
//Then run the errorHandler to do whatever
//Use doOnNext since there isn't any reason to return anything
.doOnNext(response ->
errorHandler(ORDERS_URI,createOrderRequest,response));
}
//Void doesn't need to return
public static void errorHandler(String uri, CreateOrderRequest request,ResponseEntity<?> response) {
if( response.getStatusCode().is5xxServerError()
|| response.getStatusCode().is4xxClientError())
//run log method if 500 or 400
OrderService.logResponseError(response, uri, request);
}
//No need for redundant final param as already in response
static void logResponseError(ResponseEntity<?> response, String attemptedUri, CreateOrderRequest orderRequest) {
//Do the log stuff
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
try {
log.error("Response code {} received when attempting to hit {}, request:{}, response:{}",
response.getStatusCodeValue(), attemptedUri, objectMapper.writeValueAsString(orderRequest),
response.getBody());
} catch (JsonProcessingException e) {
log.error("Error attempting to serialize request object when reporting on error for request to {}, with code:{} and response:{}",
attemptedUri, response.getStatusCodeValue(), response.getBody());
}
}
请注意,没有使用ExchangeFilter的真正理由,因为您实际上并没有执行任何筛选,只是根据响应执行一个操作
我打下面的url使用任何Rest客户端,我得到api响应:400坏请求与响应体 输入参数 但是java simple client没有显示响应主体。。下面是java代码。。它只给出了400个坏请求。
我在Alamofire 5.3中收到了大量失败的请求,其中响应对象本身为nil,或者错误为“无法解析响应”。我可以从服务器日志中看到,所有这些请求都返回有效。 这是我的设置: API管理器类: AccessTokenInterceptor: 这个拦截器从插入我的授权令牌 我也使用标准路由器的URL刚需转换,编码是通过JSON序列化(字典)或可编码协议(对象) 奇怪的是,我不认为我在做任何不同于我使
我正在使用带有Robospice(1.4.14)的Revovit(1.6.1)从一些服务中获取数据(响应应该在JSON中)。 在某些情况下,我可能会收到一个HTML错误页面,而不是一个JSON响应。服务器返回一个200状态代码,我不能改变它。在这种情况下,RoboSpice将调用方法。 在那里,我可以获得原始的expetion,但正文是。我是这样得到的: 在研究了reverfit的源代码之后,我发
使用Guzzle,我正在使用JSON格式的一些外部API,通常我获取数据 $data = $request- 但是我无法从这个不同的api中获取数据。数据似乎没有出现在“响应体”中。 这个api调用有效:https://i.ibb.co/80Yk6dx/Screenshot-2.png 这不起作用:https://i.ibb.co/C239ghy/Screenshot-3.png
我在雄猫上部署了一个泽西岛 2.5.1 应用程序。我在我的网络中添加了以下配置.xml: 它打印请求和响应头。但是,它没有在响应中打印请求/响应实体/主体。 我试着和不同的情妇玩,但没有运气,比如: 感谢您的回答。看起来我在上面粘贴了错误的配置。这是我在我的网络上有什么.xml: 它记录标题。但它不记录实体。这是我在日志中看到的: 我的Jersey应用程序部署在Tomcat 7_50服务器上。 如
我使用的是Spring版本4(Spring data),我想将Object作为JSON返回,我想知道以下代码即使不使用xmlRootElement注释用户类也能工作: 任何机构都可以解释吗?当我需要注释要返回为JSON的对象类时,响应体/响应实体是否自己完成工作?