Java 如何停止在控制台上打印异常堆栈跟踪?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18849415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:36:20  来源:igfitidea点击:

How to stop printing exception stack trace on Console?

javatomcatservletsweb.xmlsocketexception

提问by Suresh Atta

I wrote a servlet to handle the exceptions occurring in my web app and mapped them in web.xml

我写了一个 servlet 来处理我的 web 应用程序中发生的异常并将它们映射到 web.xml

    <error-page>
      <exception-type>java.lang.Exception</exception-type>
      <location>/exceptionHandler</location>
    </error-page>

Here is what I have done in the Exception Handling servlet servicemethod:

这是我在异常处理 servletservice方法中所做的:

@Override
    protected void service(HttpServletRequest req, HttpServletResponse arg1)
            throws ServletException, IOException {
         Object attribute = req.getAttribute("javax.servlet.error.exception");
         if(attribute instanceof  SocketException){
            // don't do anything 
         }else{
          super.service(req, arg1);
         }
    }.

Problem:

问题:

The above approach is not working and the stack trace is printing to the console. This occurs when the user requests something and then closes their browser.

上述方法不起作用,堆栈跟踪正在打印到控制台。当用户请求某些内容然后关闭他们的浏览器时,就会发生这种情况。

Question:

题:

How do I stop printing the stacktrace to the JBoss console whenever a SocketExceptionoccurs?

SocketException发生这种情况时,如何停止将堆栈跟踪打印到 JBoss 控制台?

Reason for doing this:

这样做的原因:

I want to avoid seeing all of the log's SocketExceptions at the end of th day because I can't do anything with that information.

我想避免SocketException在一天结束时看到所有日志,因为我无法对这些信息做任何事情。

回答by MansoorShaikh

You probably will have to override fillInStackTrade method

您可能必须覆盖 fillInStackTrade 方法

public static class CustomException extends Exception {
@Override
public Throwable fillInStackTrace() {
    return null;
}       

}

}

回答by Suresh Atta

Here is what I done so war as work around.

这是我所做的战争作为解决方法。

Added one filter and hiHyman all the request and response.Catch the exception and check the type.

添加了一个过滤器,劫持了所有的请求和响应。捕获异常并检查类型。

/**
 * HiHymans all the http request and response here.
 * Catch the SocketException and do not print 
 * If other exceptions print to console
 * date : 9-18-2013
 * 
 * @author Suresh Atta
 *
 */
public class ExceptionHandler implements Filter {

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        try{
        arg2.doFilter(arg0, arg1);
        }catch(SocketException e ){
           // Please don't print this to log.    
        }
    }


}

And in web.xml,filter mapping

并在web.xml,过滤器映射

