天天看点

解决getWriter() has already been called for this response异常

近期,查看公司应用日志系统error错误信息时,发现了大量的nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response异常。这个错误以前见到过,也解决过。于是想着趁有点空闲,总结下该错误。如有不对,望各位多包容,欢迎交流。

一、应用日志文件中的错误信息

ERROR 

977

--- [io-

8686

-exec-

10

] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() 

for

servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: getWriter() has already been called 

for

this

response] with root cause

java.lang.IllegalStateException: getWriter() has already been called 

for

this

response

at org.apache.catalina.connector.Response.getOutputStream(Response.java:

575

) ~[tomcat-embed-core-

8.5

.

5

.jar:

8.5

.

5

]

  • 原因分析

IllegalStateException: getWriter() has already been called for this response

        从字面意思不难得出错误原因:HttpServletResponse中的PrintWriter已经被手动调用过了。所以当servlet执行到方法结果处理逻辑时,需要将返回值输出到writer中去,这时发现PrintWriter已经被调用过。于是servlet认为这是使用混乱的逻辑错误,于是抛出错误。

        根本原因:在Controller接口方法中,既手动调用PrintWriter向客户端输出内容,又设置了方法返回值。导致servlet需要两次将结果通过PrintWriter输出到客户端,结果报错。

@RequestMapping

(value=

"/checkGetWriterError"

, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public

ServiceResponse<String> checkGetWriterError(HttpServletResponse response) 

throws

Exception {

log.info(

"验证接口既手动调用输出流flush,又return 返回值.造成异常!"

);

PrintWriter printWriter = response.getWriter();

printWriter.write(ServiceResponse.ok(

"来自printWriter的返回值"

).toString());

printWriter.flush();

//没有该句也是报一样错.

return

ServiceResponse.ok(

"成功了,恭喜你."

);

}

结果:程序正常返回结果,控制台出现异常。

(返回结果中编码问题,不在本文讨论范围,请忽略)

解决getWriter() has already been called for this response异常
  • 源码佐证

解决getWriter() has already been called for this response异常

二、扩展验证附验证结果

  • 验证PrintWriter输出流flush,无返回值

@RequestMapping

(value=

"/checkGetWriterError2"

, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public

void

checkGetWriterError2(HttpServletResponse response) 

throws

Exception {

log.info(

"验证接口手动调用PrintWriter输出流, 无return 返回值. 接口正常执行无异常!"

);

PrintWriter printWriter = response.getWriter();

printWriter.write(ServiceResponse.ok(

"来自printWriter的返回值"

).toString());

printWriter.flush();

}

结果:程序正常返回结果,控制台无异常。

(返回结果中编码问题,不在本文讨论范围,请忽略)

解决getWriter() has already been called for this response异常
  • 调用ServletOutputStream输出流flush,  无返回值

@RequestMapping

(value=

"/checkGetWriterError3"

, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public

void

checkGetWriterError3(HttpServletResponse response) 

throws

Exception {

log.info(

"验证接口手动调用ServletOutputStream输出流, 无return 返回值. 接口正常执行无异常!"

);

ServletOutputStream output = response.getOutputStream();

output.write(ServiceResponse.ok(

"来自ServletOutputStream的返回值"

).toString().getBytes());

output.flush();

}

结果:程序正常返回结果,控制台无异常。

解决getWriter() has already been called for this response异常
  • 调用ServletOutputStream输出流flush,又return 返回值

@RequestMapping

(value=

"/checkGetWriterError4"

, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public

ServiceResponse<String> checkGetWriterError4(HttpServletResponse response) 

throws

Exception {

log.info(

"验证接口手动调用ServletOutputStream输出流, 又执行return 返回值. 接口返回异常!"

);

ServletOutputStream output = response.getOutputStream();

output.write(ServiceResponse.ok(

"来自ServletOutputStream的返回值"

).toString().getBytes());

output.flush();

return

ServiceResponse.ok(

"来自return的返回值."

);

}

结果:程序返回结果不正常,控制台无异常。

不仅ServletOutputStream输出流中的内容被发送到客户端,而且方法返回结果也输出到客户端。

解决getWriter() has already been called for this response异常

继续阅读