Jetty使用教程(四:23)—Jetty开发指南
二十三、Maven和Jetty
这一章节将说明如何通过Maven管理Jetty和使用Jetty的Maven插件。
23.1 使用Maven
Apache Maven是一个款软件项目管理工具。基于项目对象模型(POM)的概念,Maven可以管理一个项目的构建生成报告和文档。这是一个理想的工具用来构建一个web应用程序,这样的项目也可以使用jetty-maven-plugin来轻松运行并可以节省开发时间,你也可以使用Maven来构建、测试、运行一个嵌入式Jetty项目。
首先我们要看一个非常简单的Jetty嵌入式的HelloWorld程序,然后再看如何用jetty-maven-plugin来加速开发一个web应用。
23.1.1 通过Maven使用嵌入式Jetty
为了理解构建和运行Jetty的基本操作,首先请回顾以下内容(点击我):
- 嵌入式Jetty
- Jetty的HelloWorld例子
Maven多使用约定而不是配置,所以最好的做法是使用Maven推荐的命令来构建项目。你可以使用archetypes 模板来快速生成一个Maven项目,但是对于这个简单的入门例子,我们将手动进行配置:
> mkdir JettyMavenHelloWorld > cd JettyMavenHelloWorld > mkdir -p src/main/java/org/example
23.1.1.1 创建一个HelloWorld类
可以使用文本编辑器创建文件src/main/java/org/example/HelloWorld.java,有如下内容:
package org.example; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import java.io.IOException; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; public class HelloWorld extends AbstractHandler { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); response.getWriter().println("<h1>Hello World</h1>"); } public static void main(String[] args) throws Exception { Server server = new Server(8080); server.setHandler(new HelloWorld()); server.start(); server.join(); } }
23.1.1.2 创建POM描述文件
pom.xml用来描述项目名称和依赖关系。使用文本编辑器创建pom.xml,包含如下内容:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>hello-world</artifactId> <version>0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>Jetty HelloWorld</name> <properties> <!-- 具体版本信息可在此查看 http://central.maven.org/maven2/org/eclipse/jetty/jetty-maven-plugin/ --> <jettyVersion>9.0.2.v20130417</jettyVersion> </properties> <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${jettyVersion}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.1</version> <executions> <execution><goals><goal>java</goal></goals></execution> </executions> <configuration> <mainClass>org.example.HelloWorld</mainClass> </configuration> </plugin> </plugins> </build> </project>
23.1.1.3 构建和运行嵌入式的HelloWorld
你可以使用如下命令来编译并执行HelloWorld:
> mvn clean compile exec:java
你可以在你的浏览器中输入http://localhost:8080来查看欢迎页。你可以观察到使用mvn dependency:tree命令后Maven到底做了什么,主要是解决依赖和下载文件:
> mvn dependency:tree [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'dependency'. [INFO] ------------------------------------------------------------------------ [INFO] Building Jetty HelloWorld [INFO] task-segment: [dependency:tree] [INFO] ------------------------------------------------------------------------ [INFO] [dependency:tree {execution: default-cli}] [INFO] org.example:hello-world:jar:0.1-SNAPSHOT [INFO] \- org.eclipse.jetty:jetty-server:jar:9.0.0:compile [INFO] +- org.eclipse.jetty:javax.servlet:jar:3.0.0.v201112011016:compile [INFO] +- org.eclipse.jetty:jetty-continuation:jar:9.0.0:compile [INFO] \- org.eclipse.jetty:jetty-http:jar:9.0.0:compile [INFO] \- org.eclipse.jetty:jetty-io:jar:9.0.0:compile [INFO] \- org.eclipse.jetty:jetty-util:jar:9.0.0:compile [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4 seconds [INFO] Finished at: Thu Jan 24 16:19:08 EST 2013 [INFO] Final Memory: 11M/68M [INFO] ------------------------------------------------------------------------
23.1.2 通过Jetty和Maven来部署一个标准的web应用
上面一节演示了如何通过Maven来创建嵌入式Jetty应用。现在我们要研究如何通过Maven和Jetty来开发一个标准的web应用。首先创建Maven项目结构(如果你喜欢你也可以使用maven的webapp模板来构建)。
> mkdir JettyMavenHelloWarApp > cd JettyMavenHelloWebApp > mkdir -p src/main/java/org/example > mkdir -p src/main/webapp/WEB-INF
23.1.2.1 创建一个Servlet
使用编辑器创建一个src/main/java/org/example/HelloServlet.java文件,内容如下:
package org.example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello Servlet</h1>"); response.getWriter().println("session=" + request.getSession(true).getId()); } }
你需要将这个servlet声明在部署描述中,所以创建src/main/webapp/WEB-INF/web.xml文件,并增加如下内容:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" metadata-complete="false" version="3.1"> <servlet> <servlet-name>Hello</servlet-name> <servlet-class>org.example.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping> </web-app>
23.1.2.2 创建POM描述文件
pom.xml用来描述项目名称和依赖关系。使用文本编辑器创建pom.xml,包含如下内容,特别注意 jetty-maven-plugin的声明:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>hello-world</artifactId> <version>0.1-SNAPSHOT</version> <packaging>war</packaging> <name>Jetty HelloWorld WebApp</name> <properties> <jettyVersion>9.3.11.v20160721</jettyVersion> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>${jettyVersion}</version> </plugin> </plugins> </build> </project>
23.1.2.3 构建运行web应用
现在你可以同时构建和运行一个web应用,不需要把项目打成war包,而是使用jetty-maven-plugin插件命令:
> mvn jetty:run
你可以在http://localhost:8080/hello看到静态和动态的内容。
23.1.2.4 生成一个War文件
你可以使用如下命令来讲一个web项目打包成war包:
> mvn package
打包后的war包可以部署到标准的servlet容器里,包括Jetty。
23.2 配置Jetty的Maven插件
Jetty Maven插件非常适合快速开发和测试。根据通常的Maven约定你可以把它添加到任何web项目中。这个插件可以周期性的扫描你的项目,若有改变会自动部署。这样通过消除构建的时间,可以让开发更有效率,部署的步骤是:你使用你的开发工具对项目有所改变,那么运行中的web容器会自动更换它们,允许你可以立即测试代码。
重要提示:
为了使用这个插件应该使用Maven 3.3+ 和 Java1.8版本。
虽然Jetty Maven的插件对开发非常有用,但是我们依然不建议用户在生产环境上使用。为了让插件能正常工作,时用了很多maven内部的API,但是maven本身并不是一个生产部署工具。所以我们建议使用传统方式部署应用或者使用嵌入式Jetty。
23.2.1 快速开始:起步运行
首先新增jetty-maven-plugin 到你的 pom.xml中:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> </plugin>
然后,在pom.xml的目录下执行如下命令:
mvn jetty:run
可以通过访问http://localhost:8080/来查看启动的Jetty服务。
Jetty会持续运行知道你停止它,当它运行时,它会定期扫描你项目下的文件,所以如果你对保存修改的文件并重新编译成class文件,那么Jetty会重新部署你的应用,你就可以立即对你刚才做的改变进行测试。
你可以在控制台使用Ctrl+C,来强行终止Jetty运行。
注意:
运行中的Jetty程序的classpath和它的部署webapp都是由Maven进行管理的,所以有可能不像你想的那么精确。例如:web应用依赖的jar包有可能引用的是本地文件,而不是WEB-INF/lib目录下。
23.2.2 实现目标
Jetty Maven插件有很多不同于Maven的功能,可以说最有用的命令run
可以用在一个原始的web应用上。这还有另一个方法同样可以帮助你实现目标,例如:你有可能需要将你的应用运行在Jetty下,而不是maven下;或者你想通过Jetty来部署应用。有不同的方法来实现你想要的。
使用如下命令可以列出Jetty Maven 插件所有的功能
mvn jetty:help
如果想要查看具体的参数配置,可以添加如下参数:
mvn jetty:help -Ddetail=true -Dgoal= goal-name
23.2.3 配置Jetty容器
下面这些Jetty环境属性的设置在你的web应用中执行,最常用的配置如下:
httpConnector
可选择的配置,如果没有设置,Jetty将创建ServerConnector实例来监听8080端口。你可以在命令行上使用系统属性jetty.http.port来
修改默认的端口配置,例如mvn -Djetty.http.port=9999 jetty:run,
当然你可以通过配置下面的属性来配置ServerConnector。可以配置的属性如下:
port:连接监听的端口,默认8080;
host:监听的主机,默认监听所有主机,即所有主机都可以访问;
name:连接器的名称,在配置指定连接器来处理指定请求时有用;
idleTimeout:连接超时时间;
soLinger:socket连接时间;
你同样可以在一个标准的Jetty xml配置文件中配置连接,并把配置文件的路径赋值给jettyXml参数。jetty-9.0以后已经不需要把连接信息配置在pom.xml中了;你可以使用Jetty的xml进行配置。
jettyXml
可选择的配置,通常,可以把以逗号分割的Jetty xml配置文件的地址字符串增加到任何插件的配置参数中。如果你有另一个web应用、处理器、特别是连接器,你就可以使用它,但是若你有另外一个Jetty对象,则不能通过插件得到配置信息。
scanIntervalSeconds
自动扫描文件改变并进行热部署的时间间隔,单位为秒。默认值为0,这代表着禁用扫描并热部署,只有一个大于0的配置可以使它生效。
reload
重新加载选项,默认值是"automatic"(自动),一般用来和配置不为0的scanIntervalSeconds一同使用。默认配置下当发现有文件改变会自动进行热部署。如果设置为"manual" (手动),这样设置的话,部署将会通过插件被手动触发,这在当你频繁改动文件时比较有用,这样会忽略你的改动,直到你做完所有改变。
dumpOnStart
可选择的配置,默认为false,如果设置为true。那么Jetty会在启动时打印出server的结构。
loginServices
可选择的配置。是一系列org.eclipse.jetty.security.LoginService的实现类。注意,没有指定默认的域,如果你需要在web.xml中配置域,那么就可以配置一个统一的域。当然也可以在Jetty的xml里面进行配置。并把配置文件的地址增加到
jettyXml中。
requestLog
可选择的配置。一个实现了org.eclipse.jetty.server.RequestLog接口的请求日志记录。有三种方式配置请求日志:
-
- 在Jetty xml配置文件,并加到jettyXML参数中。
- 在context xml配置文件中,并加到contextXml参数中。
- 在webAPP元素中
server
jetty-9.3.1以后是可选择配置。这可以配置org.eclipse.jetty.server.Server 实例用来支持插件的使用,然而通常是不需要配置的,因为插件会自动为你配置。特别是你在使用jettyXml的时候你通常不愿意使用这个元素。如果你同时定义了server元素和在xml文件中进行了包含“<Configure id="Server" class="org.eclipse.jetty.server.Server">”的配置,那么xml文件的配置将会覆盖pom中的配置。
stopPort
可选择配置。一个用来监听停止命令的端口。
stopKey
可选择的配置。和stopPort结合使用。
systemProperties
可选择的配置。允许你为了执行插件而配置系统参数。
systemPropertiesFile
可选择的配置。一个包含执行插件系统参数的文件。默认情况你在文件中设置的参数不会覆盖在命令行中写的参数,不管通过JVM还是通过POM的systemProperties。
skip
默认为false。如果为true的话,插件的执行会退出。同样可以使用命令-Djetty.skip
进行设置。这在一体化测试你可以通过配置取消执行时非常有用。
useProvidedScope
默认为false。如果为true的话, <scope>provided</scope所依赖的位置将会被添加到容器的classpath中。注意这并不是webapp的classpath,只是提供给容器使用的。所以你应该会少使用这一功能,而是明确拷贝需要的依赖。
excludedGoals
可选择的配置。一系列Jetty插件的名称可以使插件打印出有效的信息并退出。这在你想禁止用户使用指定功能的时候很有用。
23.2.3.1 配置https连接器
为了配置https连接器,你需要使用Jetty xml配置文件。下面的例子是直接拷贝 etc/文件夹下的文件,当然你也可以自己编写你自己xml文件。我们将使用下面的文件:
jetty.xml
设置 org.eclipse.jetty.server.Server 实例的各种属性,为了让插件可以使用。重点提示,下面设置了org.eclipse.jetty.server.HttpConfiguration元素,我们也可以使用一个字xml文件来配置它。这是一个相关的部分:
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration"> <Set name="secureScheme">https</Set> <Set name="securePort"><Property name="jetty.secure.port" default="8443" /></Set> <Set name="outputBufferSize">32768</Set> <Set name="requestHeaderSize">8192</Set> <Set name="responseHeaderSize">8192</Set> <Set name="sendServerVersion">true</Set> <Set name="sendDateHeader">false</Set> <Set name="headerCacheSize">512</Set> </New>
jetty-ssl.xml
为https连接配置ssl。下面一个jetty-ssl.xml
例子来自jetty-distribution:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> <!-- ============================================================= --> <!-- SSL基础配置 --> <!-- 这个配置文件需要和至少一个或多个 --> <!-- etty-https.xml 或 jetty-http2.xml文件同时使用 --> <!-- ============================================================= --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- 不使用协议工厂增加一个SSL连接 --> <!-- =========================================================== --> <Call name="addConnector"> <Arg> <New id="sslConnector" class="org.eclipse.jetty.server.ServerConnector"> <Arg name="server"><Ref refid="Server" /></Arg> <Arg name="acceptors" type="int"><Property name="jetty.ssl.acceptors" deprecated="ssl.acceptors" default="-1"/></Arg> <Arg name="selectors" type="int"><Property name="jetty.ssl.selectors" deprecated="ssl.selectors" default="-1"/></Arg> <Arg name="factories"> <Array type="org.eclipse.jetty.server.ConnectionFactory"> <!-- 注释掉用于支持代理 <Item> <New class="org.eclipse.jetty.server.ProxyConnectionFactory"/> </Item>--> </Array> </Arg> <Set name="host"><Property name="jetty.ssl.host" deprecated="jetty.host" /></Set> <Set name="port"><Property name="jetty.ssl.port" deprecated="ssl.port" default="8443" /></Set> <Set name="idleTimeout"><Property name="jetty.ssl.idleTimeout" deprecated="ssl.timeout" default="30000"/></Set> <Set name="soLingerTime"><Property name="jetty.ssl.soLingerTime" deprecated="ssl.soLingerTime" default="-1"/></Set> <Set name="acceptorPriorityDelta"><Property name="jetty.ssl.acceptorPriorityDelta" deprecated="ssl.acceptorPriorityDelta" default="0"/></Set> <Set name="acceptQueueSize"><Property name="jetty.ssl.acceptQueueSize" deprecated="ssl.acceptQueueSize" default="0"/></Set> </New> </Arg> </Call> <!-- =========================================================== --> <!-- 基于定义在jetty.xml配置文件里的HttpConfiguration --> <!-- 创建一个基于TLS的HttpConfiguration --> <!-- 增加一个SecureRequestCustomizer来管理证书和session信息 --> <!-- =========================================================== --> <New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration"> <Arg><Ref refid="httpConfig"/></Arg> <Call name="addCustomizer"> <Arg> <New class="org.eclipse.jetty.server.SecureRequestCustomizer"> <Arg name="sniHostCheck" type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg> <Arg name="stsMaxAgeSeconds" type="int"><Property name="jetty.ssl.stsMaxAgeSeconds" default="-1"/></Arg> <Arg name="stsIncludeSubdomains" type="boolean"><Property name="jetty.ssl.stsIncludeSubdomains" default="false"/></Arg> </New> </Arg> </Call> </New> </Configure>
现在你需要让插件来应用上面的这个文件:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <jettyXml>jetty.xml,jetty-ssl.xml,jetty-https.xml</jettyXml> </configuration> </plugin>
!警告
对于Jetty的安装来说,xml配置文件的顺序是很重要的。
你也可以使用jetty xml文件来配置http连接供插件使用。在这我们使用Jetty程序包中的jetty-http.xml文件:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> <!-- ============================================================= --> <!-- 使用"Server"的ID来配置Server实例,并添加一个HTTP连接 --> <!-- 这个配置文件必须和jetty.xml文件结合使用 --> <!-- ============================================================= --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- 增加一个HTTP连接 --> <!-- =========================================================== --> <Call name="addConnector"> <Arg> <New id="httpConnector" class="org.eclipse.jetty.server.ServerConnector"> <Arg name="server"><Ref refid="Server" /></Arg> <Arg name="acceptors" type="int"><Property name="jetty.http.acceptors" deprecated="http.acceptors" default="-1"/></Arg> <Arg name="selectors" type="int"><Property name="jetty.http.selectors" deprecated="http.selectors" default="-1"/></Arg> <Arg name="factories"> <Array type="org.eclipse.jetty.server.ConnectionFactory"> <Item> <New class="org.eclipse.jetty.server.HttpConnectionFactory"> <Arg name="config"><Ref refid="httpConfig" /></Arg> <Arg name="compliance"><Call class="org.eclipse.jetty.http.HttpCompliance" name="valueOf"><Arg><Property name="jetty.http.compliance" default="RFC7230"/></Arg></Call></Arg> </New> </Item> </Array> </Arg> <Set name="host"><Property name="jetty.http.host" deprecated="jetty.host" /></Set> <Set name="port"><Property name="jetty.http.port" deprecated="jetty.port" default="8080" /></Set> <Set name="idleTimeout"><Property name="jetty.http.idleTimeout" deprecated="http.timeout" default="30000"/></Set> <Set name="soLingerTime"><Property name="jetty.http.soLingerTime" deprecated="http.soLingerTime" default="-1"/></Set> <Set name="acceptorPriorityDelta"><Property name="jetty.http.acceptorPriorityDelta" deprecated="http.acceptorPriorityDelta" default="0"/></Set> <Set name="acceptQueueSize"><Property name="jetty.http.acceptQueueSize" deprecated="http.acceptQueueSize" default="0"/></Set> </New> </Arg> </Call> </Configure>
现在讲这个文件添加到文件列表中:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <jettyXml>jetty.xml,jetty-http.xml,jetty-ssl.xml,jetty-https.xml</jettyXml> </configuration> </plugin>
当然也可以使用httpConnector元素来配置同上面的例子一样。
23.2.4 配置你的WebApp
这些配置参数应用到你的webapp中。它们可以实现所有的要求。
webApp
这是一个继承了org.eclipse.jetty.webapp.WebAppContext的org.eclipse.jetty.maven.plugin.JettyWebAppContext实例。你可以使用这个对象上所有的方法来配置你的webapp。下面几个是最常用的:
contextPath
你web应用的根路径。默认设置为“/”,如果你可以设置一个路径在“/”下面,例如/mycontext
descriptor
当前web应用的web.xml路径
defaultsDescriptor
webdefault.xml的路径,会在web.xml之前应用这个文件内容。如果你不指定一个,那么Jetty会使用一个在jetty-webapp.jar里面的webdefault.xml。
overrideDescriptor
当Jetty读取web.xml后要覆盖的配置文件。你可以用这个文件来覆盖或者增加配置。
tempDirectory
在web应用运行时,Jetty用来扩展或者拷贝jar文件和JSP编译后类的文件夹路径,默认路径是${project.build.outputDirectory}/tmp
baseResource
Jetty静态资源的根目录,默认为src/main/webapp
resourceBases
用来替代baseResource,如果你有多个静态目录。这是一个地址名字的数组。
baseAppFirst
默认为true。控制是否要在web应用的原始资源加载前或者加载后覆盖war包。
containerIncludeJarPattern
默认为"./javax.servlet-[^/]\.jar$|./servlet-api-[^/]\.jar$|.javax.servlet.jsp.jstl-[^/]\.jar|.taglibs-standard-impl-.\.jar"。这是一个匹配规则,用来匹配容器classpath(注意:是容器的classpath不是web应用的classpath)里jar包的名字中应该被扫描的fragments,tlds和annotations 。这和context中org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern 属性比较相似。用户也可以定义额外的需要被扫描的jar包。
contextXml
应用到web应用的context的xml的路径,在元素webApp
以后。
23.2.5 jetty:run
run 命令运行在一个web应用上,并且不需要将应用打成一个war包。相反,Jetty直接从源代码处进行部署。它将会在Maven默认的项目路径下寻找webapp的组成部分,你也可以通过插件配置来覆盖默认路径。例如,默认它将寻找如下内容:
- 在
${project.basedir}/src/main/webapp
下的资源 - 在
${project.build.outputDirectory}下
的classes - 在
${project.basedir}/src/main/webapp/WEB-INF/
下的web.xml
插件会在部署前确保classes被重新编译过并保证是最新的。如果你改变class的来源那么你的IDE工具将会自动在后台重新编译,插件也将获得修改后的class。
用户也不需要将webapp打成一个war包,在部署时可以节省时间。一旦被调用,用户可以配置插件来不断的运行并扫描项目的改变,并且在有需要的时候进行热部署。你一旦对项目做出了改变,那么将会立即在Jetty实例中展现出来,让你很快的进行代码的测试,这样比编码、编译、打包、测试这样的循环要好。
这里有一个简单的例子,用来每10秒钟进行一次扫描获取改变,并且设置web应用的根路径为“/”:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> </configuration> </plugin>
23.2.5.1 配置
除了webApp这一个常用的元素外,jetty:run还支持以下:
classesDirectory
你webapp应用编译后classes文件的地址。你应该尽量不要设置这个属性,而是应该在pom.xml设置build outputDirectory这个属性。
testClassesDirectory
你webapp应用测试代码编译后classes文件的地址。默认是${project.build.testOutputDirectory}
。
useTestScope
默认为false,若为true的话,testClassesDirectory 路径下的classes和“test”依赖的将会被放置在classpath下。
webAppSourceDirectory
默认的设置为${project.basedir}/src/main/webapp,如果逆境在资源的在不同路径下,可以设置这个路径。
jettyEnvXml
可选择的,jetty-env.xml文件的路径,这个允许你对JNDI进行绑定,并将env-entry, resource-env-ref 和 resource-ref关联到web.xml的合适位置。这将只对当前web应用有效,不能共享到其它web应用,所以你需要在部署项目的同时部署此文件(例如,通过使用jettyConfig文件)。
scanTargets
可选择的,需要被插件自动扫描的文件或者文件夹的列表。
scanTargetPatterns
可选择的,如果你有大量的文件想要扫描,最方便的做法是使用规则来匹配文件这样要比把所有文件列出来要好。
scanClassesPattern
9.3.0以后可选择配置,在扫描的时候包含或者排除的规则。如果一个文件发生被修改了,但这个文件符合排除规则,那么将不会进行重新部署。
scanTestClassesPattern
同scanClassesPattern,用于测试类。
下面有一个例子:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <webAppSourceDirectory>${project.basedir}/src/staticfiles</webAppSourceDirectory> <webApp> <contextPath>/</contextPath> <descriptor>${project.basedir}/src/over/here/web.xml</descriptor> <jettyEnvXml>${project.basedir}/src/over/here/jetty-env.xml</jettyEnvXml> </webApp> <classesDirectory>${project.basedir}/somewhere/else</classesDirectory> <scanClassesPattern> <excludes> <exclude>**/Foo.class</exclude> </excludes> </scanClassesPattern> <scanTargets> <scanTarget>src/mydir</scanTarget> <scanTarget>src/myfile.txt</scanTarget> </scanTargets> <scanTargetPatterns> <scanTargetPattern> <directory>src/other-resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <excludes> <exclude>**/myspecial.xml</exclude> <exclude>**/myspecial.properties</exclude> </excludes> </scanTargetPattern> </scanTargetPatterns> </configuration> </plugin> </plugins> </project>
不管什么原因,如果你不能在一个没有配置过的webapp上运行,那么使用可以使用run-war 。
23.2.6 jetty:run-war
首先打包你的应用成一个war包,然后将它部署到Jetty。如果你把scanInterval设置为非0数值,那么Jetty将会监视pom.xml和war文件,如果文件被改变,那么Jetty将会重新部署这个war。
配置
war
war包的地址。默认为${project.build.directory}/${project.build.finalName}.war。如果这个不合适,那么将其设置到你常用的地点。
下面有配置的例子:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <war>${project.basedir}/target/mycustom.war</war> </configuration> </plugin> </plugins> </project
23.2.7 jetty:run-exploded
run-exploded命令的目的是首先将你的webapp与一个已经打开的war文件关联,然后把它部署到Jetty上。如果scanInterval参数设置了一个非0的数,那么Jetty将会监视你的pom.xml,WEB-INF/lib,WEB-INF/classes和WEB-INF/web.xml文件,如果检测到改变则重新部署。
配置
war
解压的war文件地址,默认的为${project.build.directory}/${project.build.finalName}
,但是你可以通过配置覆盖默认值。
下面有一个例子展示如何使用:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <war>${project.basedir}/target/myfunkywebapp</war> </configuration> </plugin> </plugins> </project>
23.2.8 jetty:deploy-war
这个命令和jetty:run-war基本一样,但是不会把当前模块打成war包,你可以指定任何路径下的war文件来运行。
配置
war
war文件的路径。默认为${project.build.directory}/${project.build.finalName},但是你可以通过设置参数来覆盖。
daemon
如果设置为true,那么插件会运行Jetty并让构建继续。这是非常有用的,如果你想启动jetty作为执行绑定在一个特定的阶段,然后阻止它在另一个。当然,你也可以把这个参数设置为false,在这种情况下,Jetty将会堵塞运行,你需要使用Ctrl+C来终止运行它。
下面有一个配置文件:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <war>/opt/special/some-app.war</war> <stopKey>alpha</stopKey> <stopPort>9099</stopPort> </configuration> <executions> <execution> <id>start-jetty</id> <phase>test-compile</phase> <goals> <goal>deploy-war</goal> </goals> </execution> <execution> <id>stop-jetty</id> <phase>test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> </plugins> </project>
23.2.9 jetty:run-forked
这个命令的作用是允许你将当前webapp运行在一个新的JVM上,可以传入参数到新的JVM上。命令支持同jetty:run一样的参数配置。
配置
可用的配置参数,比jetty:run多的如下:
jvmArgs
可选择配置。表示需要传入到JVM的任意参数的字符串。
waitForChild
默认为true。这个需要父进程等待所有进程结束后才能退出。在这种情况下你也可以使用Ctrl+C来同时终止它们。把这个参数设置为false或许更有效,在这种情况下,父进程退出了,而子进程可以继续运行。你可以使用 jetty:stop来终止子进程。
maxStarupLines
默认为50。子进程运行后,父进程可以读取子进程传入的最大行数。如果子进程产生大量的输出,那么你有可能需要把这个配置的数字增大。
这个命令不会支持容器的某些配置:
scanIntervalSeconds
不支持。不会监控并重部署应用。
reload
不支持。不会重新部署应用。
httpConnector
不支持。定义connectors使用jetty xml配置文件。
loginService
不支持。定义LoginServices使用jetty xml或者容器xml文件来替代。
requestLog
不支持。定义requestLog使用jetty xml或者容器xml文件来替代。
systemProperties
不支持。使用 jvmArgs 参数来讲系统属性传入命令中。
部署你未打包的程序到新的JVM使用如下命令:
mvn jetty:run-forked
Jetty将持续运行直到你做了如下操作的一种:
- 输入Ctrl+C来终止命令窗口运行来终止插件运行,这将会同时终止分出的JVM(仅当你使用
waitForChild=true来启动时
)。 - 使用jetty:stop命令,来终止分出去的JVM运行,这样讲会同时停止插件运行。
23.2.10 jetty:start
这个命令的目的是执行时绑定你的pom.xml。它和jetty:run命令有些相似,然而它第一次运行不会编译除非输入“test-compile”命令来确保所有需要的classes和webapp下的所有文件都是新生成的。这个你想通过绑定的pom.xml控制启动和终止的情况下很有用。
例如,你可以配置插件为在你测试前启动webapp并在你测试完成后停止webapp。为了这么做,你可以设置Jetty插件的一对execution 情景。你是用 pre-integration-test和post-integration-test的Maven插件来设置Jetty启动和终止的触发器。
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <stopKey>foo</stopKey> <stopPort>9999</stopPort> </configuration> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin>
23.2.11 jetty:stop
stop命令会终止一个运行中的Jetty实例。为了使用它,你需要为这个插件配置一个特别的端口和key。相同的端口和key将被另一个运行的Jetty使用。
stopPort
一个Jetty的端口数字,又来监听接收一个终止的命令并将其终止。
stopKey
一个发送到stopPort端口的有效命令。
stopWait
等待Jetty停止确认的最大时间间隔,单位秒。如果为false或者为设置,那么插件将不会再发出命令后等待结果。
下面有一个配置的例子。
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <stopPort>9966</stopPort> <stopKey>foo</stopKey> <stopWait>10</stopWait> </configuration> </plugin>
然后当Jetty运行的时候,在另一个窗口输入以下命令:
mvn jetty:stop
stopPort端口必须是有效的。如果不是这种情况,那么你将再输入命令后得到一个“端口已经被占用”的错误消息。
23.2.12 jetty:effective-web-xml
这个命令的作用是计算一个合成的web.xml(一个有效的web.xml),通过Servlet规范把应用组件中的所有描述文件(webdefault.xml、web.xml、web-fragment.xmls、web-override.xml),发现的注解(@WebServlet、 @WebFilter、 @WebListener)。通过有效的来源组成一个web.xml并输出日志。关于你应用的一些其他有用的信息,也会存储在effective-web.xml中。
下面的参数配置允许你保存文件:
deleteOnExit
默认为true。如果设置为false,那么原始的web.xml将会生成到输出路径下的一个名为effective-web.xml的文件中。
effectiveWebXml
实际web.xml文件生成的全路径名。
注意,没有被声明的servlets,filters和listeners将不会被使用。
23.2.13 使用war包覆盖
如果你的应用需要依赖其他war文件,jetty:run和jetty:run-forked命令可以合并所有的资源文件。它可以基于maven-war-plugin的配置,如果你的项目不是用maven-war-plugin,那么它将通过简单的算法来获得所有资源文件。
23.2.13.1 使用maven-war-plugin
maven-war-plugin插件有合并资源的丰富经验。 jetty:run和jetty:run-forked的命令有能力解释你运行中程序的大多数。可以通过以下两个例子来了解。
让你的webapp依赖以下war文件:
<dependency> <groupId>com.acme</groupId> <artifactId>X</artifactId> <type>war</type> </dependency> <dependency> <groupId>com.acme</groupId> <artifactId>Y</artifactId> <type>war</type> </dependency>
包含如下:
WebAppX: /foo.jsp /bar.jsp /WEB-INF/web.xml WebAppY: /bar.jsp /baz.jsp /WEB-INF/web.xml /WEB-INF/special.xml
它们可以被maven-war-plugin配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <overlays> <overlay> <groupId>com.acme</groupId> <artifactId>X</artifactId> <excludes> <exclude>bar.jsp</exclude> </excludes> </overlay> <overlay> <groupId>com.acme</groupId> <artifactId>Y</artifactId> <excludes> <exclude>baz.jsp</exclude> </excludes> </overlay> <overlay> </overlay> </overlays> </configuration> </plugin>
执行 jetty:run将获得以下资源:com.acme.X.war : com.acme.Y.war: ${project.basedir}/src/main/webapp。注意,当前项目的资源将会被放在最后一位<overlay/>元素中。你可以使用它或者定义
<baseAppFirst>false</baseAppFirst>命令到jetty-maven-plugin.。
此外,由于上面配置的排除策略,请求资源 bar.jsp 将会从com.acme.Y.war中获得,而请求baz.jsp资源,将会返回404。
23.2.13.2 不是用maven-war-plugin
这个算法是非常简单的,通过依赖war包的声明顺序,并且不支持排除策略。<baseAppFirst>配置属性可以用来控制那个webapp的资源放在前面或者放在后面。
例如,让我们当前webapp依赖如下两个war:
<dependency> <groupId>com.acme</groupId> <artifactId>X</artifactId> <type>war</type> </dependency> <dependency> <groupId>com.acme</groupId> <artifactId>Y</artifactId> <type>war</type> </dependency>
依赖的webapp包含如下:
WebAppX: /foo.jsp /bar.jsp /WEB-INF/web.xml WebAppY: /bar.jsp /baz.jsp /WEB-INF/web.xml /WEB-INF/special.xml
最终webapp中有效的文件为:
/foo.jsp (X) /bar.jsp (X) /baz.jsp (Y) /WEB-INF/web.xml (X) /WEB-INF/special.xml (Y)
23.2.14 配置安全设置
你可以在这个插件中配置LoginServices,下面有一个为webapp设置HashLoginSercice的例子:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> <loginServices> <loginService implementation="org.eclipse.jetty.security.HashLoginService"> <name>Test Realm</name> <config>${project.basedir}/src/etc/realm.properties</config> </loginService> </loginServices> </configuration> </plugin>
23.2.15 使用多个web应用根目录
如果你有额外的资源你想把它们包含在运行中的webAPP中,但是没有被打进war包中,你不能使用覆盖war包的方法,但是你可以告诉Jetty你想添加的目录的地址。当运行时,Jetty接收到一个资源的请求,它将搜索它配置下的所有资源文件。它和覆盖war包的情况非常相似,但是这不是一个war。下面有一个配置的例子:
<configuration> <webApp> <contextPath>/${build.finalName}</contextPath> <baseResource implementation="org.eclipse.jetty.util.resource.ResourceCollection"> <resourcesAsCSV>src/main/webapp,/home/johndoe/path/to/my/other/source,/yet/another/folder</resourcesAsCSV> </baseResource> </webApp> </configuration>
23.2.16 运行多个web应用
你可以使用jetty.xml文件来配置你想要部署的额外的webapp,或者你可以使用<contextHandlers> 配置元素来这么做。如果你想部署webapp A和webapp B和webapp C到你的Jetty实例中:
将这些配置信息放到webapp A的pom.xml文件中:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> <contextHandlers> <contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext"> <war>${project.basedir}../../B.war</war> <contextPath>/B</contextPath> </contextHandler> <contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext"> <war>${project.basedir}../../C.war</war> <contextPath>/C</contextPath> </contextHandler> </contextHandlers> </configuration> </plugin>
重要:
如果你是用ContextHandler 部署的是一个webapp,最好的做法是使用
org.eclipse.jetty.maven.plugin.JettyWebAppContext实例而不是使用
org.eclipse.jetty.webapp.WebAppContext实例。只有前者才会允许webapp 在maven环境中正常工作。
同样的,你也可以增加一个jetty.xml文件到你的webapp A中。然后复制这个到其他,并为其它两个应用增加WebAppContexts:
<Ref refid="Contexts"> <Call name="addHandler"> <Arg> <New class="org.eclipse.jetty.maven.plugin.JettyWebAppContext"> <Set name="contextPath">/B</Set> <Set name="war">../../B.war</Set> </New> </Arg> </Call> <Call> <Arg> <New class="org.eclipse.jetty.maven.plugin.JettyWebAppContext"> <Set name="contextPath">/C</Set> <Set name="war">../../C.war</Set> </New> </Arg> </Call> </Ref>
这将把jetty.xml的地址配置到A的 Jetty插件中:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> <jettyXml>src/main/etc/jetty.xml</jettyXml> </configuration>
</plugin>
对于上面两种解决方案,其它webapp必须是已经构建好,并且它们没有被自动监听文件改变。
23.2.17 设置系统属性
你可以特别的指定 name/value 对设置到系统属性中,为Jetty插件使用。这样的特性可以整理输入命令并节省大量的输入。
然而,有时不能使用这种功能来设置系统属性 - 有时使用系统属性的软件组件已经在maven运行的时候进行了初始化(这种情况下,你需要在命令行上提供系统属性),或者Jetty运行的时候。在后一种情况,你可以使用maven的属性插件来定义系统属性。下面有一个例子又来配置logback日志系统作为Jetty的日志记录:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>properties-maven-plugin</artifactId> <version>1.0-alpha-2</version> <executions> <execution> <goals> <goal>set-system-properties</goal> </goals> <configuration> <properties> <property> <name>logback.configurationFile</name> <value>${project.baseUri}/resources/logback.xml</value> </property> </properties> </configuration> </execution> </executions> </plugin>
注意,如果一个系统属性已经被设置(例如,从命令行或者被JVM自己设置),那么默认这些属性将不会被覆盖(查看下面的<force>属性)。
23.2.17.1 在POM中设置系统属性
这里有一个例子展示如何在POM中设置系统属性:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <systemProperties> <systemProperty> <name>fooprop</name> <value>222</value> </systemProperty> </systemProperties> <webApp> <contextPath>/test</contextPath> </webApp> </configuration> </plugin>
为了改变默认行为,使用<force>参数来保证系统属性覆盖命令行参数:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<systemProperties>
<force>true</force>
<systemProperty>
<name>fooprop</name>
<value>222</value>
</systemProperty>
</systemProperties>
<webApp>
<contextPath>/test</contextPath>
</webApp>
</configuration>
</plugin>
23.2.17.2 在一个文件中设置系统属性
你也可以在一个文件中指定系统属性。在这种方式指定的系统属性将不会覆盖命令行的参数的系统属性、JVM的系统属性、POM中的系统属性。
包含如下类似内容的一个名为mysys.props的文件:
fooprop=222
这可以被配置到插件中,如下所示:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <systemPropertiesFile>${project.basedir}/mysys.props</systemPropertiesFile> <webApp> <contextPath>/test</contextPath> </webApp> </configuration> </plugin>
你也可以使用通过系统属性jetty.systemPropertiesFile来设置文件位置。
23.3 Jetty Maven插件的文件扫描
如果你设置了一个非0的scanInterval 属性,那么Jetty的maven插件将会在每间隔指定的时间扫描确定的文件,如果发现改变在需要的情况下将会重新部署。扫描的文件将依赖于执行的目标。
命令 | 扫描文件 |
jetty:run |
pom.xml, <dependencies>, <classesDirectory>, <testClassesDirectory>, <webXml> 或者 <webAppSourceDirectory>/WEB-INF/web.xml, <jettyEnvXml> 或者 <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <scanTargets>, <scanTargetPatterns>, 任何webapp描述的默认描述文件和覆盖描述文件。 |
jetty:run-war | pom.xml, <war> |
jetty:run-exploded |
pom.xml, <war>/WEB-INF/web.xml, <war>/WEB-INF/jetty-web.xml, <war>/WEB-INF/jetty-env.xml, <war>/WEB-INF/classes, <war>/WEB-INF/lib |
jetty:deploy-war | pom.xml, <war> |
jetty:run-forked | |
jetty:start |
pom.xml, <dependencies> from the pom, <classesDirectory>, <testClassesDirectory>, <webXml> 或者 : <webAppSourceDirectory>/WEB-INF/web.xml, <jettyEnvXml> 或者: <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <scanTargets>, <scanTargetPatterns>, 任何webapp描述的默认描述文件和覆盖描述文件。 |
jetty:stop |
23.4 Jetty Jspc的Maven插件
这个插件将帮助你预编译你的JSP并和maven war插件结合起来时候,将它们放到封装的war包中。
23.4.1 配置
将jspc插件放到你的构建环境中有一个级别的安装操作:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jspc-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <executions> <execution> <id>jspc</id> <goals> <goal>jspc</goal> </goals> <configuration> </configuration> </execution> </executions> </plugin>
配置的参数如下:
webXmlFragment
默认值为: $\{project.basedir}/target/webfrag.xml,一个包含servlet声明的文件,将会被合并到已经存在的web.xml中。
webAppSourceDirectory
默认值:$\{project.basedir}/src/main/webapp ,用来防止jsps、tags等资源的根目录。
webXml
默认值:$\{project.basedir}/src/main/webapp/WEB-INF/web.xml,web.xml文件用来和已经存在的片段合成。
includes
默认值:\/.jsp, \/.jspx ,一系列匹配需要的文件的条件。
excludes
默认值:\/.svn\/,一系列需要排除的条件。
classesDirectory
默认值:$\{project.build.outputDirectory},webapp的classes的路径。
generatedClasses
默认值: $\{project.build.outputDirectory} ,用来放置jsps生成的classes位置。
insertionMarker
默认值:none,在原web.xml文中的标记字符串,表明需要被合并到web.xml中的片段。注意,这个标记的字符串在插入的时候不会被隐藏掉。可以留空,这种情况下将会被插入到</web-app>之前。
useProvidedScope
默认值:false,如果为true,标有<scope>provided</scope> 中的jar包将会被classpath中的jar包替换。
mergeFragment
默认为true,不论是否将与源web.xml进行合并。合并后的文件将会放到与webXmlFragment文件同一路径。
keepSources
默认为false,如果为true的话,默认 .java 文件不会再执行的时候删除。
sourceVersion
jetty-9.3.6 版本以后的属性。jsp源文件的Java版本。默认为1.7。
targetVersion
jetty-9.3.6 版本以后的属性。jsps生成class文件的版本。默认为1.7。
tldJarNamePatterns
默认值:taglibs[^/]\.jar|.jstl-impl[^/]\.jar$,系统路径下,包含tlds文件的jar包匹配条件。使用 | 来分割每一个条件。
jspc
默认值:被配置过的the org.apache.jasper.JspC。JspC类用来进行预编译。所有在JspC类上的setter都是有效的。
使用所有默认设置,下面有一个使用普通web.xml,包含所有jsp servlet声明的war插件配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <webXml>${project.basedir}/target/web.xml</webXml> </configuration> </plugin>
23.4.2 只在构建时预编译
一般只有在准备正式版本的时候编译jsp 但是在开发过程中不太经常编译,最方便的做法是将插件放置到<profile> 中,这样可以假装准备生产版本而进行编译。
例如,下面的profile只有在 -Dprod被输入时才会被执行:
<profiles> <profile> <id>prod</id> <activation> <property><name>prod</name></property> </activation> <build> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jspc-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <!-- put your configuration in here --> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <!-- put your configuration in here --> </plugin> </plugins> </build> </profile> </profiles>
这样,下面的调用将会让你的代码进行编译,让jsp进行编译,<servlet>和<servlet-mapping>被插入到web.xml是,并将你的项目打成war包。
$ mvn -Dprod package
23.4.3 覆盖war时预编译
覆盖war时对jsp预编译需要多一点的配置。这是因为你需要分步骤解压需要覆盖的war文件,并将它们重新打包。所以jetty-jspc-maven-plugin讲有可能访问到覆盖的资源。
像下面例子中展示的,我们将使用一个覆盖的war。覆盖的war文件将提供web.xml,但是jsps将被放置到src/main/webapp。我们将解压war文件,编译jsps并且将servlet的定义合并到已经存在的web.xml中,然后将其打成war包。
这里有一个配置war插件的例子,分为解压步骤和打包步骤:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<goals><goal>exploded</goal></goals>
<phase>generate-resources</phase>
<configuration>
<webappDirectory>target/foo</webappDirectory>
<overlays>
<overlay />
<overlay>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
</overlay>
</overlays>
</configuration>
</execution>
<execution>
<id>pack</id>
<goals><goal>war</goal></goals>
<phase>package</phase>
<configuration>
<warSourceDirectory>target/foo</warSourceDirectory>
<webXml>target/web.xml</webXml>
</configuration>
</execution>
</executions>
</plugin>
接下来你让需要配置jetty-jspc-maven-plugin,这样插件才能使web.xml与额外的war文件中的servlets定义进行合并。这时在target/foo/WEB-INF/web.xml 中。使用默认的配置,web.xml将于jsp servlet 定义进行合并并放到target/web.xml中。
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jspc-maven-plugin</artifactId> <version>9.3.11.v20160721</version> <executions> <execution> <id>jspc</id> <goals> <goal>jspc</goal> </goals> <configuration> <webXml>target/foo/WEB-INF/web.xml</webXml> <includes>**/*.foo</includes> <excludes>**/*.fff</excludes> </configuration> </execution> </executions> </plugin>
附言:
Jetty文档的目录详见:http://www.cnblogs.com/yiwangzhibujian/p/5832294.html
Jetty第一章翻译详见:http://www.cnblogs.com/yiwangzhibujian/p/5832597.html
Jetty第四章(21-22)详见:http://www.cnblogs.com/yiwangzhibujian/p/5845623.html
这是翻译的第四部分的第23小节,主要是Maven的使用,如果项目不使用Maven管理可以跳过本文。一开始翻译总是感觉表达不出英文的本意,不过慢慢觉得我要做的不是一字不差的把原文翻译过来,而是要用中文的思维来表达英文的意思,我觉得以后的翻译会容易理解些。