Как остановить печать стека исключений на консоли?
Я написал сервлет, чтобы обрабатывать исключения, происходящие в моем веб-приложении, и отображал их в web.xml
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/exceptionHandler</location>
</error-page>
Вот что я сделал в методе сервлетов Exception Handle 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);
}
}.
Проблема:
Указанный выше подход не работает, и трассировка стека печатается на консоль. Это происходит, когда пользователь что-то запрашивает, а затем закрывает свой браузер.
Вопрос:
Как остановить печать stacktrace на консоли JBoss всякий раз, когда возникает SocketException
?
Причина для этого:
Я хочу, чтобы не видеть весь журнал SocketException
в конце дня, потому что я не могу ничего сделать с этой информацией.
Ответы
Ответ 1
Вот что я сделал так, чтобы работать, как работа.
Добавлен один фильтр и захват всего запроса и ответа. Заблокируйте исключение и проверьте тип.
/**
* 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>
Я не отмечаю это как ответ, так как я не уверен, что это стандартный способ или нет. Просто работайте.
Ответ 2
Вместо добавления java.lang.Exception
в ваш web.xml, почему бы вам просто не попробовать добавить исключение сокета в web.xml, как показано ниже
<error-page>
<exception-type>java.net.SocketException</exception-type>
<location>/exceptionHandler</location>
</error-page>
и просто ничего не делайте в своем сервлете
Или вместо этого добавьте пустой файл jsp, например,
<error-page>
<exception-type>java.net.SocketException</exception-type>
<location>/error.jsp</location>
</error-page>
Ответ 3
Используйте Jboss Custom Handging Handler, чтобы решить эту проблему.
Если вы не хотите регистрировать трассировку стека исключений 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;
}
}
-
Затем файл упаковывается в банку и помещается в каталог модулей.
то есть. 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>
-
Добавьте дополнительный обработчик в корневой журнал, если необходимо, например FILE, CONSOLE и т.д.
- Теперь все журналы регистрируются в вашем пользовательском файле журнала через этот пользовательский обработчик, где мы пропустили
SocketException
- Мы можем сделать этот класс более универсальными передающими свойствами из standalone.xml, например, для передачи пути файла журнала.
Пожалуйста, дайте мне знать, если есть какие-либо проблемы.
Ответ 4
Вероятно, вам придется переопределить метод fillInStackTrade
public static class CustomException extends Exception {
@Override
public Throwable fillInStackTrace() {
return null;
}
}
Ответ 5
Как я понимаю, исключения регистрируются на консоли, когда они не пойманы до достижения контейнера. Как таковой использование фильтра для обнаружения необработанных исключений имеет смысл.
У Struts2 также есть исключение "перехватчик" в качестве последнего перехватчика, по умолчанию. См. defaultStack. Нам нужно переопределить этот перехватчик, если нам нужна специальная обработка исключений.
Единственное, что я сделал бы дополнительно, - это регистрировать исключения (по крайней мере, файл errors-ignore.txt), а не полностью пропускать их.
Ответ 6
Другая фанковая идея: вы можете создать обработчик исключений
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)
Может быть полезно при тестировании/экспериментировании или если вы полностью контролируете потоки в своем собственном коде
Ответ 7
Вы можете использовать Logger
. Для этого вам нужна библиотека log4j
и все желаемое поведение, а исключения записываются в файл журнала. Для этого вам нужно указать путь к файлу журнала