当前位置: 首页 > 面试题库 >

可执行的战争文件,可在没有Maven的情况下启动码头

仰成天
2023-03-14
问题内容

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

我找到了一个页面,描述了如何制作所需的内容:

但是,遵循该建议以及我认为我应该如何制作可执行jar(war)是行不通的。

我有一个Ant任务,它会创建一个带有清单的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.

这里似乎有两个错误:一个似乎找不到JAR文件,而另一个则Start找不到类。

为了解决第一个问题,我将Jetty JAR文件放在WAR文件的底部,然后再次尝试-同样的错误。我也尝试将清单属性添加WEB- INF/lib/<specific-JAR-files>Class-Path清单中。那也不起作用。

是否有人对我在做对/错以及如何启动并运行此可执行WAR文件有任何见解?


问题答案:

您所遇到的问题中的链接提供了您所需的大多数内容。但是,除此之外,还需要做一些事情。

打包后,Jetty需要启动的所有类文件都必须位于war文件的根目录下。<war>在归档之前,我们可以利用Ant为我们做到这一点。战争的清单文件还将需要一个Main- Class属性来执行服务器。

这是一个循序渐进的步骤:

创建您的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();
    }
}

要查看您可以在此处配置的所有内容,请查看Jetty
API文档

与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


 类似资料:
  • 我已经将Java项目从Eclipse导出为“可运行的JAR文件”,并带有“将所需库提取到生成的JAR中”。当我尝试通过双击启动它时,什么也没有发生,只是文件闪烁。当我尝试像那样从终端运行它时,它工作得很好。

  • 我正在试验OSGi条件权限机制。更具体地说,我试图使用org.osgi.service.condpermadmin.BundleSignerCondition来限制哪些包可以启动。我所拥有的文档指出,为了使用该权限,我必须使用org.osgi.framework.trust.repositories框架配置属性指定到JKS密钥库的路径。但是,同一文档提到该属性中提到的JKS不能有密码。所以问题是:

  • 我在我的Android应用程序中使用JSch,我想创建一个SSH连接,而无需最初提供用户名和密码。如果我提供用户名和密码,我可以连接,但如果我不提供用户名,我会从JSch得到一个用户名没有给出“错误”。 这是我试图在不提供用户名和密码的情况下连接的。 我唯一的选择是将JSch的源代码更改为允许,编译成jar,然后导入它吗?

  • 问题内容: 背景: 我正在尝试使用弹性堆栈 (Elastic,Logstash和Kibana) ,但是我没有钱可支付。我不介意使用封闭源代码的部件,只要它们是免费的即可。在这方面,我试图了解弹性许可的工作原理。 我们打开X-Pack似乎建议在Elastic 6.3之后包含X-Pack代码 (尽管具有不同的许可证) 。我也了解X-Pack的某些部分是免费的,而其他部分则不是免费的。这有点令人困惑。

  • 问题内容: 我正在学习使用Selenium(v2.20)来领先一些 即将使用它创建浏览器测试的程序员。我想在 陷阱到达之前发现它们,而我却跌入了一个陷阱。 当我创建ChromeDriver时,它始终会弹出“ Google Chrome EULA”并 显示两个按钮:“接受并运行”和“取消”。因为我希望这是一个 自动化测试,所以让用户单击按钮是不可能的。 我查看了Chromium CommandSwi

  • 问题内容: 我想知道在不提示输入密码的情况下执行数据库mysqldump的命令。 原因:我想运行一个cron作业,该作业每天执行一次mysqldump数据库的转储。因此,出现提示时,我将无法插入密码。 我该如何解决? 问题答案: 由于您正在使用Ubuntu,因此您所要做的只是在主目录中添加一个文件,这将禁用mysqldump密码提示。这是通过创建文件来完成的(权限需要为600)。 将此添加到.my