如何在应用程序上下文级别处理 404

How to handle 404 in application context level

我在 tomcat 7 网络服务器中部署了 2 applications/projects。上下文路径不同,如 "project1"、"project2"。当我使用这些上下文路径点击 URLs 时,相应的应用程序加载并正常工作。

有效的 URL 是:

http://localhost:8080/project1

http://localhost:8080/project2

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

我想向最终用户显示包含正确消息的正确页面。我怎样才能在网络服务器级别做到这一点?

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

摘录:

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

理论上,您应该可以修改默认 tomcat 网络应用程序的 web.xml,但根据 this,这不适用于 Tomcat 7.

您的另一个选择是扩展标准 ErrorReportValve。我从现有的 ErrorReportValve 代码中非常自由地 "borrowed":

    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>