使用Maven来创建“可运行的WAR". [英] Using Maven to create "runnable WAR"
问题描述
好的,我正在尝试创建一个可使用Maven从命令行运行的war文件.
Okay, I'm trying to create a war file that is runnable from the command line using Maven.
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warName>${project.artifactId}-${project.version}</warName>
<warSourceDirectory>src\main\java\META-INF\webapp\WEB-INF</warSourceDirectory>
<webXml>src\main\java\META-INF\webapp\WEB-INF\web.xml</webXml>
<archive>
<manifest>
<mainClass>classes\ReportToolRunner</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>default-war</id>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
运行编译的war文件时,出现错误:找不到或加载主类class \ ReportToolRunner",我尝试了< \ mainClass>标记的所有不同路径.
When I run the compiled war file, I get "Error: Could not find or load main class classes\ReportToolRunner", I've tried all manner of different paths for the <\mainClass> tag.
我不想使用tomcat或类似的工具进行战争,我只想能够像这样进行战争:
I don't want to run the war using tomcat or anything like that, I just want to be able to run it like:
java -jar reportTool.war
我正在将Jetty用于我的Web服务器.
I'm using Jetty for my web server.
推荐答案
如果您嵌入了像Jetty这样的servlet容器,则有可能: 嵌入式码头可执行战.
It is possible, if you embed a servlet container like Jetty: Embedded Jetty Executable War.
注意:一场可战役的战争并不常见. (例如,詹金斯(Jenkins)这样做-它允许用户决定是独立运行应用程序-也许是为了进行某些产品评估,而不应该安装其他基础结构-还是将其部署在(共享的)servlet容器上,从而对其进行管理和管理.监视)
Note: A runnable war is not very common. (For example Jenkins did this - It allows the user to decide whether to run the application standealone - maybe for some product evaluation, where no further infrastructure should be installed - or to deploy it on a (shared) servlet container, which gets managed and monitored)
解决方案: 以下步骤是必需的,并且可以使用标准Maven插件来实现:
Solution: The following steps are necessary and can be achieved with standard Maven plugins:
- 编写一个Main类,该类将启动Jetty服务器并添加webapp上下文
- 在prepare-package阶段,将Main类和用于服务器的所有类从$ {project.build.directory}/classes/移至目标war目录,以实现jar布局(在war文件中,这些类是在类"文件夹中,但在jar文件中,这些类在根文件夹中)
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>classes-copy</id>
<phase>prepare-package</phase>
<configuration>
<tasks>
<move todir="${project.build.directory}/${project.artifactId}-${project.version}/">
<fileset dir="${project.build.directory}/classes/">
<include name="your.package.Main.class" />
</fileset>
</move>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
- 将所有依赖项打包,这对于Jetty服务器启动是必需的,因此这些类是可执行文件大战的一部分. (您可以跳过此步骤,但是当以jar方式执行war时,这些依赖项必须在类路径上可用:java -cp< your classpath> -jar< your war>.(请注意:依赖项列表取决于在您的Jetty服务器实施中)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>jetty-classpath</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty,javax.servlet</includeGroupIds>
<outputDirectory>
${project.build.directory}/${project.artifactId}-${project.version}
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
- 在清单中指定主类,以便可以将jar文件执行为war文件. (请注意:我还指定了战争名称.此名称在以前的插件配置中用作"move todir"和"outputDirectory"的一部分)
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>${project.artifactId}-${project.version}</warName>
<archive>
<manifest>
<mainClass>your.package.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>default-war</id>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
这是我使用的服务器代码(Jetty版本8.1.0.v20120127).它配置一个新的Jetty服务器并添加一个webapp上下文(请参阅最后的代码片段)-如果配置正确,则可以使用server.start()/server.stop()启动和停止该服务器:
Here is the server code (Jetty version 8.1.0.v20120127) I used. It configures a new Jetty server and adds a webapp context (see last code snippet) - if configured correctly the server can be started and stopped with server.start() / server.stop():
// Create connector
SocketConnector connector = new SocketConnector();
connector.setMaxIdleTime(1000 * 60 * 60);
connector.setSoLingerTime(-1);
connector.setPort(8080);
// Create handler collection
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
HandlerCollection handlerCollection = new HandlerCollection();
handlerCollection.setHandlers(new Handler[] { contextHandlerCollection });
// Add webapp context
context.setServer(server);
contextHandlerCollection.addHandler(context);
server.setConnectors(new Connector[] { connector });
server.setHandler(handlerCollection);
最后是webapp上下文代码:
And finally the webapp context code:
public class ServerContextImpl extends WebAppContext {
private static final Logger LOGGER = Logger.getLogger(ServerContextImpl.class);
protected static final String[] JETTY_PLUS_CONFIGURATION_CLASSES;
static {
JETTY_PLUS_CONFIGURATION_CLASSES = new String[7];
JETTY_PLUS_CONFIGURATION_CLASSES[0] = "org.eclipse.jetty.webapp.WebInfConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[1] = "org.eclipse.jetty.webapp.WebXmlConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[2] = "org.eclipse.jetty.webapp.MetaInfConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[3] = "org.eclipse.jetty.webapp.FragmentConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[4] = "org.eclipse.jetty.plus.webapp.EnvConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[5] = "org.eclipse.jetty.plus.webapp.PlusConfiguration";
JETTY_PLUS_CONFIGURATION_CLASSES[6] = "org.eclipse.jetty.webapp.JettyWebXmlConfiguration";
}
ServerContextImpl() {
setConfigurationClasses(JETTY_PLUS_CONFIGURATION_CLASSES);
setContextPath("/");
setWar(getWarLocation());
}
/**
* Returns the location of the war (a trick, which is necessary for executable
* wars please see: <a target="_blank" href=
* "http://uguptablog.blogspot.de/2012/09/embedded-jetty-executable-war-with.html"
* >Embedded Jetty with executable WAR</a>).
*
* @return The war location.
*/
protected String getWarLocation() {
ProtectionDomain protectionDomain = ServerImpl.class.getProtectionDomain();
URL location = protectionDomain.getCodeSource().getLocation();
return location.toExternalForm();
}
}
请注意getWarLocation()方法.它使用打包的战争本身作为位置.
Please note the getWarLocation() method. It uses the packaged war itself as location.
这篇关于使用Maven来创建“可运行的WAR".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!