I have a custom tag that does some processing and then sets a cookie. However, the cookie wasn't being set, and I couldn't figure out why. Another developer pointed out that because we're using a template system, the point at which the tag evaluates, the response header has already been flushed as a part of an include. Since the header has been sent, it doesn't look possible to add the cookie (however, no state exceptions are thrown when I try to do it). Is there a way around this? Does this sound like that might be the problem?
解决方案
Like other folks have said, you really want to avoid having to do this in the first place. You'd like maybe a nice MVC kind of model where you have some servlets that do your heavy work like database and cookies and all that, and then pass control off to a JSP that actually renders the response. Since the JSP isn't called to generate HTML until after your servlets are done, you shouldn't run into grief like this.
It is kind of lame that setCookie doesn't tell you when it fails, but it also makes sense that probably you don't want it to break your entire page. ServletResponse.isCommitted() will tell you if the headers are already written, and consequently if your setCookie() call will fail.
If you are in dire straits and absolutely need to be able to do this (while you look for a better solution), you could create a servlet filter to buffer the response in memory until after your cookie is set. The pattern would be something like this:
doFilter(request, response, chain)
{
BufferedResponse bufferedResponse = new BufferedResponse(response);
try
{
// pass control to the next filter or to the JSP/servlet servicing the request
chain.doFilter(request, bufferedResponse);
}
finally
{
bufferedResponse.flush();
}
}
BufferedResponse would need to implement HttpServletResponse and basically keep everything in memory until you explicitly flush it. At that point it would write out the headers, cookies, and the buffered response body.
This will totally work, but it will cause your web server to use a bunch of extra memory since it has to buffer the entire response body in memory for every request. Also, your pages will load slower since the server can't start sending anything to the client browser until after your page is completely done. Bad juju my friend.