gpt4 book ai didi

java - Spring ResponseBodyEmitter 未在响应中设置 Content-Type header

转载 作者:行者123 更新时间:2023-12-02 01:35:37 25 4
gpt4 key购买 nike

我正在为我的请求处理程序编写一种包装器,以使它们传输 HTTP 响应。我现在拥有的是

处理程序响应包装:

 @Component
public class ResponseBodyEmitterProcessor {

public ResponseBodyEmitter process(Supplier<?> supplier) {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
Executors.newSingleThreadExecutor()
.execute(() -> {
CompletableFuture<?> future = CompletableFuture.supplyAsync(supplier)
.thenAccept(result -> {
try {
emitter.send(result, MediaType.APPLICATION_JSON_UTF8);
emitter.complete();
} catch (IOException e) {
emitter.completeWithError(e);
}
});
while (!future.isDone()) {
try {
emitter.send("", MediaType.APPLICATION_JSON_UTF8);
Thread.sleep(500);
} catch (IOException | InterruptedException e) {
emitter.completeWithError(e);
}
}
});

return emitter;
}
}

Controller :

@RestController
@RequestMapping("/something")
public class MyController extends AbstractController {

@GetMapping(value = "/anything")
public ResponseEntity<ResponseBodyEmitter> getAnything() {
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(process(() -> {
//long operation
}));
}

我正在做的只是每半秒发送一次空字符串以保持请求 Activity 。某些工具需要不因超时而关闭它。这里的问题是我在响应中没有看到任何 Content-Type header 。尽管我从 Controller 方法返回了 ResponseEntity,正如本线程中所述:

https://github.com/spring-projects/spring-framework/issues/18518

看起来只有 TEXT_HTML 媒体类型可以用于流式传输。难道就没有办法传输 json 吗?我什至使用 objectMapper 手动将 dtos 映射到 json 字符串,但仍然没有运气。尝试使用 APPLICATION_JSON 和 APPLICATION_STREAM_JSON - 不起作用。在不同的浏览器中尝试过 - 结果相同。

我还在 Controller 中手动设置 ResponseEntity 的 Content-Type header 。现在响应中有 header ,但我不确定我的数据是否确实进行了流式传输。在 Chrome 中,我只能看到操作结果,看不到我发送的中间字符(将它们更改为“a”以进行测试)。

我检查了两个选项的请求处理时间:

没有发射器(只是普通的 Controller 处理程序) Without emitter

带发射器 With emitter

据我了解,等待状态意味着:“等待第一个字节出现”。似乎发射器第一个字节出现得更早 - 这看起来像我需要的。我可以将其视为我的解决方案有效的证据吗?

也许在 Spring 中有另一种方法可以做到这一点?我需要的只是通过向浏览器发送一些无用的数据来通知浏览器请求仍在处理中,直到实际操作完成 - 然后返回结果。

任何帮助将不胜感激。

最佳答案

查看ResponseBodyEmitter#send的来源,似乎指定的MediaType应该在AbstractHttpMessageConverter#addDefaultHeaders方法中设置,但仅当不存在其他 contentType header 时。

protected void addDefaultHeaders(HttpHeaders headers, T t, MediaType contentType) throws IOException{
if (headers.getContentType() == null) {
MediaType contentTypeToUse = contentType;
// ...
if (contentTypeToUse != null) {
headers.setContentType(contentTypeToUse);
}
}
// ...
}

我建议在那里设置一个断点,看看为什么标题没有被应用。也许@RestController设置了默认 header 。

作为解决方法,您可以尝试通过 MVC Controller 中的注释设置 contentType header 。

例如

@RequestMapping(value = "/something", produces = MediaType.APPLICATION_JSON_UTF8)

关于java - Spring ResponseBodyEmitter 未在响应中设置 Content-Type header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57521188/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com