getWriter() has already been called for this response
背景
测试图片展示功能,出现报错:
aitrs-manage-app-2024-11-08-1.log-2024-11-08 17:19:50.492 [catalina-exec-44] ERROR aitrs - com.iflytek.aitrs.manage.config.uap.LoginHandlerFilter.doFilter(LoginHandlerFilter.java:149), msg: channel 为空
aitrs-manage-app-2024-11-08-1.log-2024-11-08 17:19:50.496 [catalina-exec-44] INFO aitrs - com.iflytek.aitrs.manage.controller.file.FileController.show(FileController.java:132), msg: 图片id:8d88249cb3b84268bef7dd6f1b6bf5a0
aitrs-manage-app-2024-11-08-1.log-2024-11-08 17:19:54.713 [catalina-exec-44] INFO aitrs - com.iflytek.aitrs.storage.StorageHandle.downloadInputStream(StorageHandle.java:398), msg: 下载文件耗时:2ms
aitrs-manage-app-2024-11-08-1.log:2024-11-08 17:20:11.909 [catalina-exec-44] ERROR aitrs - com.iflytek.aitrs.manage.controller.file.FileController.show(FileController.java:159), msg: getWriter() has already been called for this response
获取图片展示的方法如下:
@GetMapping(value = "show")
public void show(String pictureId, HttpServletResponse response) {
OutputStream os = null;
try {
LoggerUtil.info("图片id:" + pictureId);
if (StringUtils.isAbsEmpty(pictureId)) {
return;
}
byte[] buf;
if ("0".equals(LoadConfig.storageType)){
buf = StorageHandle.downloadBytes(pictureId);
}else{
String file = JedisClientFactory.Singleton.INSTANCE.getJedisClient().hget("AITRS_USER_FILE", pictureId);
buf = StorageHandle.downloadBytes(file);
}
os = response.getOutputStream();
os.write(buf);
os.flush();
} catch (Exception e) {
LoggerUtil.error(e.getMessage());
} finally {
if (os != null) {
try {
os.close();
} catch (Exception e) {
LoggerUtil.error("流关闭异常", e);
}
}
}
}
解决
在这篇博客解决getWriter() has already been called for this response异常里提到了,HttpServletResponse中的PrintWriter已经被手动调用过了。所以当servlet执行到方法结果处理逻辑时,需要将返回值输出到writer中去,这时发现PrintWriter已经被调用过。于是servlet认为这是使用混乱的逻辑错误,于是抛出错误。
但是我的代码里并没有收到调用PrintWriter啊,百思不得其解。折腾了半天,突然注意到这个报错:
这个是在过滤器里校验参数的,点开这个过滤器找到报错信息的位置:
破案了,原来是在过滤器里面调用了PrintWriter
,于是进行改造,如下: