【问题标题】:change behavior of tomcat when page not found (404)找不到页面时更改 tomcat 的行为 (404)
【发布时间】:2019-03-22 20:45:31
【问题描述】:

任何人都可以提供有关如何配置 Tomcat 以完全避免 404 的建议,而是在未找到页面时(特别是在应触发 404 的情况下)返回 index.html 内容和 200 作为状态? 让我告诉你我为什么要这样做:

  1. 我们有 Angular 应用程序“www.app.exmpl/app”,当用户点击“www.app.exmpl/app”应用程序时,应用程序正确显示并返回 200。返回的 index.html 包含 Angular 应用程序代码。

  2. 当用户点击“www.app.exmpl/app/some_unexisted_url_in_file_system_path”时,tomcat 会尝试查找可以提供此 url 的端点或 html 文件,并返回 404,在 web.xml 中我们有以下配置:

    <error-page>
     <error-code>404</error-code>
     <location>/index.html</location>
    </error-page>
    

这会导致用户收到 404 响应,但仍然会加载 Web 应用程序 正确,因为 index.html 在其中和加载页面后有角度应用程序 将 url 重写为正确的 URL,例如:“www.app.exmpl/app”。

  1. 当用户点击“www.app.exmpl/app/url_handled_by_angular_app”时,仍然没有找到“url_handled_by_angular_app”下的页面OR端点,因此tomcat将代码设置为404并呈现index.html,返回给用户,并且在用户的电脑上,此响应呈现为 Angular 应用程序而无需重写 url,因为 Angular 应用程序知道如何处理此“url_handled_by_angular_app”路由。

所以总而言之,我只需要摆脱 404 并将它们全部替换为 200 并在这种情况下呈现 index.html 内容。这种情况的最佳做法是什么?

【问题讨论】:

    标签: angular tomcat http-status-code-404


    【解决方案1】:

    如果没有服务器上的重定向规则,应用程序深层链接将无法工作。所有深层链接都必须由服务器重定向到应用程序index.html

    设置 tomcat 以重定向任何深层链接 -

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

    1.在 server.xml 中配置 RewriteValve

    编辑 ~/conf/server.xml 以在 Host 部分中添加以下 Valve,如下所示 -

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

    2。在rewrite.config中写重写规则

    创建目录结构 - ~/conf/Catalina/localhost/ 并在其中创建 rewrite.config 文件,内容如下。注意 - 在这里,我考虑将 /app 作为问题中提到的应用程序的上下文路径。

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

    设置完成后重启 tomcat 服务器,您可以点击应用程序的深层链接,该链接将路由到 Angular 应用程序内的正确组件。

    您可以参考this post了解更多详情。

    【讨论】:

    • 哇。谢谢你的详细解释。 :) 这是一种艰难的方式...不要认为应该使用它来解决我遇到的问题...
    • 对于您的第 3 点 - 当用户点击 URL www.app.exmpl/app/url_handled_by_angular_app 时,您希望服务器返回 index.html。这是由重写规则设置的,如果 URL 包含上下文路径为/app/* 的任何内容,则返回 index.html。从那里角度路由将接管并返回该路径的相应组件。
    【解决方案2】:

    当错误页面不是静态页面,而是 JSP 页面(或 Servlet)时,它可以更改响应状态 (response.setStatus(200)) 并提供静态文件(转发给它或包含它)。

    虽然我猜在像您这样的用例中,使用302(客户端重定向)响应会更合适,例如response.sendRedirect(application.getContextPath() + "/index.html")

    【讨论】:

    • 将所有“虚拟” url 重定向到 index.html 将使 Angular 应用程序无法正常工作,因为它将无法处理由 Angular 提供的路由,因为在重定向期间路由将被切断。 Abhishek 为这个线程的主题提供了正确的解决方案,其他解决方案是将应用程序的 url 模式映射到呈现 index.html 而不重写 url,这将使路由处理成为可能。但我个人更喜欢 HashLocationStrategy,因为它让我避免了不必要的服务器端映射配置。
    【解决方案3】:

    您能否提供有关您的Routing Strategy 的更多详细信息。 好吧,我想你必须使用这个{useHash: true}

    这可能是一种情况,如果您没有使用过{useHash: true},并且在重新加载它时搜索 URL 路径中的特定文件, 你可以在这里找到更多https://thinkster.io/tutorials/angular-2-routing-navigation

    【讨论】:

    • 如何修复tomcat的404问题?
    • @Pavel 请分享您的路由文件内容。
    • 其实你是对的,使用 HashLocationStrategy 是最佳实践。谢谢。
    • PathLocationStrategy 优于 HashLocationStrategy。参考angular docs
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 2020-01-25
    • 2013-06-28
    • 2016-08-01
    • 2016-08-01
    • 2015-10-22
    • 2014-03-20
    相关资源
    最近更新 更多