将战争应用程序名称与战争文件名分开

Posted

技术标签:

【中文标题】将战争应用程序名称与战争文件名分开【英文标题】:Separating war application name from war file name 【发布时间】:2011-08-18 00:56:54 【问题描述】:

目前,如果我在 tomcat 上部署一个名为 myapp.war 的 war 文件,我可以通过 http://localhost/myapp/MyServlet 访问其 url。

但是,我想要的是部署一个战争文件名中带有版本号的战争,并且仍然具有相同的 url。 例如,我想部署 myapp-1.1.0.war 并且仍然有 url 是 http://localhost/myapp/MyServlet

当然,我需要不断更新战争,版本号会不断变化,所以我不能在任何地方硬编码战争文件名。 web.xml 中是否有任何设置,无论战争文件名如何,我都可以使用它来为应用程序保留相同的 url?

【问题讨论】:

如果您只想在文件名中添加版本信息,请查看我对这个问题的回答:***.com/a/33822607/1458639 【参考方案1】:

解决方法是停止使用Tomcat的自动部署功能,该功能采用将“上下文名称”(URL的/myapp部分)设置为WAR文件名“.war”之前的部分的快捷方式。

相反,您可以自己将 WAR 内容提取到文件系统并在 TOMCAT_HOME/conf/[enginename]/[hostname]/[contextname].xml 处设置一个 XML 文件,该文件将所需的上下文路径(例如 /myapp)指向磁盘上应用程序的位置(例如 /opt/webapps/myapp-1.1.0/) .

Tomcat reference docs 很好地解释了 Tomcat 如何自动部署应用程序,以及如何配置自定义逻辑以将上下文路径映射到应用程序文件位置(除了我在上面建议的)。

【讨论】:

这是否意味着每次使用更新的文件名部署新版本的战争时,我也必须更新 .xml 文件? 我有点困惑。在这种情况下,“myapp.xml”文件的内容应该是什么才能使其指向战争的位置? 类似<Context docBase="/path/to/your/webapp/root" />。 Tomcat 将使用不带.xml 扩展名的文件名作为上下文路径。另外关于我的符号链接建议,我刚刚在文档中注意到它指出 If a symbolic link is used for docBase then changes to the symbolic link will only be effective after a Tomcat restart or by undeploying and redeploying the context. A context reload is not sufficient.【参考方案2】:

您可以为此使用 YOUR_WAR/META-INF/context.xml。这是一个示例:

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/MyServlet"/>

【讨论】:

@Matthew Gillard 据我所知,tomcat 文档说不要在 Server.xml 中放置 Context 元素。他们对 META-INF/context.xml 没有任何问题。文档甚至告诉您 context.xml 是如何工作的。来自文档:“上下文元素可能被显式定义:* 在 $CATALINA_BASE/conf/context.xml 文件中:上下文元素信息将由所有 webapps 加载。” 那我是不是看错了? “路径”部分说:“除非在 server.xml 中静态定义上下文,否则不得设置此字段的值” 我认为tomcat 在这方面的行为(和文档!)非常令人困惑。尤其重要的是:如果您决定要更改 web 应用程序的上下文根目录,您必须手动从 $CATALINA_BASE/conf 中删除一个文件(该页面介绍部分的 5 个要点中的第 4 个) @Matthew Gillard 我唯一一次在让 META-INF/context.xml 做正确的事情时遇到困难是在我尝试设置根上下文时。在那种情况下,我发现我必须删除预先捆绑的根 webapp。除了它似乎工作正常。但是您是对的,文档/行为中似乎确实存在一些不一致之处。可能值得向他们提交票证?【参考方案3】:

使用Maven 时,您可以通过执行以下操作来控制部署路径:

Tomcat 的 conf/tomcat-users.xml:

<tomcat-users>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-jmx"/>
  <role rolename="manager-status"/>
  <role rolename="admin-gui"/>
  <role rolename="admin-script"/>

  <user username="root" password="root" roles="manager-gui,manager-script,manager-jmx,manager-status,admin-gui,admin-script"/>

</tomcat-users>

~/.m2/settings.xml:

...
<server>
  <id>tomcat</id>
  <username>root</username>
  <password>root</password>
</server>
...

pom.xml:

