Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2013-05-15 19:26:37 -0400
committerGreg Wilkins2013-05-15 19:26:37 -0400
commit76d4859eda56dde318448741559671e54c78d7c9 (patch)
tree15c01f5fd17d8a3824d9abc93327db9f03da5b39 /examples
parentc03cb95e8a832ede39e5faf9f5c4b3ba3e11ecff (diff)
downloadorg.eclipse.jetty.project-76d4859eda56dde318448741559671e54c78d7c9.tar.gz
org.eclipse.jetty.project-76d4859eda56dde318448741559671e54c78d7c9.tar.xz
org.eclipse.jetty.project-76d4859eda56dde318448741559671e54c78d7c9.zip
398467 Servlet 3.1 Non Blocking IO
Improved sendContent API and javadoc. Added FastFileServer example
Diffstat (limited to 'examples')
-rw-r--r--examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java181
1 files changed, 181 insertions, 0 deletions
diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java
new file mode 100644
index 0000000000..dd819acdf7
--- /dev/null
+++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java
@@ -0,0 +1,181 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.embedded;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.StandardOpenOption;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpOutput;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.URIUtil;
+import org.eclipse.jetty.util.resource.Resource;
+
+/* ------------------------------------------------------------ */
+/** Fast FileServer.
+ *
+ * <p>This example shows how to use the Jetty APIs for sending static
+ * as fast as possible using various strategies for small, medium and
+ * large content.</p>
+ * <p>The Jetty {@link DefaultServlet} does all this and more, and to
+ * a lesser extent so does the {@link ResourceHandler}, so unless you
+ * have exceptional circumstances it is best to use those classes for
+ * static content</p>
+ */
+public class FastFileServer
+{
+ public static void main(String[] args) throws Exception
+ {
+ Server server = new Server(8080);
+
+ HandlerList handlers = new HandlerList();
+ handlers.setHandlers(new Handler[] { new FastFileHandler(new File(".")), new DefaultHandler() });
+ server.setHandler(handlers);
+
+ server.start();
+ server.join();
+ }
+
+ static class FastFileHandler extends AbstractHandler
+ {
+ private final MimeTypes _mimeTypes = new MimeTypes();
+ private final File _dir;
+
+ FastFileHandler(File dir)
+ {
+ _dir=dir;
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ // define small medium and large.
+ // This should be turned for your content, JVM and OS, but we will huge HTTP response buffer size as a measure
+ final int SMALL=response.getBufferSize();
+ final int MEDIUM=8*SMALL;
+
+
+ // What file to serve?
+ final File file = new File(_dir,request.getPathInfo());
+
+ // Only handle existing files
+ if (!file.exists())
+ return;
+
+ // we will handle this request
+ baseRequest.setHandled(true);
+
+ // Handle directories
+ if (file.isDirectory())
+ {
+ if (!request.getPathInfo().endsWith(URIUtil.SLASH))
+ {
+ response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH)));
+ return;
+ }
+ String listing = Resource.newResource(file).getListHTML(request.getRequestURI(),request.getPathInfo().lastIndexOf("/") > 0);
+ response.setContentType("text/html; charset=UTF-8");
+ response.getWriter().println(listing);
+ return;
+ }
+
+ // Set some content headers
+ // Jetty DefaultServlet will cache formatted date strings, but we will reformat for each request here
+ response.setDateHeader("Last-Modified",file.lastModified());
+ response.setDateHeader("Content-Length",file.length());
+ response.setContentType(_mimeTypes.getMimeByExtension(file.getName()));
+
+
+
+ // send "small" files blocking directly from an input stream
+ if (file.length()<SMALL)
+ {
+ // need to caste to Jetty output stream for best API
+ ((HttpOutput)response.getOutputStream()).sendContent(FileChannel.open(file.toPath(),StandardOpenOption.READ));
+ return;
+ }
+
+
+ // send not "small" files asynchronously so we don't hold threads if the client is slow
+ final AsyncContext async = request.startAsync();
+ Callback completionCB = new Callback()
+ {
+ @Override
+ public void succeeded()
+ {
+ // Async content write succeeded, so complete async response
+ async.complete();
+ }
+
+ @Override
+ public void failed(Throwable x)
+ {
+ // log error and complete async response;
+ x.printStackTrace();
+ async.complete();
+ }
+ };
+
+
+
+ // send "medium" files from an input stream
+ if (file.length()<MEDIUM)
+ {
+ ((HttpOutput)response.getOutputStream()).sendContent(FileChannel.open(file.toPath(),StandardOpenOption.READ),completionCB);
+ return;
+ }
+
+
+ // for "large" files get the file mapped buffer to send
+ // Typically the resulting buffer should be cached as allocating kernel memory
+ // can be hard to GC on some JVMs. But for this example we will create a new buffer per file
+ ByteBuffer buffer;
+ try (RandomAccessFile raf = new RandomAccessFile(file,"r");)
+ {
+ buffer=raf.getChannel().map(MapMode.READ_ONLY,0,raf.length());
+ }
+
+ // Assuming the file buffer might be shared cached version, so lets take our own view of it
+ buffer=buffer.asReadOnlyBuffer();
+
+
+ // send the content as a buffer with a callback to complete the async request
+ // need to caste to Jetty output stream for best API
+ ((HttpOutput)response.getOutputStream()).sendContent(buffer,completionCB);
+ }
+ }
+}

Back to the top