使用9.2.x。因为这个版本是JDK7的,9.3对应的JDK8。
嵌入模式中运行Jetty意味着放一个HTTP模块到你的应用中,而不是放你的应用到一个HTTP server中。
1 开发一个嵌入式SERVER的步骤
1)创建一个Server实例;
2)添加/配置连接器;
3)添加/配置Handlers和/或Contexts和/或Servlets;
4)启动Server;
5)在server上等待或者使用你的线程做其它事。
Connector负责接收客户端的HTTP请求,请求的处理是由Handler来完成的。
2 主要代码所在地:Handler
处理逻辑在Handler中完成,这也是你的主要代码所在地。
为了对一个请求产生一个响应,Jetty要求你在server上设置一个handler。一个handler可以:
1)测试/修改HTTP请求;
2)产生完整的HTTP响应;
3)调用另一个Handler(看HandlerWrapper);
4)选择一个或多个Handlers调用(看HandlerCollection)。
其核心代码示例:
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
//response.setContentType("text/plain;charset=utf-8");
//response.getWriter().println(new JSONObject(params));
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true); //本Handler将请求标记为已处理。
response.getWriter().println("<h1>"+_greeting+"</h1>");
}
在自定义Handler的时候,必须要实现这个方法,可以直接输出响应,也可以对Request做一些包装再把它交给下一个Handler。
Handler的强大的地方是可以为Jetty Server设置若干Handler,每个Handler完成自己的功能。
传递给handle方法的参数是:
1)target:请求的目标,一个URI或者一个来自指定的分发器的名称;
2)baseRequest:Jetty易变的请求对象,总是被拆开;
3)request:不变的请求对象,可以被一个filter或者servlet包装;
4)response:响应,可以被一个filter或者servlet包装。
handler设置响应状态、content-type、并在使用writer产生响应的body前将请求设置为handled(表示处理完成,不再传递到下一个handler处理)。
Handler集合和包装器
1)HandlerCollection
包含其它多个handler的集合,按顺序调用每一个handler(即使某个Handler将请求标记为已处理,即setHandled(true));。
2)HandlerList
一个handler集合,依次调用每一个handler,直到或者一个异常产生,或者响应被提交,或者request.isHandled()返回true。
3)HandlerWrapper
一个Handler基类,你能以面向方面编程的风格使用链接在一起的Handler。例如,一个标准web应用通过一个context、session、security和servlet handlers的链实现。
4)ContextHandlerCollection
一个特殊的HandlerCollection,使用请求URI(contextPath)的最长前缀选择一个包含的ContextHandler处理这个请求。
多个handler的处理:
public static void main(String[] args) throws Exception
{
Server server = new Server(8081);
HandlerCollection hc =new HandlerCollection();
hc.setHandlers(new Handler[]{new HelloHandler(),new HelloHandlerScond()});
server.setHandler(hc);
server.start();
server.join();
}
3 连接器
上面的代码,Server内部会创建一个默认的连接器实例,监听该端口的请求。然而,我们经常希望能够直接为Server实例初始化和配置一个或者多个连接器。
public static void main(String[] args) throws Exception
{
// The Server
Server server = new Server();
// HTTP connector
ServerConnector http = new ServerConnector(server);
http.setHost("localhost");
http.setPort(8080);
http.setIdleTimeout(30000);
// Set the connector
server.addConnector(http);
// Set a handler
server.setHandler(new HelloHandler());
// Start the server
server.start();
server.join();
}
也可以根据需要,设置多个连接器,比如一个处理HTTP,一个处理HTTPS。
4 嵌入Servlets
Servlet可看成是类似于Jetty Handler,除了请求对象是不可变的。
Servlet在Jetty中被一个ServletHandler处理。
它使用标准路径匹配方法来匹配一个Servlet到一个请求。
public static void main(String[] args) throws Exception
{
Server server = new Server(8080);
ServletHandler handler = new ServletHandler();
server.setHandler(handler);
// HelloServlet就是你按照Servlet的语法写的程序。 handler.addServletWithMapping(HelloServlet.class, "/*");
server.start();
server.join();
}
5 验证程序的响应能力
写一个最简单的程序,做高并发访问的压力测试。
程序如下:
public class RestServer
{
public static void main(String[] args ) throws Exception
{
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
//http.setHost("localhost");
connector.setPort(8080);
//connector.setIdleTimeout(30000);
server.setConnectors(new Connector[] { connector });
server.setHandler(new HelloHandler());
server.start();
server.join();
}
}
// ------- HelloHandler ---------
public class HelloHandler extends AbstractHandler {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
System.out.print("target=" + target + ", baseRequest=" + baseRequest.getQueryString());
response.setContentType("text/plain; charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
String xxx = request.getParameter("xxx");
System.out.println(", xxx=" + xxx);
PrintWriter out = response.getWriter();
out.println("Hello, Jetty. 我来啦!");
baseRequest.setHandled(true);
}
}
- 使用Apache ab做压力测试:
就是httpd里面自带的一个执行文件。
ab -n 100000 -c 100 http://localhost:8080/ab?xxx=a1
ab的常用参数:
-n:总共的请求执行数,缺省是1;
-c:并发数,缺省是1;
-t:测试所进行的总时间,秒为单位,缺省50000s
-p:POST时的数据文件
-w: 以HTML表的格式输出结果
如果要用POST提交数据,增加以下内容:
-p d:/tmp/postfile.txt -T “application/x-www-form-urlencoded”
postfile.txt的内容就是标准的POST数据格式,例如:name=xxx&age=123。
压测结束后,看其结果报告,注意几个数据:
1)Failed requests。失败了多少
2)Requests per second。响应能力
3)Time per request。一个请求的响应时间
因为apache不提供windows版的运行程序下载,所以,需要到ApacheHaus或XAMPP等第三方软件中找。这在Apache http的官网上可以找到他们的链接。在httpd下载页面上,”For Microsoft Windows”这个链接页面上有。
到ApacheHaus中,下载对应版的文件即可,比如对应WIN10的包: Apache 2.4 VC14。下载解压后,到bin目录即可找到ab.exe。
- 使用jstat监测性能(GC等)、jmap监测内存
jps // 找到Jetty程序的pid
jstat -gcutil PID 5000 //开始监测。每5秒(5000毫秒)显示一次
jmap -histo PID | less // 打印每个class的实例数目,内存占用,类全名信息
jstat,一般使用 -gcutil 查看gc情况:
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)
EC、EU:Eden区容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年轻代GC次数和GC耗时
FGC、FGCT:Full GC次数和Full GC耗时
GCT:GC总耗时