最近测试一个导出功能的时候,后台日志报异常,但是页面的文件下载正常,网上搜了一些,都不是需要的答案。但是 java.lang.IllegalArgumentException: No converter found for return value of type 里面 Soumyajit Swain 的回答给了我一点提示。仔细看我的代码,原来是 Service 里面直接以流的方式把内存数据响应给页面请求,等于结束了 HTTP 请求,但是我们的 Controller 还是一如既往地想返回一个通用的对象作为响应体。
报错信息:
08:43:09 WARN [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] - Failure in @ExceptionHandler com.hebta.retrieval.person.controller.GlobalExceptionHandler#defaultErrorHandler(HttpServletResponse, Throwable)
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.hebta.retrieval.person.common.BaseResponse] with preset Content-Type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:317)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:181)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:124)
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:407)
Service 里面是以文件流的方式写数据:
原来的 Controller 代码:
@ResponseBody
@ApiOperation(value = "数据导出")
@PostMapping("export")
public BaseResponse<Integer> export(@RequestBody ExportDTO dto, HttpServletRequest request, HttpServletResponse response) {
BaseResponse<Integer> resp = new BaseResponse<>(RESPONSE_STATUS.SUCCESS);
try {
exportService.doExport(dto, request, response);
resp.setStatus(RESPONSE_STATUS.SUCCESS);
resp.setMsg("导出文件成功");
} catch (Exception ex) {
resp.setStatus(RESPONSE_STATUS.FAIL);
resp.setMsg("导出文件失败");
}
return resp;
}
知道了原因后,Controller 直接调用 Service 方法就行了,不需要返回什么。
@ApiOperation(value = "数据导出")
@PostMapping("export")
public void export(@RequestBody ExportDTO dto, HttpServletRequest request, HttpServletResponse response) {
try {
exportService.doExport(dto, request, response);
} catch (Exception ex) {
ex.printStackTrace();
}
}