可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I wrote a servlet to handle the exceptions occurring in my web app and mapped them in 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:
@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?
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.
回答1:
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
<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.
回答2:
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
<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
<error-page>
<exception-type>java.net.SocketException</exception-type>
<location>/error.jsp</location>
</error-page>
回答3:
Use Jboss Custom Logging Handler to solve this problem.
If you don't want to log any SocketException
exception stack trace then just skip it while loggin into a file.
Steps to follow:
- A custom handler must inherit 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/main
together 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.
Please let me know if there is any issue.
回答4:
You probably will have to override fillInStackTrade method
public static class CustomException extends Exception {
@Override
public Throwable fillInStackTrace() {
return null;
}
}
回答5:
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.
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.
回答6:
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
回答7:
You can use the Logger
. For this you need log4j
library and all the desired behavior and exceptions are written to log file. For this you need to give the log file path