可执行的war文件,无需maven即可启动jetty

我正在尝试创build一个“可执行”war文件( java -jar myWarFile.war ),它将启动一个Jetty Web服务器,该Web服务器托pipe包含在我执行的WAR文件中的Web应用程序。

我find了一个描述如何使我所寻找的网页 :

然而,遵循这个build议以及我认为我应该做一个可执行的jar(战争)是行不通的。

我有一个Ant任务创build一个WAR文件,其清单如下所示:

 Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7.1 Created-By: 1.5.0_18-b02 (Sun Microsystems Inc.) Main-Class: Start 

WAR文件的内容如下所示:

 > Start.class > jsp > build.jsp > META-INF > MANIFEST.MF > WEB-INF > lib > jetty-6.1.22.jar > jetty-util.6.1.22.jar 

当我尝试执行WAR文件时,错误是:

 Exception in thread "main" java.lang.NoClassDefFoundError: org/mortbay/jetty/Handler Caused by: java.lang.ClassNotFoundException: org.mortbay.jetty.Handler at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) Could not find the main class: Start. Program will exit. 

这里似乎有两个错误:一个看起来不能findJAR文件,另一个找不到Start类。

为了解决第一个问题,我把Jetty JAR文件放在WAR文件的底部,然后重试 – 同样的错误。 我也尝试将WEB-INF/lib/<specific-JAR-files>到清单的Class-Path属性中。 那也行不通。

有没有人有任何的洞察力,我在做什么对/错,我怎么能得到这个可执行文件的WAR文件启动和运行?

你在你的问题中的链接提供了你所需要的大部分。 但是,除此之外还有一些需要做的事情。

Jetty需要启动的任何类文件在打包时都需要位于war文件的根目录下。 我们可以在我们<war>文件之前利用Ant来为我们做这件事。 战争的清单文件还需要一个Main-Class属性来执行服务器。

这里是一步一步的:

创build您的Jetty服务器类:

