在应用程序中运行 Jetty Web 服务器






4.83/5 (16投票s)
不要将您的应用程序部署到Jetty中,而是将Jetty部署到您的应用程序中
目录
引言
本文的目的是让您快速了解如何在不真正运行应用程序外部的Web服务器并且不创建WAR文件进行部署的情况下,构建和部署您的Web应用程序。目前,我正在开发一个项目,它是一个后台计算引擎,并提供一个简单的Web界面供支持和业务用户监控正在进行的活动。在部署我们的应用程序时,我们只需在应用程序内部启动Jetty Web服务器,就可以轻松访问Web应用程序。
如果您访问Jetty wiki,会提到Jetty的口号是“不要将您的应用程序部署到Jetty中,而是将Jetty部署到您的应用程序中。” 在本文中,我们将通过一个 nice and simple 的应用程序来阐述这个口号。
下载Jetty
在开始创建项目之前,我们需要从Jetty@eclipse downloads网站下载任何稳定版本的Jetty JAR文件。在本文中,我使用了Jetty 7。每个Jetty网站都附带以下捆绑包。
- 核心Jetty Web服务器 (HTTP & Websocket)
- 核心Jetty Servlet容器
- JNDI、JMX、OSGi、JASPI模块
- HTTP客户端
除了Jetty JAR之外,我们还需要在系统上安装JSK 1.6和Eclipse 3.5。一旦这三样东西准备就绪,我们就可以创建我们的应用程序了。
创建一个Eclipse项目
您只需要按照下面提到的步骤在Eclipse中创建一个Java项目。
- 转到Eclipse的“文件”菜单并创建一个Java项目。
- 如果默认的JRE选项设置为JavaSE-1.6,则保留该选项。
- 点击“库”选项卡并选择Jetty JAR文件。
- 项目创建完成后,在项目中再添加两个文件夹:“page”和“WEB-INF”。
项目创建完成后,项目结构应如下所示:
由于项目已设置完毕,我们就可以创建将在应用程序内部启动的Web应用程序了。
创建一个Web应用程序
- 在WEB-INF文件夹中创建一个部署描述符(即web.xml)。这是一个非常基本的描述符,其中只包含欢迎页面的文件名。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <welcome-file-list> <welcome-file>page/index.jsp</welcome-file> </welcome-file-list> </web-app>
- 接下来,我们需要在page文件夹中创建一个index.jsp文件,当我们在Web浏览器中访问URL时,将显示该文件。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1 pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Embedding Jettye</title> </head> <body> <h2>Running Jetty web server from our application!!</h2> </body> </html>
创建一个Jetty服务器实例
- 首先,我们构建一个
WebAppContext
,其中可以定义部署描述符的位置并设置应用程序的上下文路径。这个WebAppContext
需要设置Jetty服务器的头部,这将在本节的后面部分进行说明。以下代码描述了如何构建WebAppContext
。package blog.runjetty.context; import org.eclipse.jetty.webapp.WebAppContext; public class AppContextBuilder { private WebAppContext webAppContext; public WebAppContext buildWebAppContext(){ webAppContext = new WebAppContext(); webAppContext.setDescriptor(webAppContext + "/WEB-INF/web.xml"); webAppContext.setResourceBase("."); webAppContext.setContextPath("/runJetty"); return webAppContext; } }
- 创建WebAppContext后;我们创建一个负责操作
org.eclipse.jetty.server.Server
类实例的类。为此,我构建了一个包装器JettyServer
。它定义了运行端口(默认为8585),设置上下文头部(即设置WebAppContext),启动/停止服务器,并检查服务器是否正在运行。package blog.runjetty.server; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; public class JettyServer { private Server server; public JettyServer() { this(8585); } public JettyServer(Integer runningPort) { server = new Server(runningPort); } public void setHandler(ContextHandlerCollection contexts) { server.setHandler(contexts); } public void start() throws Exception { server.start(); } public void stop() throws Exception { server.stop(); server.join(); } public boolean isStarted() { return server.isStarted(); } public boolean isStopped() { return server.isStopped(); } }
创建一个用户界面来启动和停止服务器
现在我们将构建一个简单的基于Swing的用户界面,其中包含一个启动/停止按钮。根据服务器的状态,它会启动服务器或关闭服务器。- 创建一个
ActionListener
,它实际上会检查服务器的当前状态,并在执行任何操作时切换其状态。在我们的应用程序中,我们创建了ServerStartStopActionListner
,它实现了ActionListener接口
并覆盖了actionPerformed
方法。package blog.runjetty.ui.listener; import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import blog.runjetty.server.JettyServer; public class ServerStartStopActionListner implements ActionListener { private final JettyServer jettyServer; public ServerStartStopActionListner(JettyServer jettyServer) { this.jettyServer = jettyServer; } @Override public void actionPerformed(ActionEvent actionEvent) { JButton btnStartStop = (JButton) actionEvent.getSource(); if(jettyServer.isStarted()){ btnStartStop.setText("Stopping..."); btnStartStop.setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { jettyServer.stop(); } catch (Exception exception) { exception.printStackTrace(); } btnStartStop.setText("Start"); btnStartStop.setCursor (new Cursor(Cursor.DEFAULT_CURSOR)); } else if(jettyServer.isStopped()){ btnStartStop.setText("Starting..."); btnStartStop.setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { jettyServer.start(); } catch (Exception exception) { exception.printStackTrace(); } btnStartStop.setText("Stop"); btnStartStop.setCursor (new Cursor(Cursor.DEFAULT_CURSOR)); } } }
- 创建
ActionListener
后,我们需要创建一个JFrame
。我们的ServerRunner
类继承了JFrame
。它有一个JButton
,该按钮已注册到ServerStartStopActionListner
,以便在单击时执行启动或停止操作。package blog.runjetty.ui; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import blog.runjetty.server.JettyServer; import blog.runjetty.ui.listener.ServerStartStopActionListner; public class ServerRunner extends JFrame{ private static final long serialVersionUID = 8261022096695034L; private JButton btnStartStop; public ServerRunner(final JettyServer jettyServer) { super("Start/Stop Server"); setDefaultCloseOperation(EXIT_ON_CLOSE); btnStartStop = new JButton("Start"); btnStartStop.addActionListener (new ServerStartStopActionListner(jettyServer)); add(btnStartStop,BorderLayout.CENTER); setSize(300,300); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if(jettyServer.isStarted()) { try { jettyServer.stop(); } catch (Exception exception) { exception.printStackTrace(); } } } },"Stop Jetty Hook")); setVisible(true); } }
- 在
ServerRunner
中,我添加了一个ShutdownHook
。因此,每当用户单击窗口右上角的关闭按钮时,它将首先检查服务器是否正在运行。如果正在运行,它将在退出之前停止服务器。
创建一个main方法
现在一切就绪,我们可以创建一个main
方法来触发用户界面。以下代码展示了如何启动界面。package blog.runjetty.main;
import java.awt.EventQueue;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import blog.runjetty.context.AppContextBuilder;
import blog.runjetty.server.JettyServer;
import blog.runjetty.ui.ServerRunner;
public class JettyFromMain {
public static void main(String[] args) {
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ new AppContextBuilder().buildWebAppContext()});
final JettyServer jettyServer = new JettyServer();
jettyServer.setHandler(contexts);
Runnable runner = new Runnable() {
@Override
public void run() {
new ServerRunner(jettyServer);
}
};
EventQueue.invokeLater(runner);
}
}
在这里,您可以发现我首先创建了一个ContextHandlerCollection
并将我们的WebAppContext
添加进去,然后再将处理器设置到我们的服务器中。在run()
方法中,我创建了一个ServerRunner
的实例。在实现以下代码之后,我们的项目结构应该如下所示:

运行应用程序
现在是时候测试我们的应用程序了。按照步骤执行以下操作来运行应用程序,并亲自了解它是如何工作的。
- 从Eclipse运行应用程序。
- 您应该会看到以下窗口
- 单击“开始”按钮。等待按钮文本更改为“停止”,如下图所示
- 打开Web浏览器并访问URL https://:8585/runJetty/。
您的Web应用程序应该已启动并运行,如下图所示 - 现在,单击“停止”按钮或直接关闭窗口。
- 如果单击“停止”按钮,请等待出现“开始”文本。然后刷新您的浏览器窗口,以验证您的Web应用程序不再运行,如下图所示
结论
如您所见,在我们的应用程序中构建和部署Jetty服务器非常容易。现在您已经准备好自行探索,例如仅用几行代码创建SSL连接,使用Spring MVC或任何其他Java Web技术构建更复杂的Web应用程序。有关更多信息,请访问官方Jetty网站:http://www.eclipse.org/jetty/,或者随时在此处发表评论。欢迎任何建议或意见!