Setting the Content-Length header from a Java Servlet
If you have run the test mentioned on the previous page to
determine whether your Servlet is compatible with keep-alive connections
and found that it isn't, then a solution is to manually set the HTTP Content-Length beader
from your Servlet to the number of bytes that your Servlet is going to output. In a typical
case, you won't actually know this in advance. So the easiest solution is to write all
your servlet's output into a temporary byte buffer, whose length you can
then measure before sending its contents as the final output.
A handy feature of the Java IO framework is its
modular approach to streams. We can write our output to a buffer just as easily as if we
were writing it to the servlet output stream. Where before we would have done this:
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter pw = res.getWriter();
// ... output page to pw...
}
instead, we declare pw as writing to a PrintWriter wrapped around
our buffer:
private static final ENCODING = "UTF-8";
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout, ENCODING ));
// ... output page to pw ...
}
Note that we set the character encoding. Since we're now writing to our
own PrintWriter, it could have a different character encoding to the default one used by
the servlet's writer. It's safer not to rely on the default encoding, and just specify an encoding.
When we set the content length header, we also set the Content-Encoding header. That
way, the client will always be told how we've encoded the page and will hopefully display it correctly.
So the final part of our doGet() method looks as follows:
res.setContentLength(bout.size());
res.setHeader("Content-Encoding", ENCODING);
bout.writeTo(res.getOutputStream());
It so happens that HttpServletResponse has the handy method setContentLength()
which we can use, but essentially all it's doing is setting the ContentLength header.
For the character encoding, there's no such method, so we set the header "manually" using
setHeader().
Another difference is where we write the byte array to. Since we've now turned the
characters into bytes via our own PrintWriter and OutputStreamWriter,
we call res.getOutputStream(). This tells us the place to send Servlet output when
we want to send "raw data" rather than character/textual data.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.