【问题标题】:Angular deep linking - Apache TomcatAngular 深度链接 - Apache Tomcat
【发布时间】:2018-10-07 09:00:33
【问题描述】:

我正在构建一个 Angular 应用程序。它以/hris 的基础a href 托管。所以我访问应用程序的基本 URL 将是domain.com/hris。此外,我有 3 个不同的应用程序,其中一个称为 term。因此,当我点击 term 链接时,它会转到 domain.com/hris/term。

当用户直接尝试访问链接domain.com/hris/term时,它会返回404并显示一条消息:HTTP Status 404 - /hris/term

我不希望发生 404。如何完成这项工作?

到目前为止我做了什么:

我尝试在index.html 所在的文件夹中创建一个.htaccess 文件。(我使用ng build --base-href=/hris/ 构建了Angular 应用程序)。我将dist 文件夹部署到服务器的一个名为hris 的目录中。

.htaccess 文件中,我使用了以下变体,但无济于事。

1

    <IfModule mod_rewrite.c>
          Options Indexes FollowSymLinks
          RewriteEngine On
          RewriteBase /hris/
          RewriteRule ^index\.html$ - [L]
          RewriteCond %{REQUEST_FILENAME} !-f
          RewriteCond %{REQUEST_FILENAME} !-d
          RewriteRule . index.html [L]
    </IfModule>

2

    <IfModule mod_rewrite.c>
       Options Indexes FollowSymLinks
       RewriteEngine On
       RewriteRule ^index\.html$ - [L]
       RewriteCond %{REQUEST_FILENAME} !-f
       RewriteCond %{REQUEST_FILENAME} !-d
       RewriteRule . /index.html [L]
    </IfModule>

3

    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteCond %{REQUEST_FILENAME} -s [OR]
        RewriteCond %{REQUEST_FILENAME} -l [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^.*$ - [NC,L]
        RewriteRule ^(.*) index.html [NC,L]
   </IfModule>

我正在使用 Angular 5。请告诉我我的方法是否正确,或者我必须做些什么才能让这一切顺利进行。

版本:Apache Tomcat 7- 版本 7.0.64

【问题讨论】:

    标签: angular apache tomcat deep-linking


    【解决方案1】:

    “.htaccess”文件在 Tomcat 上不起作用。将重写配置放入文件WEB-INF/rewrite.conf,可能是这样的:

    RewriteCond %{SERVLET_PATH} !-f
    RewriteRule ^/(.*)$ /index.html [L]
    

    接下来,您需要添加一个名为 META-INF/context.xml 的文件以启用重写,即:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context reloadable="true" tldValidation="false" xmlValidation="false">
    
      <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
    
    </Context>
    

    同时从您的 Angular 应用程序中删除 HashLocationStrategy

    更新

    为什么要重写

    • 由于 Angular 应用程序是 SPAs,唯一真正被寻址的页面是 index.html
    • 因此,任何像 href 这样的链接都会离开该页面并退出应用程序。
    • Angular 使用其Router 重定向到应用程序内部的虚拟路径,而无需离开index.html
    • Web 服务器会猜测这些路径是真实文件,并且由于它们不存在,因此以 404 HTTP 状态响应(如果是 Tomcat,则其 DefaultServlet 提供静态内容)。
    • 要解决这个问题,可以使用url rewriting

    如何启用重写

    • 首先您需要启用RewriteValve,这是一个网络过滤器,默认情况下是禁用的。为此,您可以将 context.xml 添加到您的 Angular 构建文件中,如上面的示例(便携版),或将其添加到 server.xml(服务器端版)。请参见上面的代码 sn-ps。
    • 之后添加一个rewrite.conf 文件来设置rewriting conditions。请参见上面的代码 sn-ps。
    • 在上面的示例中,第一行告诉 Tomcat 在当前 servlet 路径中查找“不是真实/现有文件的文件”!-f。 servlet 路径部​​分是必需的,如果您的应用未部署为 ROOT(即www.xyz.com/**myApp**)并将进行相应设置。
    • 第二行将每个“虚拟路径”从 Angular 路由器映射到 index.html。

    更新 2

    【讨论】:

    • 您能否提供一些链接来详细说明您的答案?我认为也可以为 tomcat 配置一个 .htaccess 。非常感谢!
    • 非常感谢!我应该在 Angular 项目的 src 文件夹中创建 WEB-INF/rewrite.conf 然后 META-INF/context.xml?
    • 是的,但您需要确保它们在构建后都位于dist 文件夹中。因此,您需要将它们添加到assets 部分中的angular.json。毕竟运行ng build 并检查dist 文件夹。
    • 我尝试了几次,但不知何故我无法让它工作。运行ng build 后,META-INFWEB-INF 文件夹确实在dist 文件夹中。另一方面,如果我在服务器文件中进行这些更改(server.xml 或创建rewrite.conf 文件),那么它可以工作。
    【解决方案2】:

    用于解决在 apache tomcat 服务器 (8, 9) 上部署 Angular 应用程序(使用 PathLocationStrategy 路由)时的深层链接问题 -

    1. 在 server.xml 中配置 RewriteValve
    2. 在rewrite.config中写入重写规则

    server.xml -

    ...
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    
            <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
    
    ...
          </Host>
    ...
    

    rewrite.config - (注意 - /hello/ 是 Angular 应用在​​ tomcat 上的上下文路径)

    RewriteCond %{REQUEST_PATH} !-f
    RewriteRule ^/hello/(.*) /hello/index.html
    

    我已经在我的文章中记录了这一点 - Fixing deep linking issue – Deploying angular application on Tomcat server

    【讨论】:

      【解决方案3】:

      我在尝试解决类似问题时偶然发现了这个问题。 stefan 的回答对我有用,对文件名稍作修改。根据https://tomcat.apache.org/tomcat-9.0-doc/rewrite.html,重写配置文件应该命名为rewrite.config(不是rewrite.conf)。

      我没有足够的代表来评论他的回答,所以为了完整起见,我将在这里重申:

      把重写配置放到一个文件WEB-INF/rewrite.config中,可能是这样的:

      RewriteCond %{SERVLET_PATH} !-f
      RewriteRule ^/(.*)$ /index.html [L]
      

      接下来,您需要添加一个名为 META-INF/context.xml 的文件以启用重写,即:

      <?xml version="1.0" encoding="UTF-8"?>
      <Context reloadable="true" tldValidation="false" xmlValidation="false">
        <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
      </Context>
      

      同时从你的 Angular 应用中移除 HashLocationStrategy。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-23
        • 2014-09-04
        • 2018-11-30
        相关资源
        最近更新 更多