Java HttpMediaTypeNotAcceptableException:找不到可接受的表示形式-MediaType产生不同的结果
使用SpringMVC,我有一个控制器,其端点返回一个SSE发射器Java HttpMediaTypeNotAcceptableException:找不到可接受的表示形式-MediaType产生不同的结果,java,spring-boot,spring-mvc,media-type,Java,Spring Boot,Spring Mvc,Media Type,使用SpringMVC,我有一个控制器,其端点返回一个SSE发射器 @GetMapping(path = "/accept/{amount}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK"), @
@GetMapping(path = "/accept/{amount}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "409", description = "BUSY", content = @Content(schema = @Schema(implementation = MyErrorClass.class))),
@ApiResponse(responseCode = "500", description = "UNEXPECTED_ERROR", content = @Content(schema = @Schema(implementation = MyErrorClass.class)))
})
public SseEmitter accept(@Parameter(description = "Amount to accept") @PathVariable double amount) throws MyException {
ExecutorService service = Executors.newCachedThreadPool();
SseEmitter emitter = new SseEmitter();
myService.accept(amount);
service.execute(() -> {
while(myService.inAcceptanceState()) {
try {
emitter.send(myService.getCurrentAmount());
Thread.sleep(1000);
} catch (InterruptedException | IOException ex) {
emitter.completeWithError(ex);
}
}
try {
emitter.send(myService.getCurrentAmount());
emitter.complete();
} catch (IOException e) {
emitter.completeWithError(e);
}
});
service.shutdown();
return emitter;
}
在上面的代码中,在第一次调用完成之前第二次调用accept()方法时,预期会抛出400错误。到目前为止,我得到以下信息:
2020-09-03 15:22:14.105 WARN 480 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Failure in @ExceptionHandler com.mydomain.common.ExceptionController#handleMyException(Exception)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
这不会使我的springboot服务崩溃,但调用不会终止,因此会导致明显的问题。我注意到,如果我改为
products=MediaType.APPLICATION\u JSON\u STREAM\u VALUE
,它会工作得非常好。正如我所期望的,它返回异常和与该异常相关的错误消息,但我们需要为SSEEmiter使用文本流,我们的消费者也期望这种类型的返回。从我(有限)的理解来看,Spring在响应体上发生了一些神奇的HttpConversion,那么我需要做什么才能使用products=MediaType.APPLICATION\u JSON\u STREAM\u VALUE
返回异常呢?我是否需要编写自己的响应转换器,但这可能看起来…?您没有正确终止执行器。对shutdown的调用并没有达到您可能期望的效果。ExecutorService的javadoc中的一个示例
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
通常,cachedThread池应该是共享资源,不应该在端点内初始化。cachedThreadPool的要点是利用线程重用,避免线程失控创建。如果您真的需要单线程,请使用
我真的不明白你为什么在这里用遗嘱执行人。它似乎没有增加任何价值。您只是在阻止请求处理程序线程在另一个线程中执行代码,而该线程本可以在原始线程中执行。感谢您指出这一点。我认为这是一个很糟糕的复制意大利面案例,虽然不是我实际问题的答案。这个问题似乎与我遇到的问题相似,但没有解决方案:我确实想象@ExceptionHandler可以被利用,但不确定它是否那么简单