What does “HttpServletResponse is committed” mean?

2019-04-11 11:42发布

问题:

As stated in title, what does it mean that HttpServletResponse is committed?

I have some request interceptor, extending HandlerInterceptorAdapter, that overrides postHandle method. Post handle method takes parameter final HttpServletResponse response. In method body there is an if statement checking if response.isCommitted(), what exactly does that check?

private static final String voidResponse = "null";

@Override
    public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws IOException {
        if (!response.isCommitted()) {
            if (DefaultServletHttpRequestHandler.class == handler.getClass()) {
                return;
            }
            response.setStatus(200);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            try (final Writer writer = response.getWriter()) {
                writer.write(voidResponse);
            }
            log.info("void method called, respond with 200 and null");

            response.flushBuffer();
        }
    }

回答1:

ServlerResponse.isCommited() checks if the response has been already committed to the client or not (Means the servlet output stream has been opened to writing the response content).

The committed response holds the HTTP Status and Headers and you can't modify it. It's important also to note that in this case the response content has NOT been written yet, as the headers and status are committed before the content itself.

In such examples as yours the check is required to prevent situations when the response has already been commited but someone is trying to modify it, in which case you will get an IllegalStateException stating that response has already been committed.

UPDATE: I see that you are using Spring controllers. The story differs a bit here.

  • Case 1: If you are using @ResponseBody in your controller method or returning ResponseEntity Spring writes to and commits the response before the postHandle() is called, which makes it impossible to change the response later. That said in this case response.isCommited() statement will always return true and you are not able to modify the response.
  • Case 2: If you don't have the above mentioned annotation and don't return ResponseEntity or controller returns NULL the postHandle() method of interceptor is called after the controller method has been processed, but the response has not been committed yet. This means you can modify the response as you want (e.g. return 200 OK).


回答2:

It is response committed not request. It means response already sent to output stream/client.