...
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myapp</artifactId>
  <version>1.1.0</version>
  <packaging>war</packaging>
...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>tomcat-maven-plugin</artifactId>
        <configuration>
          <!-- neglect /html below Tomcat7: -->
          <url>http://server:8080/manager/html</url>
          <!-- Refer to the server settings in your ~/.m2/settings.xml -->
          <server>tomcat</server>
          <path>/myWebApp</path>
        </configuration>
      </plugin>
      ....
    </plugins>
  </build>
...

首先启动你的tomcat 然后构建并部署您的应用程序..

mvn clean install tomcat:deploy

..它可以在http://server:8080/myWebApp下访问

【讨论】:

【参考方案4】:

web.xml 中没有为此设置。我不相信有可能以跨容器的方式在 war 文件中设置它——无论如何在规范中都没有提到它——所以每个容器的做法都不同。 jboss-web.xmlsun-web.xmlcontext.xml

【讨论】:

因为我使用的是 wildfly 10,所以我在 jboss-web.xml 中对其进行了更改,它对我有用。【参考方案5】:

我更喜欢使用“##”符号来标注 tomcat 中 *.war 文件的版本。 例如:myapp.war -> URL:http://localhost:8080/myapp/MyServlet myapp##1.1.0 -> URL:http://localhost:8080/myapp/MyServlet(还是一样,因为“##”后面的所有符号都是被tomcat忽略)

【讨论】:

【参考方案6】:

我遇到了同样的问题,事实上,正如@matt 提到的,Tomcat reference docs 很好地解释了 Tomcat 如何自动部署应用程序,以及如何配置自定义逻辑以将上下文路径映射到应用程序文件位置。

就我而言,我使用了这个建议(在“路径”解释中):

即使在 server.xml 中静态定义上下文时,此属性 (/path) 必须 not 设置,除非 docBase 不位于 主机的 appBase 或 deployOnStartup 和 autoDeploy 均为 false。如果 不遵守这条规则,很可能导致双重部署。

所以在我的情况下,我将 deployOnStartupautoDeploy 都切换为 false,因此我的 WAR (egaWAR) 不会自动分解到 webapps 下的“a”目录,而是自动分解到“b”目录,因为到这些设置:

<Host name="localhost"  appBase="webapps"
            autoDeploy="false" deployOnStartup="false" 
            unpackWARs="true" deployIgnore="$ignore.context">

   <Context docBase="a" path="/b" />

</Host>

【讨论】:

【参考方案7】:

我发现关于这个主题的所有建议都有些简洁和混乱。以下方法适用于我使用默认的 tomcatee 安装。

假设我有一个名为 mywar.war 的战争文件。这包含一个到“/hello”的 servlet 映射。我想从 localhost:8080/myapp/hello 之类的 url 访问这个 servlet

此方法避免对 server.xml 进行任何不建议的更改,因为这需要重新启动 tomcat。

如果您部署到 /webapps,此方法将失败,因为它会尝试部署相同的战争两次。因此,我首先创建一个要部署到的新目录。我使用 /apps 但目录名称是任意的。

我现在将 mywar.war 复制到应用程序中。 Tomcat 忽略此操作。 我现在创建一个名为 myapp.xml 的简单部署文件。请注意,此文件的名称定义了将在其中部署战争的 URL 上下文。相信你可以使用 ROOT.xml 在 .内容如下:

如上所述,这需要复制到 /conf/Catalina/localhost 这会导致 tomcat 扩展和部署 /apps/mywar.war 并设置正确的 URL 上下文。 servlet 现在可以在 localhost://myapp/hello 上使用(或远程客户端的 :8080//myapp/hello)。

请注意,对于相对地址,docBase URL 标识 webapps 目录中战争的位置 - 因此前导 ..

【讨论】:

以上是关于将战争应用程序名称与战争文件名分开的主要内容,如果未能解决你的问题,请参考以下文章

如何在部署阶段设置战争名称到 Nexus 存储库?

Tomcat 8 Unicode 文件名战争文件部署问题

为 Spring Boot 应用程序生成战争

如何使用另一场战争中的类文件

幕府将军2全面战争 玩一会就会弹出来?Shogun2.exe 关闭应用程序···怎么回事?

在 Maven 中,如何在版本中命名战争文件与在快照构建中不同