Contents

Jetty部署Web应用程序

1. 概述

在本文中,我们将快速概述 Jetty Web 服务器,然后介绍部署 WAR 文件的各种方法。

Jetty 是一个开源的 Java HTTP Web 服务器和一个 servlet 容器。Jetty 更常用于 Java 生态系统中的机器对机器通信。

2. 项目设置

最新版本的 Jetty 总是可以通过这个链接 下载。我们将使用 Maven 从命令行创建一个非常基本的 Java Web 应用程序,我们将在示例中使用它。

在本文中,我们使用的是目前最新版本的 Jetty 9.x。

让我们转到我们的控制台,导航到我们选择的位置并运行以下命令:

mvn archetype:generate -DgroupId=com.blogdemo -DartifactId=jetty-app 
  -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

此命令将在我们当前位置的新jetty-app文件夹中创建一个完整的 Java Web 应用程序。它只是使用 Maven 创建 Java 应用程序的众多方法之一,它符合我们的目的。

由于我们要处理 WAR 文件,让我们导航到项目根目录并构建它:

cd jetty-app

使用 Maven 构建:

mvn package

然后jetty-app.war将在位置jetty-app/target/jetty-app.war 创建。

3. Jetty结构

Context 路径。指相对于服务器地址的位置,代表 Web 应用程序的名称。

例如,如果我们的 Web 应用程序放在*$JETTY_HOME\webapps\myapp目录下,它将通过 URL http://localhost/myapp 访问,其Context 路径将是/myapp*。

WAR。是以 ZIP 格式打包 Web 应用程序目录层次结构的文件的扩展名,是 Web Archive 的缩写。Java Web 应用程序通常打包为 WAR 文件以进行部署。WAR 文件可以在命令行上创建,也可以使用 Eclipse 之类的 IDE 创建。

4. 复制WAR部署

将 Web 应用程序部署到 Jetty 服务器的最简单方法可能是将 WAR 文件复制到*$JETTY_HOME/webapps*目录中。

复制后,我们可以通过导航到*$JETTY_HOME*并运行命令来启动服务器:

java -jar start.jar

Jetty 将在启动时扫描其*$JETTY_HOME/webapps目录以部署 Web 应用程序。我们的新应用程序将部署在/jetty-app*Context 中。

当我们从浏览器加载 URL http://localhost:8080/jetty-app 时,我们应该看到我们的应用程序运行*Hello world!*打印到屏幕上。

5. 使用Context 文件部署

Jetty Web 服务器为我们提供了一种方法来部署位于文件系统中任何位置的 Web 存档,方法是我们为它创建一个Context 文件。

这样,即使我们的 WAR 文件位于桌面上,或者我们选择将其保存在 Maven 放置包的jetty-app/target中,我们也可以在*$JETTY_HOME/webapps*中创建其Context 文件。

让我们通过从webapps中删除刚刚部署的jetty-app.war来取消部署它。然后,我们将使用以下代码创建jetty-app.xml并将其放在webapps中:

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" 
  "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/jetty</Set>
    <Set name="war">absolute/path/to/jetty-app.war</Set>
</Configure>

此Context 文件必须与我们的 WAR 同名,并带有 XML 文件扩展名。请注意,我们已将contextPath属性设置为*/jetty*。这意味着我们将从 URL http://localhost:8080/jetty 访问我们的 Web 应用程序。

这种自定义Context 路径的能力是在 Jetty 中部署 WAR 的Context 文件方法的一大优势,因为某些应用程序名称可能不方便用于此目的。

6. 使用 Jetty Maven 插件进行部署

6.1. 默认部署

jetty Maven 插件帮助我们在构建 Java Web 应用程序时进行快速测试和迭代。为了能够使用它部署和运行应用程序,我们只需要在pom.xml中添加插件:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.3.11.v20160721</version>
</plugin>

最新版本可以通过这个 Maven 链接 找到。

在执行下一步之前,我们必须确保在端口8080上运行的 Jetty 实例已停止。

要在添加插件后部署我们的应用程序,我们导航到pom.xml所在的根目录并运行以下命令:

mvn jetty:run

此命令创建一个新的实例,插件将应用程序部署到它。我们可以通过加载http://localhost:8080 来访问它。

jetty Maven 插件会持续扫描 Web 项目的任何更改并不断重新部署它。

6.2. 更改ContextPath

在上一小节中,应用程序部署在*/下。但是,如果我们想像以前一样在给定的Context路径下部署,例如/jetty*,我们将不得不以不同的方式配置插件。