<filter>
        <filter-name>ExceptionHandler</filter-name>
        <filter-class>com.nextenders.server.ExceptionHandler</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ExceptionHandler</filter-name>
        <dispatcher>  REQUEST   </dispatcher>
        <url-pattern> /*</url-pattern>
    </filter-mapping>  

I'm not marking this as answer,since I'm not sure this is a standard way or not.Just a work around.

我没有将此标记为答案,因为我不确定这是否是标准方式。只是一种解决方法。

回答by Ravindra HV

As I understand it, exceptions are logged to the console when it is not caught before reaching the container. As such using a filter to catch unhandled exceptions makes sense.

据我了解,在到达容器之前没有捕获异常时,异常会记录到控制台。因此,使用过滤器来捕获未处理的异常是有意义的。

Struts2 also has an exception 'interceptor' as its last interceptor, by default. See defaultStack. We need do override this interceptor if we need custom exception handling.

默认情况下,Struts2 也有一个异常“拦截器”作为它的最后一个拦截器。请参阅defaultStack。如果我们需要自定义异常处理,我们需要覆盖这个拦截器。

The only thing I would do additionally would be to log the exceptions (atleast to an errors-ignore.txt file) rather than completely skipping them.

我唯一要做的就是记录异常(至少记录到一个 errors-ignore.txt 文件)而不是完全跳过它们。

回答by Prakash

Instead of adding java.lang.Exceptionin your web.xml why won't you just try to add socket exception in web.xml itself like below

而不是java.lang.Exception在你的 web.xml中添加你为什么不尝试在 web.xml 本身中添加套接字异常,如下所示

<error-page>
  <exception-type>java.net.SocketException</exception-type>
  <location>/exceptionHandler</location>
</error-page>

and just do nothing in your servlet Orinstead add a empty jsp file like

并在您的 servlet 中什么都不做 或者添加一个空的 jsp 文件,例如

<error-page>
  <exception-type>java.net.SocketException</exception-type>
  <location>/error.jsp</location>
</error-page>

回答by Braj

Use Jboss Custom Logging Handlerto solve this problem.

使用Jboss Custom Logging Handler来解决这个问题。

If you don't want to log any SocketExceptionexception stack trace then just skip it while loggin into a file.

如果您不想记录任何SocketException异常堆栈跟踪,则只需在登录文件时跳过它。

Steps to follow:

要遵循的步骤:

  • A custom handler must inherit java.util.logging.Handler
  • 自定义处理程序必须继承 java.util.logging.Handler

Here is the code:

这是代码:

package com.custom.jboss.logging;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.logging.ErrorManager;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class SocketExceptionCustomLoggingHandler extends Handler {

    private String logFile;
    public BufferedWriter out = null;

    public SocketExceptionCustomLoggingHandler() {
        super();
        logFile = "";
    }

    @Override
    public void publish(LogRecord record) {
        if (!initialize()) {
            return;
        }
        if (isLoggable(record)) {
            process(record);
        }
    }

    private synchronized boolean initialize() {
        if (out == null && logFile != null && !logFile.equals("")) {
            FileWriter fstream = null;
            try {
                fstream = new FileWriter(logFile, true);
                out = new BufferedWriter(fstream);
            } catch (IOException e) {
                reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE);
            }
            logToFile("Log file initialized. Logging to: " + logFile);
        }
        return true;
    }

    private void process(LogRecord logRecord) {

        String log = getFormatter().format(logRecord);
        if (log.indexOf("java.net.SocketException") == -1) {
            logToFile(log);
        }
    }

    private void logToFile(String text) {
        try {
            if (out != null) {
                out.write((new Date()).toString() + "\t" + text + "\n");
                out.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.WRITE_FAILURE);
        }

    }

    @Override
    public void flush() {
        try {
            if (out != null) {
                out.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.FLUSH_FAILURE);
        }
    }

    @Override
    public void close() {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                reportError(e.getMessage(), e, ErrorManager.CLOSE_FAILURE);
            }

        }
    }

    public void setLogFile(String logFile) {
        this.logFile = logFile;
    }

}
  • The file is then packaged into a jar and placed in the modules directory.

    i.e. Jboss-7.1.1/modules/com/custom/jboss/loggers/maintogether with a module.xml file. The contents of the module.xml should look like this.

    <?xml version="1.0" encoding="UTF-8"?>   
    <module xmlns="urn:jboss:module:1.0" name="com.custom.jboss.loggers">  
         <resources>      
               <resource-root path="SocketExceptionHandler.jar"/>  
              <!-- Insert resources here -->   
         </resources>    
         <dependencies>      
              <module name="org.jboss.logging"/>  
              <module name="javax.api"/>   
         </dependencies>  
    </module>  
    
  • Then modify the standalone.xml to support logging to the custom logger

    <subsystem xmlns="urn:jboss:domain:logging:1.1">
        ...
        <custom-handler name="SocketExceptionAppender" class="com.custom.jboss.logging.SocketExceptionCustomLoggingHandler" module="com.custom.jboss.loggers">
            <level name="DEBUG"/>
            <formatter>
                <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
            </formatter>
            <properties>
                <property name="logFile" value="d:\temp\logfile.txt"/>
            </properties>
        </custom-handler>
        ...
        <root-logger>
            <level name="INFO"/>
            <handlers>
                <handler name="SocketExceptionAppender"/>                    
            </handlers>
        </root-logger>
    </subsystem>
    
  • Add more handler in root-logger if needed such as FILE, CONSOLE etc.

  • Now all the logs will be logged in your custom log file via this custom handler where we have skipped SocketException
  • We can make this class more generic passing properties from standalone.xml such as used to pass log file path.
  • 然后将该文件打包到一个 jar 中并放置在 modules 目录中。

    Jboss-7.1.1/modules/com/custom/jboss/loggers/main与module.xml 文件一起。module.xml 的内容应如下所示。

    <?xml version="1.0" encoding="UTF-8"?>   
    <module xmlns="urn:jboss:module:1.0" name="com.custom.jboss.loggers">  
         <resources>      
               <resource-root path="SocketExceptionHandler.jar"/>  
              <!-- Insert resources here -->   
         </resources>    
         <dependencies>      
              <module name="org.jboss.logging"/>  
              <module name="javax.api"/>   
         </dependencies>  
    </module>  
    
  • 然后修改standalone.xml支持日志到自定义logger

    <subsystem xmlns="urn:jboss:domain:logging:1.1">
        ...
        <custom-handler name="SocketExceptionAppender" class="com.custom.jboss.logging.SocketExceptionCustomLoggingHandler" module="com.custom.jboss.loggers">
            <level name="DEBUG"/>
            <formatter>
                <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
            </formatter>
            <properties>
                <property name="logFile" value="d:\temp\logfile.txt"/>
            </properties>
        </custom-handler>
        ...
        <root-logger>
            <level name="INFO"/>
            <handlers>
                <handler name="SocketExceptionAppender"/>                    
            </handlers>
        </root-logger>
    </subsystem>
    
  • 如果需要,在 root-logger 中添加更多处理程序,例如 FILE、CONSOLE 等。

  • 现在,所有日志都将通过我们跳过的自定义处理程序记录在您的自定义日志文件中 SocketException
  • 我们可以让这个类更通用的从 standalone.xml 传递属性,例如用于传递日志文件路径。

Please let me know if there is any issue.

如果有任何问题,请告诉我。

回答by Yuri

Another funky idea: you could create exception handler

另一个时髦的想法:你可以创建异常处理程序

class SocketExceptionSwallower implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            if (e instanceof SocketException) {
                // swallow
            } else {
                e.printStackTrace();
            }
        }
    }

and registered with

并注册

Thread.setDefaultUncaughtExceptionHandler(new SocketExceptionSwallower());

or

或者

Thread.currentThread().setUncaughtExceptionHandler(new SocketExceptionSwallower());

Simple, no overhead of another filter in chain, but it messes with threads and will probably break something in Java EE environment )
Might be useful in testing/experimenting or if you fully control threads in your own code

简单,没有链中另一个过滤器的开销,但它会干扰线程并且可能会破坏 Java EE 环境中的某些内容)
可能在测试/实验或您完全控制自己代码中的线程时有用

回答by UmeshA

You can use the Logger. For this you need log4jlibrary and all the desired behavior and exceptions are written to log file. For this you need to give the log file path

您可以使用Logger. 为此,您需要log4j库并将所有所需的行为和异常写入日志文件。为此,您需要提供日志文件路径