简体   繁体   English

如何在Console上停止打印异常堆栈跟踪?

[英]How to stop printing exception stack trace on Console?

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 service method: 这是我在异常处理servlet service方法中所做的:

@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 SocketException occurs? 每当发生SocketException时,如何停止将printtrace打印到JBoss控制台?

Reason for doing this: 这样做的原因:

I want to avoid seeing all of the log's SocketException s at the end of th day because I can't do anything with that information. 我想避免在第一天结束时看到所有日志的SocketException ,因为我无法对该信息做任何事情。

Here is what I done so war as work around. 这就是我在战争中所做的工作。

Added one filter and hijack all the request and response.Catch the exception and check the type. 添加了一个过滤器并劫持了所有请求和响应。捕获异常并检查类型。

/**
 * Hijacks 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. 我不是把它标记为答案,因为我不确定这是否是标准方法。只是一个解决方法。

Instead of adding java.lang.Exception in your web.xml why won't you just try to add socket exception in web.xml itself like below 不要在web.xml中添加java.lang.Exception ,为什么不尝试在web.xml本身中添加套接字异常,如下所示

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

and just do nothing in your servlet Or instead add a empty jsp file like 并且只是在你的servlet中什么都不做或者改为添加一个空的jsp文件

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

Use Jboss Custom Logging Handler to solve this problem. 使用Jboss Custom Logging Handler解决此问题。

If you don't want to log any SocketException exception 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. 然后将该文件打包到jar中并放在modules目录中。

    ie Jboss-7.1.1/modules/com/custom/jboss/loggers/main together with a module.xml file. Jboss-7.1.1/modules/com/custom/jboss/loggers/main loggers Jboss-7.1.1/modules/com/custom/jboss/loggers/main以及module.xml文件。 The contents of the module.xml should look like this. 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> 
  • Then modify the standalone.xml to support logging to the custom logger 然后修改standalone.xml以支持记录到自定义记录器

     <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. 如果需要,在root-logger中添加更多处理程序,如FILE,CONSOLE等。

  • Now all the logs will be logged in your custom log file via this custom handler where we have skipped SocketException 现在,所有日志都将通过此自定义处理程序记录在您的自定义日志文件中,我们已跳过SocketException
  • We can make this class more generic passing properties from standalone.xml such as used to pass log file path. 我们可以使这个类更通用,从standalone.xml传递属性,例如用于传递日志文件路径。

Please let me know if there is any issue. 如果有任何问题,请告诉我。

You probably will have to override fillInStackTrade method 您可能必须覆盖fillInStackTrade方法

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

} }

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. 默认情况下,Struts2还有一个异常“拦截器”作为它的最后一个拦截器。 See defaultStack . 请参阅defaultStack We need do override this interceptor if we need custom exception handling. 如果我们需要自定义异常处理,我们需要覆盖此拦截器。

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文件),而不是完全跳过它们。

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 ) 简单,没有链中的另一个过滤器的开销,但它与线程混淆,可能会破坏Java EE环境中的某些东西)
Might be useful in testing/experimenting or if you fully control threads in your own code 可能在测试/实验中有用,或者如果您在自己的代码中完全控制线程

You can use the Logger . 您可以使用Logger For this you need log4j library and all the desired behavior and exceptions are written to log file. 为此,您需要log4j库,并将所有所需的行为和异常写入日志文件。 For this you need to give the log file path 为此,您需要提供日志文件路径

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM