【问题标题】:How to handle 404 in application context level如何在应用程序上下文级别处理 404
【发布时间】:2015-02-23 08:48:17
【问题描述】:

我在 tomcat 7 Web 服务器中部署了 2 个应用程序/项目。上下文路径不同,例如“project1”、“project2”。当我使用这些上下文路径点击 URL 时,相应的应用程序会加载并正常工作。

有效的网址是:

http://localhost:8080/project1

http://localhost:8080/project2

现在,当我使用正确的主机名和不正确的上下文路径(如 /project3)点击任何错误的 URL 时,它会给我错误消息 404 未找到并向用户显示奇怪的屏幕。

我想向最终用户显示带有正确消息的正确页面。如何在 Web 服务器级别做到这一点?

【问题讨论】:

  • @Magnilex 感谢您编辑我的问题。你也能帮帮我吗?
  • 对不起,我没有时间。顺便问一下,您真的在使用 JEE 堆栈吗?为此,通常使用像 JBoss 这样的应用程序服务器。如果不是,那么您使用错误的标签标记了问题。
  • @Magnilex 我正在使用 Web 服务器 (Apache Tomcat 7.0),而不是任何应用程序服务器。
  • 您运行的是哪个版本的 TC-7?

标签: tomcat jakarta-ee


【解决方案1】:

您可以调整 Tomcat 的 conf/web.xml 文件以显示 404 错误的默认页面以外的其他页面 - 有关示例,请参阅 here

摘录:

<error-page>  
       <error-code>404</error-code>  
       <location>/NotFound.jsp</location>  
</error-page>

【讨论】:

  • 感谢您的宝贵回答。但是使用这种方法,我可以使用项目资源处理 404。但我正在寻找服务器级别 404。请再次阅读我的问题。
  • @SunilSharma:我确实再次阅读了你的问题,但我想说我的回答仍然有效 - 你的 tomcat 试图提供错误的 URL 并且没有上下文,所以它产生了一个丑陋的404网页本身。所以要单独处理这个,你必须调整tomcat的配置(我提到的web.xml)并将它指向一个更好的错误页面。这与您部署的项目无关,它在服务器级别。
  • 你是对的,它工作正常!!现在该喝啤酒了!!
【解决方案2】:

理论上,你应该可以修改默认tomcat web应用程序的web.xml,但是根据this,这对Tomcat 7不起作用。

您的另一个选择是扩展标准ErrorReportValve。我从现有的ErrorReportValve 代码中“借用”了很多:

    public class Custom404Valve extends ErrorReportValve{

        public void invoke(Request request, Response response) throws IOException, ServletException {

           if(request.getStatusCode() != 404){
               super.invoke();
               return;
           }
           // Perform the request
           getNext().invoke(request, response);

           if (response.isCommitted()) {
               if (response.setErrorReported()) {
                   try {
                    response.flushBuffer();
                  } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                  }
               response.getCoyoteResponse().action(ActionCode.CLOSE_NOW, null);
                }
          return;
          }

         response.setSuspended(false);
         //this is where your code really matters
         //everything prior are just precautions I lifted
         //from the stock valve. 
         try {
           response.setContentType("text/html");
           response.setCharacterEncoding("utf-8");
           String theErrorPage = loadErrorPage();
           Writer writer = response.getReporter();
           writer.write(theErrorPage);
           response.finishResponse();
         } catch (Throwable tt) {
           ExceptionUtils.handleThrowable(tt);
         }

         if (request.isAsyncStarted()) {
             request.getAsyncContext().complete();
         }
      }

      protected String loadErrorPage() {
          BufferedReader reader = null;
          StringBuilder errorMessage = new StringBuilder();
              try{
                 File file = new File("YourErrorPage.html");
                 reader = new BufferedReader(new FileReader(file));

                    while (reader.ready()) {
                       errorMessage.append(reader.readLine());
                    }
              }catch (IOException e){
                  e.printStackTrace();
              }finally{
                 try{
                    reader.close();
                 }catch (IOException e) {
                    e.printStackTrace();
                 }
              } 
          return errorMessage.toString();     
        }
    }

您现在需要做的就是配置自定义阀门:

    <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">

        <Valve className="com.foo.bar.Custom404Valve"/>
    </Host>

【讨论】:

  • 你在Tomcat 7中试过了吗?我没有,但根据 BalusC 对您的链接的回答中提交的错误,它已被修复。
  • 谢谢@Geziefer;我没有看到链接帖子的最后一条评论(指出它已在新版本的 TC7 中修复),而且我从 JIRA 并不清楚它是否已修复。我们会让 OP 确认。阀门相当简单。我只添加了库存ErrorReportValve 中的一些东西,因为它采取了一些我认为必要的预防措施。 OP 真正需要做的就是最后几行的内容
猜你喜欢
  • 1970-01-01
  • 2010-10-17
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多