- 文件服务器
- ContextHandler
- Servlets
- ServletContextHandler
- Connectors
- JMX
添加依赖
1 2 3 4 5 6
| <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.0.M0</version> </dependency>
|
HandlerCollection :维持一个handlers 集合, 然后按顺序依次调用每个handler(注意这个里的handler不管发生什么情况都会执行一遍, 这通常可以作为一个切面用于统计和记日志).
HandlerList:同样维持一个handlers 集合,也是按顺序调用每个handler.但是当有异常抛出, 或者有response返回, 或者 request.isHandled()被设为true.
HandlerWrapper:继承自HandlerWrapper的类可以以面向切面编程的方式将handler通过链式的形式组合在一起.例如一个标准的web应用程序就实现了一个这样的规则, 他将context,session,security,servlet的handler以链式的方式组合在一起.
文件服务器
通过ResourceHandler 指定了资源路径,并且允许列出目录和文件. 下面的例子中就是直接将ResourceHandler映射到根目录/下, 即通过http://localhost:8080/就可以在浏览器上看到所有的文件列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler;
public class Main {
public static void main(String[] args) throws Exception { Server server = new Server(8080);
ResourceHandler fileResourceHandler = new ResourceHandler(); fileResourceHandler.setDirectoriesListed(true); fileResourceHandler.setResourceBase("D:\\repository");
GzipHandler gzip = new GzipHandler(); server.setHandler(gzip);
ContextHandler fileContext = new ContextHandler("/files"); fileContext.setHandler(fileResourceHandler);
ResourceHandler indexResourceHandler = new ResourceHandler(); indexResourceHandler.setDirectoriesListed(true); indexResourceHandler.setWelcomeFiles(new String[]{"index.html"}); indexResourceHandler.setResourceBase(".");
ContextHandler indexContextHandler = new ContextHandler("/"); indexContextHandler.setHandler(indexResourceHandler);
HandlerList handlerList = new HandlerList(); handlerList.addHandler(fileContext); handlerList.addHandler(indexContextHandler);
server.setHandler(handlerList); server.start(); server.join(); } }
|
还可以使用ContextHandler将ResourceHandler映射到其他路径上.
ContextHandler
ContextHandler实现自ScopedHandler. ContextHandler实现的功能是将Http请求路径映射到某个具体处理业务逻辑的Handler上.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import org.eclipse.jetty.server.Handler; 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.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class ManyContexts { public static void main(String[] args) throws Exception { Server server = new Server(8080);
ContextHandler rootContext = new ContextHandler("/"); rootContext.setContextPath("/root"); rootContext.setHandler(new HelloHandler("Root Hello"));
ContextHandler contextFR = new ContextHandler("/fr"); contextFR.setHandler(new HelloHandler("Bonjoir"));
ContextHandler contextV = new ContextHandler("/"); contextV.setVirtualHosts(new String[] { "127.0.0.2" }); contextV.setHandler(new HelloHandler("Virtual Hello"));
ContextHandler resourceBaseHandler = new ContextHandler("/resources"); resourceBaseHandler.setResourceBase("/"); resourceBaseHandler.setHandler(new HelloHandler("Resource Hello"));
ContextHandlerCollection contexts = new ContextHandlerCollection(); contexts.setHandlers(new Handler[] { rootContext, contextFR, contextV, resourceBaseHandler});
server.setHandler(contexts);
server.start(); server.join(); }
public static class HelloHandler extends AbstractHandler {
private String path; public HelloHandler(String path) { this.path = path; }
@Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ServletOutputStream out = response.getOutputStream(); out.print(path); out.flush(); response.setStatus(200); } } }
|
我们看一下测试结果
1 2 3 4 5 6 7 8 9
| ζ curl http://192.168.10.220:8080/ Root Hello%
ζ curl http://192.168.10.220:8080/fr
ζ curl http://192.168.10.220:8080/it
ζ curl 127.0.0.2:8080/ Virtual HelloRoot Hello%
|
Servlets
Servlet是一种标准的处理HTTP请求逻辑的方式. Servlet和Jetty Handler非常像, 但是Servlet得request对象是不可变的.
Jetty的ServletHandler采用将请求映射到一个标准路径上.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler;
public class MinimalServlets { public static void main(String[] args) throws Exception { Server server = new Server(8080);
ServletHandler handler = new ServletHandler(); server.setHandler(handler);
handler.addServletWithMapping(HelloServlet.class, "/*");
server.start(); server.join(); }
public static class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello from HelloServlet</h1>"); } } }
|
ServletContextHandler
在上面的Servlets中我们看到每个Servlet都对应一个完整的URI地址映射, 但是如果我们想在某个特定的URI下, 增加子映射怎么办呢?这就用到了ServletContextHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class ServletContextHandlerTest { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); servletContextHandler.setContextPath("/servlet"); servletContextHandler.addServlet(HelloServlet.class, "/abc"); server.setHandler(servletContextHandler); server.start(); server.join(); }
public static class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello from HelloServlet</h1>"); } } }
|
Connectors
当创建N个connectors应用时, 一般我们会将通用的配置首先提取出来, 使用一个配置类配置这些通用配置. 然后在其他具体Connectors配置时将这个配置传递到具体配置类中, 这样一来就形成了一个链式配置形式.
首先生成一个keystore文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| D:\ssl>keytool -genkey -alias wm -keyalg RSA -keysize 1024 -keypass 123456 -validity 365 -keystore D:\ssl\wm.keystore -storepass 123456 您的名字与姓氏是什么? [Unknown]: wm 您的组织单位名称是什么? [Unknown]: wm 您的组织名称是什么? [Unknown]: wm 您所在的城市或区域名称是什么? [Unknown]: bj 您所在的省/市/自治区名称是什么? [Unknown]: bj 该单位的双字母国家/地区代码是什么? [Unknown]: cn CN=wm, OU=wm, O=wm, L=bj, ST=bj, C=cn是否正确? [否]: y
D:\ssl>
|
然后看一下服务器代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException;
public class ManyConnectors { public static void main(String[] args) throws Exception { File keystoreFile = new File("D:\\ssl\\wm.keystore"); if (!keystoreFile.exists()) { throw new FileNotFoundException(keystoreFile.getAbsolutePath()); }
Server server = new Server();
HttpConfiguration httpConfig = new HttpConfiguration(); httpConfig.setSecureScheme("https"); httpConfig.setSecurePort(8443); httpConfig.setOutputBufferSize(32768);
ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(httpConfig)); http.setPort(8080); http.setIdleTimeout(30000);
SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath()); sslContextFactory.setKeyStorePassword("123456"); sslContextFactory.setKeyManagerPassword("123456");
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); SecureRequestCustomizer src = new SecureRequestCustomizer(); src.setStsMaxAge(2000); src.setStsIncludeSubDomains(true); httpsConfig.addCustomizer(src);
ServerConnector https = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(httpsConfig)); https.setPort(8443); https.setIdleTimeout(500000);
server.setConnectors(new Connector[] { http, https });
ServletHandler handler = new ServletHandler(); handler.addServletWithMapping(HelloServlet.class, "/*"); server.setHandler(handler);
server.start(); server.join(); }
public static class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello from HelloServlet</h1>"); } } }
|
我们使用JMeter模拟客户端进行访问
JMX
服务器开启JMX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.lang.management.ManagementFactory;
import javax.management.remote.JMXServiceURL;
import org.eclipse.jetty.jmx.ConnectorServer; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.Server;
public class ServerWithJMX { public static void main(String[] args) throws Exception { MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
Server server = new Server(8080); server.addBean(mbContainer);
ConnectorServer jmx = new ConnectorServer( new JMXServiceURL("rmi", null, 1999, "/jndi/rmi://localhost:1999/jmxrmi"), "org.eclipse.jetty.jmx:name=rmiconnectorserver"); server.addBean(jmx);
server.start(); server.dumpStdErr(); server.join(); } }
|