Apache Maven是一种软件项目管理和综合工具。基于项目对象模型(POM)的概念,Maven能从核心信息管理一个项目的构建、报告和文档。
他是用于构建一个web应用项目的理想工具,这些项目能用jetty-maven-plugin轻松的运行web应用,从而节省开发时间。你也能用Maven构建、测试和运行一个嵌入Jetty的项目。
首先我们将看一个很简单嵌入Jetty的HelloWorld Java应用,然后看一个简单的webapp怎么使用jetty-maven-plugin加速开发周期。
Maven在配置之上使用惯例,因此最好的方式是使用Maven推荐的项目结构。你能用archetypes快速设置Maven项目,但这里我们为这个简单的指导性例子手动地设置结构:
> mkdir JettyMavenHelloWorld > cd JettyMavenHelloWorld > mkdir -p src/main/java/org/example
用编辑器创建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(); } }
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> <!-- Adapt this to a version found on 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>
你现在能编译和执行HelloWorld类,使用下面的命令:
mvn clean compile exec:java
你能打开你的浏览器在http://localhost:8080看hello world页。你能通过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] ------------------------------------------------------------------------
先前的例子演示怎么通过Maven在应用中使用嵌入Jetty。现在我们将测试看怎么使用Maven和Jetty开发一个标准webapp。首先创建Maven结构(你也能用maven webapp archetype代替):
> mkdir JettyMavenHelloWarApp > cd JettyMavenHelloWebApp > mkdir -p src/main/java/org/example > mkdir -p src/main/webapp/WEB-INF
用编辑器创建文件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="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="false" version="3.0"> <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>
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.0.2.v20130417</jettyVersion> /// Adapt this to a version found on http://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-maven-plugin/ </properties> <dependencies> <dependency> <groupId>org.eclipse.jetty.orbit</groupId> <artifactId>javax.servlet</artifactId> <version>3.0.0.v201112011016</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>
通过使用jetty-maven-plugin,现在你能构建和运行web应用不需要打包到war,只需使用下面的命令:
> mvn jetty:run
你能在http://localhost:8080/hello看到静态和动态的内容。
jetty-maven-plugin中有大量的配置选项可用,帮助你构建和运行你的webapp。具体看下一节“配置Jetty Maven插件”。
你能创建一个Web Application Archive(WAR)文件,用如下命令:
> mvn package
生成的war文件能够部署在任何标准servlet server,包括Jetty。
Jetty Mven插件对于快速开发和测试是非常有用的。你能增加它到任何Maven构建的webapp项目。插件能周期地扫描你的项目,如果发现任何改变,将自动的重新部署webapp。这使开发周期变得更加快速:你通过IDE改变项目,运行中的web容器自动的替换他们,你立即就能测试改变。
注意:使用该插件必须使用Maven 3和Java 1.7。
首先,增加jetty-maven-plugin到你的pom.xml:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.2-SNAPSHOT</version> </plugin>
然后,从你的根pom.xml目录,执行:
mvn jetty:run
这将启动Jetty并且部署你的项目在http://localhost:8080/。
Jetty持续运行直到你停止它。当它运行时,它周期地扫描你的项目文件的改变,如果你保存了改变并且重编译你的class文件,jetty将重新部署你的webapp,你能立即测试这些你做的改变。
你能在命令行中通过ctrl-c终止插件。
Jetty Maven插件有许多不同的Maven目标。无可争议的最有用的是run目标,用于运行未打包的webapp。有其它目标帮助你完成不同的任务。例如,你可能需要运行你的webapp在一个Jetty的分支实例,而不是在运行Maven的实例内;或者你可能需要更细粒度的控制mavne的生命周期阶段。有不同的目标用于完成这些任务,以及其它的任务。
为了看所有Jetty Maven插件支持的目标,输入:
mvn jetty:help
为了看参数的详细列表,外加它的描述信息,输入:
mvn jetty:help -Ddetail=true -Dgoal= goal-name
这些配置元素设置你的webapp执行的Jetty环境。它们适用于大部分目标:
httpConnector
可选。如果没有指定,Jetty将创建一个ServerConnector实例,监听端口8080。你能改变这个默认端口,通过在命令行使用系统属性jetty.port,例如,mvn -Djetty.port=9999 jetty:run。另外,你能用这个配置元素为ServerConnector设置信息。下面是有效的配置子元素:
1)port:连接器的端口。默认是8080.
2)host:连接器监听的特定主机。默认是所有。
3)name:连接器名,在配置上下文对应特定连接器时使用。
4)idleTimeout:连接器的最大空闲时间。
5)soLinger:套接字逗留时间。
你能配置连接器在一个标准的Jetty xml配置文件,然后用它的路径配置到jettyXml参数。注意由于jetty 9.0不再能在pom.xml中直接地配置https connector:你需要用jetty xml配置文件做它。
jettyXml
可选。一个逗号分隔的jetty xml文件路径列表,用于配置插件配置参数。参考$JETTY_HOME/etc/jetty.xml。
scanIntervalSeconds
扫描webapp变化的间隔,单位秒,当扫描到变化后,将执行自动热重部署。默认是0,表示停止热部署扫描。配置值大于0激活它。
reload
默认值“automatic”,与scanIntervalSeconds联合使用,表示当改变发生时,自动热重部署。设置到“manual”,表示你需要在控制台执行换行来触发插件执行扫描。这有时候是有用的,当你一次做一系列的改变,你想忽略中间的改变时,就可以使用reload参数。
loginServices
可选。一个org.eclipse.jetty.security.LoginService实现的列表。注意没有默认域。你在web.xml中使用的域,也能够在这里指定。你能在一个jetty xml文件中配置login service,将文件位置指定到jettyXml参数。
requestLog
可选。org.eclipse.jetty.server.RequestLog请求日志接口的一个实现。遵守NCSA格式的实现( org.eclipse.jetty.server.NCSARequestLog)是可用的。有三种其它方式用于配置RequestLog:
1)在一个Jetty xml配置文件中,指定文件路径到jettyXml参数;
2)在一个上下文配置文件中,指定文件路径到contextXml参数;
3)在webApp元素中。
更多信息参考“Jetty日志”。
stopPort
可选。端口用于监听停止命令。运行stop或者run-forked目标时使用。
stopKey
可选。用于和stopPort联合使用,用于停止jetty。运行stop或者run-forked目标时使用。
systemProperties
可选。允许你配置System属性,用于运行插件。
systemPropertiesFile
可选。一个包含System属性的文件。默认,你在这里做的设置不重载任何已经在命令行、JVM、POM(通过systemProperties)中设置的系统属性。
skip
默认是false。如果true,插件的执行退出。等同于设置SystemProperty -Djetty.skip在命令行。这是非常有用的,当配置Jetty为综合测试而你想略过测试代码时。
useProvidedScope
默认值false。如果true,<scope>provided</scope>的依赖被放置到容器classpath。注意这不是webapp的classpath,“provided”表示这些依赖通常被期望由容器提供。你应该很少需要用到这。相反,你应该拷贝provided依赖作为插件直接的依赖。
excludedGoals
可选。jetty插件目标名的列表,插件将打印信息然后退出。当你想阻止用户执行项目无法支持的目标时使用。
为了配置一个https连接器,你需要用jetty xml配置文件。这个例子用的文件直接从jetty发布的etc/目录拷贝过来,你也可以自己实现。我们将用下面这些文件:
jetty.xml
设置the org.eclipse.jetty.server.Server的几个特性,供插件使用。主要是配置org.eclipse.jetty.server.HttpConfiguration元素供配置连接器时使用。下面是相关配置:
<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> <!-- Uncomment to enable handling of X-Forwarded- style headers <Call name="addCustomizer"> <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg> </Call> --> </New>
jetty-ssl.xml
设置同https连接器使用的ssl。下面是来自jetty发布的jetty-ssl.xml文件:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <!-- ============================================================= --> <!-- Configure a TLS (SSL) Context Factory --> <!-- This configuration must be used in conjunction with jetty.xml --> <!-- and either jetty-https.xml or jetty-spdy.xml (but not both) --> <!-- ============================================================= --> <Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"> <Set name="KeyStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.keystore" default="etc/keystore"/></Set> <Set name="KeyStorePassword"><Property name="jetty.keystore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set> <Set name="KeyManagerPassword"><Property name="jetty.keymanager.password" default="OBF:1u2u1wml1z7s1z7a1wnl1u2g"/></Set> <Set name="TrustStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.truststore" default="etc/keystore"/></Set> <Set name="TrustStorePassword"><Property name="jetty.truststore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set> <Set name="EndpointIdentificationAlgorithm"></Set> <Set name="NeedClientAuth"><Property name="jetty.ssl.needClientAuth" default="false"/></Set> <Set name="WantClientAuth"><Property name="jetty.ssl.wantClientAuth" default="false"/></Set> <Set name="ExcludeCipherSuites"> <Array type="String"> <Item>SSL_RSA_WITH_DES_CBC_SHA</Item> <Item>SSL_DHE_RSA_WITH_DES_CBC_SHA</Item> <Item>SSL_DHE_DSS_WITH_DES_CBC_SHA</Item> <Item>SSL_RSA_EXPORT_WITH_RC4_40_MD5</Item> <Item>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</Item> <Item>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</Item> <Item>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</Item> </Array> </Set> <!-- =========================================================== --> <!-- Create a TLS specific HttpConfiguration based on the --> <!-- common HttpConfiguration defined in jetty.xml --> <!-- Add a SecureRequestCustomizer to extract certificate and --> <!-- session information --> <!-- =========================================================== --> <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> </Call> </New> </Configure>
jetty-https.xml
设置https连接器,用jetty.xml的HttpConfiguration和jetty-ssl.xml的ssl配置:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <!-- ============================================================= --> <!-- Configure a HTTPS connector. --> <!-- This configuration must be used in conjunction with jetty.xml --> <!-- and jetty-ssl.xml. --> <!-- ============================================================= --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- Add a HTTPS Connector. --> <!-- Configure an o.e.j.server.ServerConnector with connection --> <!-- factories for TLS (aka SSL) and HTTP to provide HTTPS. --> <!-- All accepted TLS connections are wired to a HTTP connection.--> <!-- --> <!-- Consult the javadoc of o.e.j.server.ServerConnector, --> <!-- o.e.j.server.SslConnectionFactory and --> <!-- o.e.j.server.HttpConnectionFactory for all configuration --> <!-- that may be set here. --> <!-- =========================================================== --> <Call id="httpsConnector" name="addConnector"> <Arg> <New class="org.eclipse.jetty.server.ServerConnector"> <Arg name="server"><Ref refid="Server" /></Arg> <Arg name="factories"> <Array type="org.eclipse.jetty.server.ConnectionFactory"> <Item> <New class="org.eclipse.jetty.server.SslConnectionFactory"> <Arg name="next">http/1.1</Arg> <Arg name="sslContextFactory"><Ref refid="sslContextFactory"/></Arg> </New> </Item> <Item> <New class="org.eclipse.jetty.server.HttpConnectionFactory"> <Arg name="config"><Ref refid="sslHttpConfig"/></Arg> </New> </Item> </Array> </Arg> <Set name="host"><Property name="jetty.host" /></Set> <Set name="port"><Property name="https.port" default="443" /></Set> <Set name="idleTimeout"><Property name="https.timeout" default="30000"/></Set> <Set name="soLingerTime"><Property name="https.soLingerTime" default="-1"/></Set> </New> </Arg> </Call> </Configure>
接下来你需要让插件知道应用上面的文件:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <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_0.dtd"> <!-- ============================================================= --> <!-- Configure the Jetty Server instance with an ID "Server" --> <!-- by adding a HTTP connector. --> <!-- This configuration must be used in conjunction with jetty.xml --> <!-- ============================================================= --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- Add a HTTP Connector. --> <!-- Configure an o.e.j.server.ServerConnector with a single --> <!-- HttpConnectionFactory instance using the common httpConfig --> <!-- instance defined in jetty.xml --> <!-- --> <!-- Consult the javadoc of o.e.j.server.ServerConnector and --> <!-- o.e.j.server.HttpConnectionFactory for all configuration --> <!-- that may be set here. --> <!-- =========================================================== --> <Call name="addConnector"> <Arg> <New class="org.eclipse.jetty.server.ServerConnector"> <Arg name="server"><Ref refid="Server" /></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> </New> </Item> </Array> </Arg> <Set name="host"><Property name="jetty.host" /></Set> <Set name="port"><Property name="jetty.port" default="80" /></Set> <Set name="idleTimeout"><Property name="http.timeout" default="30000"/></Set> <Set name="soLingerTime"><Property name="http.soLingerTime" default="-1"/></Set> </New> </Arg> </Call> </Configure>
接下来为插件添加配置列表:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <jettyXml>jetty.xml,jetty-http.xml,jetty-ssl.xml,jetty-https.xml</jettyXml> </configuration> </plugin>
这些配置参数应用到你的webapp。他们对几乎所有目标都适用。
webApp
类org.eclipse.jetty.webapp.WebAppContext的一个扩展。你能用对象的setter方法配置你的webapp。下面是常用的一些:
1)contextPath:你的webapp的上下文路径。默认是/。
2)descriptor:web.xml文件的路径。
3)defaultsDescriptor:webdefault.xml的路径,在web.xml之前使用。如果你不提供,Jetty用一个默认文件,在jetty-webapp.jar中。
4)overrideDescriptor:web.xml文件路径,在你的web.xml之后应用。你能用这重载或者添加配置。
5)tempDirectory:当你的webapp运行时,Jetty用于解压和拷贝jar包和jsp编译结果的文件夹。默认是${project.build.outputDirectory}/tmp。
6)baseResource:Jetty提供静态资源的路径,默认是src/main/webapp。
7)resourceBases:用于代替baseResource提供静态资源,是一个数组,可以提供多个提供静态资源的文件夹。
8)baseAppFirst:默认“true”。
contextXml
一个上下文xml文件的路径,在webApp之后应用到你的webapp。
run目标不必构建webapp到WAR。取而代之,Jetty从它的源头部署webapp。它在Maven项目中查找webapp的组件部分,虽然你能在插件的配置中重载他们。例如,默认它查找:
1)在${project.basedir}/src/main/webapp中的资源;
2)在${project.build.outputDirectory}中的类;
3)在${project.basedir}/src/main/webapp/WEB-INF/中的web.xml。
在部署前,插件自动的确认类被重建和更新。如果你改变了类的源代码,你的IDE会在后台自动的编译它,插件挑选改变的类。
你不需要打包webapp到WAR,节省部署周期时间。你能配置插件持续执行,扫描项目的改变并在需要的时候自动热部署。你做的任何改变会立即反应到运行中的Jetty实例中,让你能快速的从编码跳转到测试,而不是:编码、编译、打包、重部署、测试。
下面是一个简单的例子,每10秒执行一次改变扫描,并设置上下文路径到/test:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> </configuration> </plugin>
除了webApp元素之外,jetty:run目标支持:
1)classesDirectory:你的webapp编译后的类的位置。你应该很少需要设置这个参数。取而代之,你应该设置你的pom.xml中的build outputDirectory。
2)testClassesDirectory:你的webapp的编译后的测试类的位置。默认是 ${project.build.testOutputDirectory}。
3)useTestScope:如果true,testClassesDirectory中的类和“test”范围的依赖首先被放置在classpath。默认是false。
4)webAppSourceDirectory:默认,这被设置到 ${project.basedir}/src/main/webapp。如果你的静态资源在不同的位置,相应地设置该参数。
5)jettyEnvXml:可选。jetty-env.xml文件的位置。
6)scanTargets:可选。文件和文件夹的列表,除了那些插件自动扫描的目录和文件,插件增加对这些配置的周期扫描。
7)scanTargetPatterns:可选。如果你需要额外扫描的文件列表过长,你可以通过匹配表达式来指定它们。
下面是一个更详细的配置的例子:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <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> <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和run-exploded目标。
这个目标首先将你的webapp打包为WAR,然后部署它到Jetty。如果你设置非0的scanInterval,Jetty监视你的pom.xml和WAR文件;如果改变,它重部署war。
war:WAR文件的位置。默认是${project.build.directory}/${project.build.finalName}.war。如果需要,设置你的自定义路径。
下面是配置的例子:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <war>${project.basedir}/target/mycustom.war</war> </configuration> </plugin> </plugins> </project>
run-exploded目标首先打包你的webapp到一个分解的WAR文件,然后部署它到Jetty。如果你设置了非0的scanInterval,Jetty监视你的pom.xml、WEB-INF/lib、WEB-INF/中的类和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> <configuration> <war>${project.basedir}/target/myfunkywebapp</war> </configuration> </plugin> </plugins> </project>
这个基本上和jetty:run-war相同,除了没有装配当前模块的WAR。不想run-war,插件不必执行到"package"阶段。例如,你可以启动jetty在"test-compile"阶段,停止jetty在"test-phase"阶段。
war:WAR文件的位置。默认 ${project.build.directory}/${project.build.finalName},你能通过设置该参数覆盖该值。
下面是配置的例子:
<project> ... <plugins> ... <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <war>${project.basedir}/target/mycustom.war</war> </configuration> <executions> <execution> <id>start-jetty</id> <phase>test-compile</phase> <goals> <goal>deploy-war</goal> </goals> <configuration> <daemon>true</daemon> <reload>manual</reload> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> </plugins> </project>
这个目标允许你在一个新的JVM中启动webapp,随意地传递参数到新的JVM。
注意:不幸的是,不想大部分其它目标,这个不支持webApp参数。因此,如果你的webapp要求许多配置,则不能使用该目标。
下面是可用的配置参数:
1)jettyXml:jetty xml配置文件的位置,用于在新的JVM中配置容器。
2)contextXml:可选。上下文文件的位置,用于在新的JVM中配置webapp。
3)contextPath:可选。新JVM中webapp的上下文路径。默认 /${project.artifactId}。
4)webAppSourceDirectory:可选。你的webapp的静态资源位置。默认src/main/webapp。
5)resourceBases:可选。包含你的webapp静态内容的文件夹数组,与webAppSourceDirectory一起。也看baseAppFirst。
6)baseAppFirst:默认“true”。控制webAppSourceDirectory或者resourceBases是否第一个在资源列表上。
7)webXml:web.xml文件的位置。默认src/main/webapp/WEB-INF/web.xml。
8)tmpDirectory:临时文件夹。默认 ${project.build.directory}/tmp。
9)classesDirectory:编译后的类文件位置。默认 ${project.build.outputDirectory}。
10)testClassesDirectory:编译后测试类位置。默认 ${project.build.testOutputDirectory}。
11)useTestScope:默认“false”。如果true,范围"provided"的依赖被放置到jetty容器的classpath。
12)stopPort:强制的。一个端口号,jetty用于监听stop命令。如果配置,stopKey被用于认证接收的stop命令。
13)stopKey:强制的。一个String,用于认证stop命令。
14)skip:可选。默认false。如果true,插件的执行被略过。
15)jvmArgs:可选。一个String,表示传递到新JVM的任意参数。
为了部署你的未装配的web应用到运行在新JVM中的Jetty:
mvn jetty:run-forked
Jetty将持续执行直到:
1)在终端窗口执行ctrl+c,同时也停止另一个JVM。
2)用jetty:stop停止另一个JVM,也停止插件。
注意:如果你想设置一个自定义端口,你需要指定它在jetty.xml文件中,而不是设置连接器和端口标签。你能使用jettyXml参数执行jetty.xml的位置。
这个目标类似于jetty:run目标,然而它直到"test-compile"才执行构建,以确保所有webapp需要的类和文件已经被产生。当你想控制Jetty的start和stop时这是非常有用的。
例如,你能配置插件在你的单元测试开始的时候启动,在单元测试结束时停止。为了做这,你需要为Jetty插件设置一套execution方案,用<daemon>true</daemon>配置选项使Jetty仅当Maven运行时执行。你用pre-integration-test和post-integration-test Maven构建阶段触发Jetty的执行和终止:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <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> <daemon>true</daemon> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin>
当然你也可以在命令行中使用该目标,但你你需要确保你的webapp需要的所有类和文件已经被产生。
stop目标用于停止Jetty。为了使用它,你需要使用一个特殊的端口号和key来配置插件。这个端口号和key也将用于start目标。
1)stopPort:Jetty用于接收stop命令的端口号。
2)stopKey:用于验证stop命令。
下面是配置的例子:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <stopPort>9966</stopPort> <stopKey>foo</stopKey> <stopWait>10</stopWait> </configuration> </plugin>
当Jetty正在运行时,执行:
mvn jetty:stop
注意stopPort必须是空闲的。
你能在插件中配置LoginServices。下面是为webapp设置HashLoginService的例子:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <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>
如果你有额外的资源想要合并到当前的webapp中,但没有被集成到WAR中,你能告诉Jetty这些额外的资源位于的文件夹。在运行时,当Jetty收到一个资源请求时,它搜索所有的路径得到资源。下面是配置例子:
<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>
你能用一个jetty.xml文件配置你想部署的额外的(预编译的)webapp,或者你能用<contextHandlers>配置元素来做。如果你想部署webapp A,和webapp B和C在同一个Jetty实例中:
放配置想在webapp A的 pom.xml中:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> <contextHandlers> <contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext"> <war>${project.basedir}../../B.war</war> <contextPath>/B</contextPath> </contextHandler> <contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext"> <war>${project.basedir}../../C.war</war> <contextPath>/B</contextPath> </contextHandler> </contextHandlers> </configuration> </plugin>
或者,增加一个jetty.xml文件到webapp A。从jetty发布版本中拷贝jetty.xml文件,然后为其它两个webapp增加WebAppContext:
<Ref refid="Contexts">
<Call name="addHandler">
<Arg>
<New class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/B</Set>
<Set name="war">../../B.war</Set>
</New>
</Arg>
</Call>
<Call>
<Arg>
<New class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/C</Set>
<Set name="war">../../C.war</Set>
</New>
</Arg>
</Call>
</Ref>
然后配置这个jetty.xml文件的位置到webapp A的jetty插件:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/test</contextPath> </webApp> <jettyXml>src/main/etc/jetty.xml</jettyXml> </configuration> </plugin>
为这任何一种方式,其它的webapp都必须已经被构建,并且他们会被监控变化。
你能用maven properites插件定义系统属性。下面是一个例子配置logback logging系统作为jetty logger:
<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>参数的使用)。
下面是一个例子怎么在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>
你也能在一个文件中指定你的系统属性。通过这种方式指定的系统属性不会覆盖命令行、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来指定文件。
如果你设置一个非0的scanInterval配置参数,jetty maven插件将每scanInterval执行一次文件扫描,如果发现变化,则根据配置重新部署webapp。被扫描的文件依赖被执行的目标。
目标 | 文件 |
---|---|
Jetty:run | pom.xml, <dependencies>, <classesDirectory>, <testClassesDirectory>, <webXml> or <webAppSourceDirectory>/WEB-INF/web.xml, <jettyEnvXml> or <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <scanTargets>, <scanTargetPatterns>, any defaultsDescriptor for the webapp, any overrideDescriptor for the 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> or <webAppSourceDirectory>/WEB-INF/web.xml, <jettyEnvXml> or <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <scanTargets>, <scanTargetPatterns>, any defaultsDescriptor for the webapp, any overrideDescriptor for the webapp |
jetty:stop |
这个插件将帮助你预编译你的jsp,并和相关的maven war插件一起放他们到集成的war中。
下面是jspc插件要求的基本设置:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jspc-maven-plugin</artifactId> <version>9.1.0.RC1</version> <executions> <execution> <id>jspc</id> <goals> <goal>jspc</goal> </goals> <configuration> </configuration> </execution> </executions> </plugin>
配置参数(configuration)如下:
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
includes
默认值:**\/*.jsp, **\/*.jspx
逗号分隔的模式列表,指定将被处理的文件。
excludes
默认值:**\/.svn\/**
逗号分隔的模式列表,指定排除的文件。
classesDirectory
默认值:${project.build.outputDirectory}
webapp的类放置的路径
generatedClasses
默认值:${project.build.outputDirectory}
jsp产生的类放置的路径
insertionMarker
默认值:none
一个标记String,在源web.xml中,指示长生的web.xml片段的插入位置。
useProvidedScope
默认值:true 是否嵌入产生的片段文件到源web.xml。嵌入的文件将进入同样的文件夹作为webXmlFragment。
keepSources
默认值:false
如果true,产生的.java文件被处理完后将不被删除。
tldJarNamePatterns
默认值:.*taglibs[^/]*\.jar|.*jstl-impl[^/]*\.jar$
在包含tld的‘系统’(例如容器)路径上的jar的模式。用|分隔。
jspc
默认值:org.apache.jasper.JspC
JspC类真正执行预编译。在JspC类上的所有setter都是可用的。你能从这里下载javadoc。
采用所有的默认值,下面是怎么配置war查将,使用产生的web.xml,包含所有jsp servlet声明:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <webXml>${project.basedir}/target/web.xml</webXml> </configuration> </plugin>