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

时间:2013-09-17 12:05:47

标签: java tomcat servlets web.xml socketexception

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

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

以下是我在异常处理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);
         }
    }.

问题:

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

问题:

如果发生SocketException,如何停止将printtrace打印到JBoss控制台?

这样做的原因:

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

7 个答案:

答案 0 :(得分:7)

这就是我在战争中所做的工作。

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

/**
 * 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.    
        }
    }


}

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>  

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

答案 1 :(得分:7)

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

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

并且在servlet中什么也不做 而是添加一个空的jsp文件,如

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

答案 2 :(得分:3)

使用 Jboss自定义日志记录处理程序来解决此问题。

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

要遵循的步骤:

  • 自定义处理程序必须继承java.util.logging.Handler

以下是代码:

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;
    }

}
  • 然后将文件打包到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以支持记录到自定义记录器

    <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传递属性,例如用于传递日志文件路径。

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

答案 3 :(得分:2)

您可能必须覆盖fillInStackTrade方法

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

}

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:1)

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

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

并在

注册
Thread.setDefaultUncaughtExceptionHandler(new SocketExceptionSwallower());

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

简单,没有链中的另一个过滤器的开销,但是它与线程混淆并且可能在Java EE环境中破坏某些东西)
可能在测试/实验中有用,或者如果您完全控制自己代码中的线程

答案 6 :(得分:1)

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