我们将插件声明更改为以下 XML:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.3.11.v20160721</version>
    <configuration>
        <webApp>
            <contextPath>/jetty</contextPath>
        </webApp>
    </configuration>
</plugin>

请注意我们如何添加配置块来进一步自定义我们的部署。根据人们的需要,存在几个配置选项可以放置在此块内。 在这些更改之后,我们可以像以前一样重新运行插件并通过http://localhost:8080/jetty 访问我们的应用程序。

6.3. 更改端口

可能面临的一种情况是端口正在使用异常。可能我们有一个在端口8080上运行的实例用于生产,但我们仍处于开发阶段,并希望从使用 Maven 插件进行部署所带来的易于迭代中受益。

在这种情况下,我们必须在不同的端口上运行我们的测试服务器。让我们将插件配置更改为以下 XML:

<configuration>
    <webApp>
        <contextPath>/jetty</contextPath>
    </webApp>
    <httpConnector>
        <port>8888</port>
    </httpConnector>
</configuration>

当我们重新运行我们的 Maven 插件时,我们将能够从http://localhost:8888/jetty 访问我们的应用程序。

值得注意的是,使用 jetty Maven 插件,我们不需要安装和运行 jetty 实例。相反,它会创建自己的实例。

7. 使用 Jetty Runner 进行部署

就像 jetty Maven 插件一样,jetty-runner 提供了一种快速简便的方式来部署和运行我们的 Web 应用程序。使用 jetty-runner,我们也不需要安装和运行单独的 jetty 服务器实例。

7.1. Jetty Maven 设置

要使用 jetty-runner 快速部署和运行我们的 Web 应用程序,我们可以通过以下Maven 链接 下载最新版本。

使用 jetty-runner,我们只需要将其下载的 jar 放在我们喜欢的任何地方,并准备好我们网络档案的文件系统路径。

我们可以从命令行传入配置参数,也可以通过一个命令在不同的Context 中部署大量应用程序并绑定到不同的端口。

我已将我的 jetty-runner jar 放在与jetty-app目录相同的层次结构中。那是包含我们的 Web 应用程序的目录。

7.2. 基本部署

让我们使用 jetty-runner 部署我们的 WAR:

java -jar jetty-runner-9.4.0.M1.jar jetty-app/target/jetty-app.war

这个命令,就像 Maven 插件的情况一样,创建一个实例并将提供的 WAR 部署到它。WAR 路径可以是绝对路径或相对路径。

我们可以使用http://localhost:8080 加载这个应用程序。

7.3. 使用Context路径部署

要像以前一样在*/jetty*下部署:

java -jar jetty-runner-9.4.0.M1.jar --path /jetty jetty-app/target/jetty-app.war

可通过http://localhost:8080/jetty 访问。

7.4. 在给定端口上部署

在给定端口号上部署:

java -jar jetty-runner-9.4.0.M1.jar --port 9090 jetty-app/target/jetty-app.war

可通过http://localhost:9090 访问。

7.5. 部署多个 WAR

要使用相同的命令部署多个 WAR,我们使用*–path*参数使每个 WAR 唯一:

java -jar jetty-runner --path /one one.war --path /two two.war

然后,我们将通过http://localhost:8080/one 访问one.war,通过http://localhost:8080/two 访问 two.war 。

8. 使用 Cargo Maven 插件部署

Cargo 是一个多功能库,允许我们以标准方式操作各种类型的应用程序容器。

8.1. Cargo部署设置

在本节中,我们将了解如何使用 Cargo 的 Maven 插件将 WAR 部署到 Jetty,在这种情况下,我们将 WAR 部署到 Jetty 9.x 实例。

为了牢牢掌握整个过程,我们将从头开始,从命令行创建一个新的 Java Web 应用程序:

mvn archetype:generate -DgroupId=com.blogdemo -DartifactId=cargo-deploy 
  -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

这将在cargo-deploy目录中创建一个完整的 Java Web 应用程序。如果我们按原样构建、部署和加载此应用程序,它将打印*Hello World!*在浏览器中。

由于我们的 Web 应用程序不包含任何 servlet,因此我们的web.xml文件将非常基本。因此,导航到我们新创建的项目的WEB-INF文件夹并创建一个web.xml,如果它还没有自动创建,则包含以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://Java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://Java.sun.com/xml/ns/javaee 
      http://Java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>cargo-deploy</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

为了让 Maven 能够在不输入完全限定名称的情况下识别 cargo 的命令,我们需要在 Maven 的settings.xml 的插件组中添加 cargo Maven 插件。

作为根settings元素的直接子元素,添加以下内容:

