Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HttpServlet引发的ServletException被记录为';严重';由Tomcat执行,尽管以推荐的方式处理 问题描述_Java_Tomcat_Servlets_Exception Handling_Servletexception - Fatal编程技术网

Java HttpServlet引发的ServletException被记录为';严重';由Tomcat执行,尽管以推荐的方式处理 问题描述

Java HttpServlet引发的ServletException被记录为';严重';由Tomcat执行,尽管以推荐的方式处理 问题描述,java,tomcat,servlets,exception-handling,servletexception,Java,Tomcat,Servlets,Exception Handling,Servletexception,当我的HttpServlet抛出ServletException时,Tomcat正在记录一条严重的消息,包括stacktrace,尽管它被正确地重新定向到web.xml中的另一个HttpServlet Tomcat使用stacktrace记录以下消息: 21-Mar-2015 15:24:57.521 SEVERE [http-nio-8080-exec-28] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.servic

当我的HttpServlet抛出ServletException时,Tomcat正在记录一条严重的消息,包括stacktrace,尽管它被正确地重新定向到web.xml中的另一个HttpServlet

Tomcat使用stacktrace记录以下消息:

21-Mar-2015 15:24:57.521 SEVERE [http-nio-8080-exec-28] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [MyHttpServlet] in context with path [/HttpServletExceptionHandler] threw exception [CustomException] with root cause CustomException
at MyHttpServlet.doGet(MyHttpServlet.java:20)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
我做了什么? 首先,MyHttpServlet在其doGet()方法中抛出一个封装CustomException(Exception的子类)的ServletException:

然后,抛出的CustomException被重新定向到MyServletExceptionHandler(映射到位置“/MyServletExceptionHandler”)。此重新定向在web.xml中以以下方式定义:

<error-page>
    <exception-type>CustomException</exception-type>
    <location>/MyServletExceptionHandler</location>
</error-page>
这会导致预期的“MyServletExceptionHandler捕获Throwable:CustomException”打印,因此这确实有效,但Tomcat也会记录上面提到的严重消息,包括stacktrace。这会打乱我的日志记录

我为什么要这样? 根据JavaBeat的观点,上述方法是处理servlet中异常处理的正确方法。问题29状态(扰流板警报:粗体是正确答案):

如果出现从java.lang.exception扩展而来的业务异常,以下哪种方式是向客户端发送错误页面的合理方式

  • 捕获异常并使用RequestDispatcher将请求转发到错误页面
  • 不要捕获异常并在web.xml中定义“异常到错误页面”映射
  • 捕获异常,将其包装到ServletException中,并在web.xml中定义“业务异常到错误页面”映射
  • 捕获异常,将其包装到ServletException中,并在web.xml中定义“ServletException到错误页面”的映射
  • 如果不执行任何操作,servlet容器将自动发送一个默认错误页面
  • 第三个答案(标记为正确)明确指出,我重新引导异常的方法是一个明智的解决方案

    进一步讨论材料 我在(2012年2月10日,Tom Holloway在CodeRanch.com上)上找到了以下引文

    实际上,ServletException在Web应用程序中没有上升的空间,因此将其显示在主控制台上并不是很不合理,因为它表明应用程序本身没有处理问题

    事实上,Javadocs是这样描述ServletException构造函数的:

    “使用指定的消息构造新的servlet异常。该消息可以写入服务器日志和/或显示给用户。”

    请注意,它明确表示服务器日志

    服务器可以通过多种方式参与其中。首先,您应该能够在web.xml中定义一个通用异常处理程序,以允许应用程序处理该异常,该处理程序不仅可以登录到应用程序日志,还可以确定应采取的恢复操作(如果有的话)(这是更通用的服务器代码无法做到的)。其次,您可以定义一个自定义错误页面,在这种情况下,Tomcat将捕获ServletException并分派该页面。但是,请注意,操作词是page。与登录屏幕一样,这些页面直接从Tomcat调用,因此无法通过servlet路由。换句话说,使用HTML或JSP,而不是Struts或JSF

    不过,底线是抛出ServletException是应用程序设计糟糕的标志。这意味着某人太懒或太匆忙而无法正确处理问题。相比之下,错误记录的位置是次要的

    这句话让我质疑Java Beat的OCEJWCD模拟考试(如上所述)和我自己的解决方案是否是一个好的实践。你认为业务异常应该由另一个Servlet处理吗?如果是,你认为Servlet容器(Tomcat)应该是否应该记录这些异常的stacktrace?如果不是,那么最佳做法是什么

    最后发言
    • 抛出RuntimeExceptions而不是ServletExceptions会导致相同的严重日志
    • 该问题的工作示例通过提供

    您的基本问题似乎是希望集中处理错误,但不使用导致Tomcat将错误记录为严重的机制

    既然您从您的问题中控制了所有的servlet,那么定义一个抽象的基本servlet来定义所有的错误处理逻辑,然后让其余的servlet从这个类派生出来,这不是更有意义吗

    因此,您有一个抽象的基本servlet:

    public abstract class MyServletBase extends HttpServlet {
    
      @Override
      public void doGet(HttpServletRequest req, HttpServletResponse resp) {
        try {
          doGetInternal(req, resp);
        } catch (RuntimeException e) {
          handleError(e, req, resp);
        }
      }
    
      protected void handleError(RuntimeException e, HttpServletRequest req, HttpServletResponse resp) {
        // Error handling logic goes here
      }
    
      protected void doGetInternal(HttpServletRequest req, HttpServletResponse resp);
    
    }
    
    然后是实际的servlet:

    public class MyServlet extends MyServletBase {
    
      @Override
      protected void doGetInternal(HttpServletRequest req, HttpServlet resp) {
        // Actual servlet logic here
      }
    }
    
    这是我脑海中的一个粗略的草图,没有提及Javadoc,因此可能没有完美的方法签名,但希望您能理解


    它还有一个优点,即如果您需要向派生servlet添加额外的错误处理逻辑,并且不想出于任何原因更改基本servlet,那么您只需重写
    handleError()
    方法,这在使用Tomcat的异常处理机制时不是很容易做到的。

    @Klikodid你解决了你的问题吗?不,谢谢你的帮助,虽然问题是在你的最后一次编辑中出现的,
    edit:BUMP
    这是不合适的。@Kliko-当我从整体上看问题时,它有点大很难理解。它漫无目的地讲,没有真正的结构。我试着阅读它,但失去了所有的兴趣。我几乎看不出问题陈述。你也没有提供导致异常的代码(相反,它漫无目的地讲其他事情,比如关于事情应该如何工作的文档和博客帖子)你可能会考虑最后一次编辑,并把它与需要帮助的必要信息联系起来。现在它已经结束了,我倾向于同意——不清楚你在问什么,需要最少的例子。
    public abstract class MyServletBase extends HttpServlet {
    
      @Override
      public void doGet(HttpServletRequest req, HttpServletResponse resp) {
        try {
          doGetInternal(req, resp);
        } catch (RuntimeException e) {
          handleError(e, req, resp);
        }
      }
    
      protected void handleError(RuntimeException e, HttpServletRequest req, HttpServletResponse resp) {
        // Error handling logic goes here
      }
    
      protected void doGetInternal(HttpServletRequest req, HttpServletResponse resp);
    
    }
    
    public class MyServlet extends MyServletBase {
    
      @Override
      protected void doGetInternal(HttpServletRequest req, HttpServlet resp) {
        // Actual servlet logic here
      }
    }