这是从你提供的链接改编的。

 package com.mycompany.myapp; import java.io.File; import java.net.URL; import java.security.ProtectionDomain; import org.mortbay.jetty.Server; import org.mortbay.jetty.webapp.WebAppContext; public final class EmbeddedJettyServer { public static void main(String[] args) throws Exception { int port = Integer.parseInt(System.getProperty("port", "8080")); Server server = new Server(port); ProtectionDomain domain = EmbeddedJettyServer.class.getProtectionDomain(); URL location = domain.getCodeSource().getLocation(); WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); webapp.setDescriptor(location.toExternalForm() + "/WEB-INF/web.xml"); webapp.setServer(server); webapp.setWar(location.toExternalForm()); // (Optional) Set the directory the war will extract to. // If not set, java.io.tmpdir will be used, which can cause problems // if the temp directory gets cleaned periodically. // Your build scripts should remove this directory between deployments webapp.setTempDirectory(new File("/path/to/webapp-directory")); server.setHandler(webapp); server.start(); server.join(); } } 

要了解您可以在这里configuration什么,请查看Jetty API文档 。

与Antbuild立战争:

这将使用一个临时目录来将必要的类文件解压到战争的根目录中,以便在战争执行时可以访问它们。

 <target name="war" description="--> Creates self-executing war"> <property name="staging.dir" location="${basedir}/staging"/> <property name="webapp.dir" location="${basedir}/src/webapp"/> <mkdir dir="${staging.dir}"/> <!-- assumes you have all of your war content (excluding classes and libraries) already structured in a directory called src/webapp --> <!-- eg --> <!-- src/webapp/index.html --> <!-- src/webapp/WEB-INF/web.xml --> <!-- src/webapp/WEB-INF/classes/my.properties --> <!-- etc ... --> <copy todir="${staging.dir}"> <fileset dir="${webapp.dir}" includes="**/*"/> </copy> <unjar dest="${staging.dir}"> <!-- you'll have to locate these jars or appropriate versions; note that these include JSP support --> <!-- you might find some of them in the downloaded Jetty .tgz --> <fileset dir="path/to/jetty/jars"> <include name="ant-1.6.5.jar"/> <include name="core-3.1.1.jar"/> <include name="jetty-6.1.24.jar"/> <include name="jsp-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary --> <include name="jsp-api-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary --> <include name="servlet-api-2.5-20081211.jar"/><!-- your Servlet API implementation may vary --> </fileset> <patternset><!-- to exclude some of the stuff we don't really need --> <exclude name="META-INF/**/*"/> <exclude name="images/**/*"/> <exclude name=".options"/> <exclude name="about.html"/> <exclude name="jdtCompilerAdapter.jar"/> <exclude name="plugin*"/> </patternset> </unjar> <!-- copy in the class file built from the above EmbeddedJettyServer.java --> <copy todir="${staging.dir}"> <fileset dir="path/to/classes/dir" includes="com/mycompany/myapp/EmbeddedJettyServer.class"/> </copy> <war destfile="myapp.war" webxml="${webapp.dir}/WEB-INF/web.xml"> <fileset dir="${staging.dir}" includes="**/*"/> <classes dir="path/to/classes/dir"/><!-- your application classes --> <lib dir="path/to/lib/dir"/><!-- application dependency jars --> <manifest> <!-- add the Main-Class attribute that will execute our server class --> <attribute name="Main-Class" value="com.mycompany.myapp.EmbeddedJettyServer"/> </manifest> </war> <delete dir="${staging.dir}"/> </target> 

执行战争:

如果一切设置正确上面,你应该能够:

 java -jar myapp.war // or if you want to configure the port (since we are using the System property in the code) java -Dport=8443 -jar myapp.war 

这是@ RobHruska的答案Maven的改编。 它只是复制主类的文件,并将Jetty JAR文件合并到WAR文件中,这并不是什么新鲜事,只是为了简化您的生活,如果您是新成员,就像Maven一样:

 <plugin> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>move-main-class</id> <phase>compile</phase> <configuration> <tasks> <copy todir="${project.build.directory}/${project.build.finalName}"> <fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/classes/"> <include name="main/*.class" /> </fileset> </copy> <unjar dest="${project.build.directory}/${project.build.finalName}"> <!-- you'll have to locate these jars or appropriate versions; note that these include JSP support --> <!-- you might find some of them in the downloaded Jetty .tgz --> <fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/lib/"> <include name="ant-1.6.5.jar"/> <!--<include name="core-3.1.1.jar"/>--> <include name="jetty*"/> <include name="servlet-api*"/> </fileset> <patternset><!-- to exclude some of the stuff we don't really need --> <exclude name="META-INF/**/*"/> <exclude name="images/**/*"/> <exclude name=".options"/> <exclude name="about.html"/> <exclude name="jdtCompilerAdapter.jar"/> <exclude name="plugin*"/> </patternset> </unjar> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.2</version> <configuration> <archiveClasses>true</archiveClasses> <archive> <manifest> <mainClass>main.Main</mainClass> </manifest> </archive> </configuration> </plugin> 

我们通过使用jetty-console-maven-plugin来解决这个问题。

每当你运行mvn包时,它会创build另一个可以与java -jar一起使用的war -packpack-runnable.war

  <plugin> <groupId>org.simplericity.jettyconsole</groupId> <artifactId>jetty-console-maven-plugin</artifactId> <version>1.45</version> <executions> <execution> <goals> <goal>createconsole</goal> </goals> </execution> </executions> <configuration> <additionalDependencies> <additionalDependency> <artifactId>jetty-console-requestlog-plugin</artifactId> </additionalDependency> <additionalDependency> <artifactId>jetty-console-gzip-plugin</artifactId> </additionalDependency> <additionalDependency> <artifactId>jetty-console-ajp-plugin</artifactId> </additionalDependency> <additionalDependency> <artifactId>jetty-console-startstop-plugin</artifactId> </additionalDependency> </additionalDependencies> </configuration> </plugin> 

它也为你生成init.d脚本和一切!

Hudson使用Winstone servlet容器来解决这个确切的问题,它直接支持这个用例。 http://winstone.sourceforge.net/#embedding

也许这对你有用?

即使这是旧的另一种select与Jetty 8是简单地包括作为依附在您的POMdockerjar,并在您的POM(与一个ant脚本解开战争,并重新包装它)添加以下内容:

  <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <createDependencyReducedPom>true</createDependencyReducedPom> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>JettyStandaloneMain</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> <!-- The main class needs to be in the root of the war in order to be runnable --> <plugin> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>move-main-class</id> <phase>compile</phase> <configuration> <tasks> <move todir="${project.build.directory}/${project.build.finalName}"> <fileset dir="${project.build.directory}/classes/"> <include name="JettyStandaloneMain.class" /> </fileset> </move> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> 

我认为,通过“没有maven”,你需要一个你自己可以运行的jar,而不是“mvn jetty:run” – 而不是你根本不想使用maven。

我花了很长时间才弄清楚这一点,因为我发现了很多选项 – 它们都不是很简单。 最终我发现这个来自simplericity的maven插件 。 它奇妙地工作。

这是我的示例ANT提取。 这个想法是解压缩Jetty的依赖关系,然后将它们包含在本地,就像一个普通的JAR文件一样:

 <!-- Hack: Java doesn't support jars within jars/wars --> <unjar src="${lib.dir}/container/jetty.jar" dest="${build.dir}/unjar"/> <unjar src="${lib.dir}/container/jetty-util.jar" dest="${build.dir}/unjar"/> <unjar src="${lib.dir}/container/servlet-api.jar" dest="${build.dir}/unjar"/> <unjar src="${lib.dir}/container/jsp-api.jar" dest="${build.dir}/unjar"/> <!-- Build war file as normal, just including the compiled and unjar'ed files --> <war destfile="${war.file}" webxml="${config.dir}/web.xml"> <fileset dir="${build.dir}/classes"/> <fileset dir="${build.dir}/unjar"/> <fileset dir="${resources.dir}" excludes="*.swp"/> <lib dir="${lib.dir}/runtime"/> <manifest> <attribute name="Main-Class" value="Start"/> </manifest> </war> 

注意:

WEB-INF / lib direcory用于Web应用程序依赖项。 在这种情况下,我们打包WAR文件,使其在启动时像普通的Jetty JAR文件一样工作

  • 将.jar放入.war文件根目录中什么也不做
  • WEB-INF/lib中放入.jars并不能帮助JVMfindJetty文件甚至开始启动.war。 把它们放在那里“太迟了”。
  • 在清单中放置.jars类path仅适用于外部.jar文件,而不适用于.jar文件

那么该怎么办?

  • 使用构build脚本将所有需要的.jar文件合并到.war文件中。 这需要一些额外的工作。 编译的代码是.war中的可用文件的一部分也是有点难看的
  • 使用“java -cp jetty.jar:… …”将相关的.jars添加到JVM的类path中。尽pipe这样做会破坏一个独立的.war

我以前做过类似的事情,但是你是否启动应用程序为“java -jar xxx.war”? 你只有两个jar子,我觉得还不够。 也尝试使用Jetty 7.0.0M1(这是最新版本)。 当我添加jetty-server和jetty-webapp作为两个依赖项(它们来自org.eclipse.jetty)时,我在lib目录中获得以下jar。 仅供参考,org.mortbay.jetty.Handler在jetty-server * .jar中。

  • docker – 连续 – 7.0.0.M1.jar
  • docker-HTTP-7.0.0.M1.jar
  • docker-IO-7.0.0.M1.jar
  • docker安全,7.0.0.M1.jar
  • docker – 服务器7.0.0.M1.jar
  • docker-servlet的7.0.0.M1.jar
  • docker-UTIL-7.0.0.M1.jar
  • docker-web应用,7.0.0.M1.jar
  • docker的XML-7.0.0.M1.jar