<pluginGroups>
    <pluginGroup>org.codehaus.cargo</pluginGroup>
</pluginGroups>

8.2. 本地部署

在本小节中,我们将编辑pom.xml以适应我们的新部署要求。 添加插件如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <version>1.5.0</version>
            <configuration>
                <container>
                    <containerId>jetty9x</containerId>
                    <type>installed</type>
                    <home>Insert absolute path to jetty 9 installation</home>
                </container>
                <configuration>
                    <type>existing</type>
                    <home>Insert absolute path to jetty 9 installation</home>
                </configuration>
            </configuration>
       </plugin>
    </plugins>
</build>

请注意,我们将打包明确定义为 WAR,否则,我们的构建将失败。在插件部分,我们然后添加 cargo maven2 插件。

可以在此处 找到最新版本。此外,我们添加了一个配置部分,我们告诉 Maven 我们正在使用 Jetty 容器以及现有的 Jetty 安装。

通过将容器类型设置为installed,我们告诉 Maven 我们在机器上安装了一个 Jetty 实例,并且我们提供了此安装的绝对 URL。

通过将配置类型设置为existing,我们告诉 Maven 我们有一个正在使用的现有设置,不需要进一步的配置。

另一种方法是告诉 cargo 下载并设置通过提供 URL 指定的 Jetty 版本。但是,我们的重点是WAR 部署

值得注意的是,无论我们使用的是 Maven 2.x 还是 Maven 3.x,cargo maven2 插件都适用于两者。

我们现在可以通过执行以下命令来安装我们的应用程序:

mvn install

并通过运行部署它:

mvn cargo:deploy

如果 Maven 和 Jetty 控制台一切顺利,那么我们应该能够通过加载http://localhost:8080/cargo-deploy 来运行我们的 Web 应用程序。

如果我们检查*$JETTY_HOME/webapps文件夹,我们将找到一个部署描述符文件,或者我们之前称为由 cargo 创建的名为cargo-deploy.xml*的Context 文件。

8.3. 远程部署

默认情况下,Jetty 不具备远程部署的可能性。为了给 Jetty 添加这样的支持,Cargo 使用了Jetty 远程部署Web 应用程序。

这意味着我们必须下载一个由 Cargo 开发人员预先创建的 Web 应用程序 WAR,将该 WAR 部署到目标容器。

每次我们想使用 cargo Maven 插件部署到这个远程服务器时,它都会使用我们的 WAR 向远程服务器上的部署者应用程序发送一个 HTTP 请求以进行部署。

这个远程部署器可以在这里 找到。前往工具部分并下载cargo-jetty-7-and-onwards-deployer WAR。

安全注意事项

我们必须在 jetty 中设置一个安全领域,然后才能工作,用于身份验证。在远程服务器的 $JETTY_HOME/etc 目录中创建一个名为*realm.properties的文件。*文件内容为:

admin:password,manager

admin是客户端可以访问受保护应用程序的用户名,password是密码,manager是客户端在被授予访问权限之前必须拥有的角色。

我们还必须在部署应用程序中声明我们的安全要求。我们将从 jetty 下载页面解压我们下载的 WAR,进行一些更改并将其打包回 WAR。

解压后,前往WEB-INF/web.xml并取消注释 XML 代码以激活安全注释。或者将以下代码放在那里:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Jetty Remote Deployer</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Test Realm</realm-name>
</login-config>

发布到部署服务器

我们现在可以将应用程序打包回 WAR 并将其复制到远程服务器上的任何位置。然后我们将其部署到 Jetty。

在部署期间,最好使用部署描述符文件,这样我们就可以创建一个securityHandler并向它传递一个loginService。所有受保护的应用程序都必须具有登录服务,否则将无法部署它们。

现在,让我们在远程实例的*$JETTY_HOME/webapps*中创建一个Context 文件,记住命名Context 文件的规则。使其与 WAR 同名:

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" 
  "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/deployer</Set>
    <Set name="war">absolute/path/to/cargo-jetty-deployer.war</Set>
    <Get name="securityHandler">
        <Set name="loginService">
            <New class="org.eclipse.jetty.security.HashLoginService">
                <Set name="name">Test Realm</Set>
                <Set name="config"><SystemProperty name="jetty.home" 
                   default="."/>/etc/realm.properties</Set>
            </New>
        </Set>
    </Get>
</Configure>

启动远程服务器,如果一切顺利,我们应该能够加载http://localhost:8080/cargo-jetty-deployer 。然后我们应该能够看到类似的东西:

HTTP ERROR 400
Problem accessing /cargo-jetty-deployer/. Reason:
    Command / is unknown

