1
votes

I'm writing a web app that is sending some straight files in response to some requests. I want to handle this in Java, not nginx, et al. In a standard servlet, the only option is to use the java.io.OutputStream of the HttpServletResponse.

File file = ...
response.setContentLength((int)file.length());
FileInputStream in = new FileInputStream(file);            
IOUtils.copy(in, response.getOutputStream());  

This copies byte buffers more than is necessary. I'd like to see if I can improve performance by using NIO buffers and channels. I know Jetty is using NIO under the hood because the "connector" in my server is of class org.eclipse.jetty.server.nio.SelectChannelConnector.

Is there a way to get at the underlying channels from the servlet? Or is there a way to define a Jetty-specific handler that uses java.nio instead of java.io?

Their docs show a Jetty "hello world" handler, but that is also using HttpServletResponse and java.io streams.

2

2 Answers

1
votes

I would take a look at the DefaultServlet, it already does something like this and also serves as an example of how a servlet can use direct buffers to more efficiently serve out a static resource like that.

http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java

Line 758 is the start of the sendData method.

Typically we recommend folks just configure the DefaultServlet if they are concerned with performance in serving static content as it also lets you mess with caching headers and that ilk as well

good luck

0
votes

This copies byte buffers more than is necessary.

Not if you use chunked streaming mode. When you do that there are no byte buffers at all, unless IOUtils.copy() does that, in which case don't use it, write the 4 lines of code yourself.

The reason for the ByteBuffers is that Java will attempt to set the Content-Length response header correctly, by accumulating your output in a BB and then getting its size before sending the headers and then the BB contents as the body. Setting the header yourself has I believe no actual effect.