Исполняемый файл war, который запускает jetty без maven
Я пытаюсь сделать "исполняемый" файл War (java -jar myWarFile.war), который запустит веб-сервер причала, на котором размещается веб-приложение, содержащееся в файле WAR, который я выполнил.
нашел страница это описало, как сделать то, что я ищу:
однако, следуя этому совету вместе с тем, как я думаю, что я должен сделать исполняемый jar (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.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.
здесь, похоже, есть две ошибки: одна, где кажется, что файлы JAR не могут быть найдены, и одна, где Start класс не может быть найден.
чтобы исправить первый, я положил файлы Jetty JAR в базу файла WAR и попытался снова-та же ошибка. Я также попытался добавить WEB-INF/lib/<specific-JAR-files> к Class-Path атрибут манифеста. Это тоже не сработало.
есть ли у кого-нибудь представление о том, что я делаю правильно/неправильно и как я могу получить этот исполняемый файл войны и работает?
9 ответов:
The ссылке вы в своем вопросе предоставляете большую часть того, что вам нужно. Однако, есть несколько вещей, которые нужно сделать в дополнение к этому.
все файлы классов, которые Jetty необходимо запустить, должны быть расположены в корне файла war, когда он упакован. Мы можем использовать Ant, чтобы сделать это за нас, прежде чем мы
<war>файл. Файл манифеста войны также будет нуждаться вMain-Classатрибут для выполнения сервера.здесь шаг за шагом:
создайте свой класс сервера причала:
это адаптировано из ссылки, которую вы предоставили.
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(); } }чтобы увидеть, что все вы можете настроить здесь, взгляните на Jetty API documentation.
построить войну с Ant:
это использует промежуточный каталог для распаковки необходимых файлов классов в корень войны, чтобы они были доступны, когда война выполненный.
<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 --> <!-- e.g. --> <!-- 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
это адаптация для Maven ответа @RobHruska. Он просто копирует файлы основного класса и объединяет файлы 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, он создает еще одну войну, которую можно использовать с java-jar whateverpackage-runnable.война
<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, который поддерживает этот вариант использования напрямую. http://winstone.sourceforge.net/#embedding
возможно, это будет работать для вас?
хотя это своего рода старая еще одна альтернатива с Jetty 8-это просто включить Jetty jars в качестве зависимостей в вашем pom и добавить следующее в ваш 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 "вы хотите банку, которую вы можете запустить самостоятельно, а не с"mvn jetty:run" - не то, что вы вообще не хотите использовать maven.
Мне потребовалось много времени, чтобы понять это, потому что я нашел много вариантов-ни один из них не был простым. В конце концов я нашел этот плагин maven от simplericity. Это прекрасно работает.
Это мой пример муравьиного экстракта. Идея состоит в том, чтобы распаковать зависимости причала, а затем включить их локально, как обычный файл 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 директория предназначена для зависимостей веб-приложений. В этом случае мы упаковываем файл WAR так, чтобы он работал как обычный файл Jetty JAR при запуске
- положить .банки внутри А.War file root ничего не делает
- положить .банки внутри
WEB-INF/libне помогает JVM найти файлы причала, чтобы даже начать запуск вашего .война. Это" слишком поздно", чтобы положить их туда.- положить .jars в манифесте Class-Path работает только для внешних .JAR файлы, а не те, которые содержатся в .банку
так что делать?
- используйте скрипт сборки, чтобы просто объединить все .jar-файлы, которые вам нужны .война файл. Это требует немного дополнительной работы. Это также немного уродливо в том, что скомпилированный код является частью обслуживаемых файлов .война
- добавить зависимые .банки в classpath, который для JVM с "Ява -СР пристани.сосуд.:.. ..."Работает, хотя этот вид поражает цель одного автономного .война
Я уже делал подобное раньше, но вы запускаете приложение как "java-jar xxx. war"?. У вас есть только 2 банки, и это не будет достаточно, я думаю. Также попробуйте использовать Jetty 7.0. 0M1 (которая является последней версией). Когда я добавил jetty-server и jetty-webapp в качестве двух зависимостей (они из org.затмение.jetty) я получаю следующую банку в каталоге lib. К вашему сведению, организация.mortbay.пристань.Хендлер был в машине причал-сервер*.сосуд.
- причал-продолжение-7.0.0.М1.банку
- jetty-http-7.0.0.М1.банку
- jetty-io-7.0.0.М1.банку
- jetty-security-7.0.0.М1.банку
- jetty-server-7.0.0.М1.банку
- jetty-servlet-7.0.0.М1.банку
- jetty-util-7.0.0.М1.банку
- jetty-webapp-7.0.0.М1.банку
- jetty-xml-7.0.0.М1.банку
Comments