我在请求处理程序周围编写了一种包装器,使它们流式传输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;
}
}
控制器:
@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
}));
}
我所做的只是每隔半秒发送一个空字符串,以保持请求的活动状态。某些工具需要在超时时不关闭它。这里的问题是,我在响应中没有看到任何内容类型头。尽管我从我的控制器方法返回ResponseEntity,但什么都没有,正如这条线程中所说:
https://github.com/spring-projects/spring-framework/issues/18518
看起来只有TEXT_HTML媒体类型可以用于流式传输。难道没有办法流式传输json吗?我甚至使用ObjtMapper手动将我的dtos映射到json字符串,但仍然没有运气。尝试APPLICATION_JSON和APPLICATION_STREAM_JSON-不起作用。在不同的浏览器中尝试-相同的结果。
我还在控制器中手动设置ResponseEntity的内容类型标头。现在,响应中有了标题,但我不确定我的数据是否真的是流式传输的。在Chrome中,我只能看到我的操作结果,而不能看到我正在发送的中间字符(将它们更改为“a”以进行测试)。
我检查了两个选项的请求处理时间:
据我所知,等待状态的意思是:“等待第一个字节出现”。似乎对于发射器,第一个字节出现得更早-这似乎是我需要的。我可以把它看作是我的解决方案有效的证据吗?
也许Spring还有别的办法?我需要的只是通过向浏览器发送一些无用的数据来通知浏览器仍在处理请求,直到实际操作完成,然后返回结果。
任何帮助都将不胜感激。
查看ResponseBodyEmitter#send的源代码,似乎应该在AbstractHttpMessageConverter#addDefaultHeaders方法中设置指定的MediaType,但只有在没有其他contentType头的情况下。
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设置了一个默认头。
作为一种解决方法,您可以尝试通过MVC控制器中的注释设置contentType标头。
例如。
@RequestMapping(value = "/something", produces = MediaType.APPLICATION_JSON_UTF8)
问题内容: 因此,我在Struts2中使用freemarker模板来制定我的响应。但是,由于我也尝试使用taconite,因此需要使用“ text / xml”的内容类型发送响应。我似乎找不到使用freemarker指令设置内容类型的方法,而且我对Struts并不精通,无法知道是否有办法通过它来完成。 那么,我应该怎么做呢? 问题答案: 或者您可以在struts.xml中进行设置
问题内容: 我在注释驱动的Spring MVC Java Web应用程序中运行在Jetty Web服务器上运行(当前在Maven Jetty插件中)。 我正在尝试使用一种仅返回String帮助文本的控制器方法来提供一些AJAX支持。资源采用UTF-8编码,字符串也采用UTF-8编码,但是我来自服务器的回复是 即使我的浏览器发送 我正在以某种方式使用spring的默认配置 我发现了将这个bean添加
问题内容: 我在注释驱动的Spring MVC Java Web应用程序中运行在Jetty Web服务器上运行(当前在Maven Jetty插件中)。 我正在尝试使用一种仅返回String帮助文本的控制器方法来提供一些AJAX支持。资源采用UTF-8编码,字符串也采用UTF-8编码,但是我来自服务器的回复是 即使我的浏览器发送 我正在以某种方式使用spring的默认配置 我发现了将这个bean添加
Spring Boot中REST APIendpoint(控制器类或方法)上的响应内容类型可以使用@Produces注释进行设置。是否有一种方法可以将此应用程序wide设置为REST API中每个endpoint的默认值?例如,与其在每个控制器类或endpoint上编写@produces(“application/json”),还可以在入口应用程序类上设置它吗?或者有没有其他方法来配置默认值,直到
我正在全互联网上尝试所有解决方案,但我无法获得它。 我试图连接使用php curl到一个外部API发送json数据,但我不能设置content_type。 答复: 旋度是活动的 数组(26){["url"]= 7. 无法连接到https://example.com端口xxx:连接被拒绝 答复:bool(假) ... 如果我尝试通过SoapUi: HTTP/1.1 200 Vary:Origin V
我无法在HttpClient上设置内容类型。我接着问了一个问题:如何为HttpClient请求设置Content-Type头?但还是没有运气。 所以我怎么能强迫它,这样它就真的添加了它呢?提前道谢。