将 WAR 部署到远程 Jetty

要进行远程部署,我们只需要更改pom.xml的配置部分。远程部署意味着我们没有本地安装的 Jetty,但可以通过身份验证访问远程服务器上运行的部署应用程序。

因此,让我们更改pom.xml,使配置部分如下所示:

<configuration>
    <container>
        <containerId>jetty9x</containerId>
        <type>remote</type>
    </container>
    <configuration>          
        <type>runtime</type>
        <properties>
      <cargo.hostname>127.0.0.1</cargo.hostname>
            <cargo.servlet.port>8080</cargo.servlet.port>
            <cargo.remote.username>admin</cargo.remote.username>
            <cargo.remote.password>password</cargo.remote.password>
        </properties>
    </configuration>
</configuration>

这一次,我们将容器类型从installed 更改为remote ,并将配置类型从existing 更改为runtime。最后,我们将主机名、端口和身份验证属性添加到配置中。

清理项目:

mvn clean

安装它:

mvn install

最后,部署它:

mvn cargo:deploy

而已。

9. 从 Eclipse 部署

Eclipse 允许我们嵌入服务器,以便在正常工作流程中添加 Web 项目部署,而无需离开 IDE。

9.1. 在 Eclipse 中嵌入 Jetty

我们可以通过从任务栏中选择window 项,然后从下拉菜单中选择preferences,将 Jetty 安装嵌入到 eclipse 中。

我们将在出现的窗口的左侧面板上找到一个偏好项目的树状网格。然后我们可以导航到 eclipse -> servers 或者在搜索栏中输入 servers。

如果还没有为我们打开,我们然后选择 Jetty 目录并选择我们下载的 Jetty 版本。

在面板的右侧会出现一个配置页面,我们在其中选择启用选项来激活这个 Jetty 版本并浏览到安装文件夹。

从屏幕截图来看,jetty 7.x 将替换为我们配置的 jetty 版本。

/uploads/deploy_to_jetty/1.png   我们应用更改,下次我们从 Eclipse 的窗口 -> 显示视图子菜单打开服务器视图时,新配置的服务器将出现,我们可以启动、停止和部署应用程序到它。

9.2. 在 Embedded Jetty 中部署 Web 应用程序

要将 Web 应用程序部署到嵌入式 Jetty 实例,它必须存在于我们的工作区中。

从* window -> show打开servers 窗口并查找服务器。打开后,我们只需右键单击我们配置的服务器,然后从出现的Context 菜单中选择add deployment*。

/uploads/deploy_to_jetty/3.png

从出现的New Deployment对话框中,打开*project *下拉菜单并选择 Web 项目。

当我们选择Exploded Archive(development mode)时,Project组合框下方有一个Deploy Type部分,我们在应用程序中的更改将实时同步,而无需重新部署,这是开发过程中的最佳选择,因为它非常有效。

/uploads/deploy_to_jetty/5.png

选择*Packaged Archive(production mode)*将要求我们每次进行更改并在浏览器中查看它们时重新部署。这仅适用于生产,但 Eclipse 仍然使它同样容易。

9.3. 在外部位置部署 Web 应用程序

我们通常选择通过 Eclipse 部署 WAR 以使调试更容易。有时我们可能希望将其部署到 Eclipse 嵌入式服务器使用的位置以外的位置。

最常见的情况是我们的生产服务器在线,并且我们想要更新 Web 应用程序。

我们可以通过在生产模式下部署并在New Deployment对话框中记下Deploy Location并从中选择 WAR 来绕过此过程。

在部署期间,我们可以从嵌入式服务器列表旁边的servers 窗口中选择<Externally Launched>选项,而不是选择嵌入式服务器。我们导航到外部 Jetty 安装的$JETTY_HOME/webapps目录。

10. 从 IntelliJ IDEA 部署

要将 Web 应用程序部署到 Jetty,它必须存在并且已经下载并安装。

10.1. 本地配置

打开Run 菜单并单击Edit Configurations选项。

在左侧面板中搜索Jetty Server,如果不存在,请单击菜单中的 + 号,搜索Jetty并选择Local。在name 字段中放置Jetty 9

单击Configure…按钮,然后在Jetty Home字段中导航到安装的主位置并选择它。

或者,将Startup 页面设置为http://localhost:8080/HTTP port: 8080,根据需要更改端口。

转到*Deployment *选项卡并单击 + 符号,选择要添加到服务器的工件,然后单击确定

10.2. 远程配置

按照与本地 Jetty 配置相同的说明进行操作,但在服务器选项卡中,您必须输入安装的远程位置。