使用的框架是SpringMVC
我们使用
org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
类名:CustomCatchMappingExceptionResolver
后面会附上源码.
1,需要在WEB-INF/spring-servlet.xml 中配置
2,看下效果
程序出现代码异常时,收到的邮件
邮件内容如下:
CustomCatchMappingExceptionResolver代码如下:
package oa.web.controller.intercept;
import com.common.bean.BaseResponseDto;
import com.common.bean.email.SendEmailInfo;
import com.common.util.CommonEmailUtil;
import com.common.util.RedisCacheUtil;
import com.common.util.SystemHWUtil;
import com.common.util.WebServletUtil;
import com.time.util.TimeHWUtil;
import oa.util.SpringMVCUtil;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* Created by 黄威 on 29/11/2016.<br >
* 全局捕获异常
*/
public class CustomCatchMappingExceptionResolver extends org.springframework.web.servlet.handler.SimpleMappingExceptionResolver {
public static org.slf4j.Logger HttpClientErrorLogger = LoggerFactory.getLogger("exception_log");
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
Map<String, Exception> model = new HashMap<>();
model.put("ex", ex);
// ModelAndView modelAndView = new ModelAndView("../../exception/errorPage",model);
StringBuffer errorCause = new StringBuffer();
// 打印请求地址
String path = request.getRequestURI();//"/demo_channel_terminal/news/list"
String pathMsg = "request path:" + path;
logger.error(pathMsg);
HttpClientErrorLogger.error(pathMsg);
System.out.println(pathMsg);
errorCause.append(pathMsg).append(SystemHWUtil.CRLF);
//打印请求参数
String paramStr = null;
try {
paramStr = WebServletUtil.getRequestQueryStr(request, SystemHWUtil.CHARSET_UTF);
if (null == paramStr) {
paramStr = "(无)";
} else {
paramStr = paramStr.trim();
}
String paramMsg = "参数:" + paramStr;
logger.error(paramMsg);
HttpClientErrorLogger.error(paramMsg);
System.out.println(paramMsg);
errorCause.append(paramMsg).append(SystemHWUtil.CRLF)
.append("request Method:").append(request.getMethod())
.append(SystemHWUtil.CRLF);
} catch (IOException e) {
e.printStackTrace();
}
//打印请求头 request header
Map headerMap = WebServletUtil.getHeaderMap(request, new String[]{"cookie"});
String headerStr = headerMap.toString();
String headerMsg = "请求头:" + headerStr;
logger.error(headerMsg);
HttpClientErrorLogger.error(headerMsg);
System.out.println(headerMsg);
if (headerMap.size() > 0) {
errorCause.append(headerMsg).append(SystemHWUtil.CRLF);
}
/*错误日志输出到控制台*/
logger.error(TimeHWUtil.getCurrentDateTime());
logger.error(ex.getMessage(), ex);
HttpClientErrorLogger.error(TimeHWUtil.getCurrentDateTime());
HttpClientErrorLogger.error(ex.getMessage(), ex);
new Thread(new Runnable() {
@Override
public void run() {
try {
sendEmailWhenNullPointerException(ex,/*path,*/errorCause.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
if (SpringMVCUtil.isResponseJson(handler)) {
PrintWriter out = null;
response.setContentType(SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF);
try {
out = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage(), e);
HttpClientErrorLogger.error(e.getMessage(), e);
}
String errorMesg = ex.getMessage();
if (null == errorMesg || errorMesg.trim().length() == 0) {
errorMesg = ex.toString();
}
StackTraceElement stackTraceElement = ex.getStackTrace()[0];
out.print(new BaseResponseDto("5000", errorMesg + ":" + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName()).toJson());
out.flush();
out.close();//不能缺少,否则就会一直请求,前端报错:net::ERR_INCOMPLETE_CHUNKED_ENCODING
}
return null;
}
private static void sendEmailWhenNullPointerException(Exception ex
// ,String path
, String paramStr) {
boolean isLocalIp = WebServletUtil.isLocalIp(SpringMVCUtil.getRequest());
if (isLocalIp) {
return;
}
String errorMessage = ex.getMessage();
if (null == errorMessage) {
errorMessage = ex.toString();
}
if (errorMessage.contains("java.lang.NullPointerException")
|| errorMessage.contains("java.sql.SQLException")) {
StringBuffer emailDesc = new StringBuffer();
emailDesc.append(errorMessage).append(SystemHWUtil.CRLF);
StackTraceElement[] stackTraceElements = ex.getStackTrace();
StackTraceElement stackTrace = stackTraceElements[0];
emailDesc/*.append("请求地址:").append(path)*/
.append(SystemHWUtil.CRLF)
.append("请求详细信息:").append(SystemHWUtil.CRLF)
.append(paramStr)
.append(SystemHWUtil.CRLF)
.append(SystemHWUtil.CRLF);
appendException(emailDesc, stackTraceElements, 4);
// recordExceptionTrace(emailDesc, stackTraceElements[1]);
emailDesc.append(SystemHWUtil.CRLF)
.append(SystemHWUtil.CRLF)
.append(SystemHWUtil.CRLF)
.append(TimeHWUtil.getCurrentDateTime())
.append(SystemHWUtil.CRLF);
// System.out.println(emailDesc.toString());
SendEmailInfo sendEmailInfo = RedisCacheUtil.getSendEmailInfo();
// if (null == sendEmailInfo || ValueWidget.isNullOrEmpty(sendEmailInfo.getUsername())) {
CommonEmailUtil.sendEmailRandom("服务器出bug了-house", emailDesc.toString(), RedisCacheUtil.getEmail());
/*} else {
CommonEmailUtil.sendEmail(sendEmailInfo, "服务器出bug了-house", emailDesc.toString(), RedisCacheUtil.getEmail());
}*/
}
}
private static void appendException(StringBuffer emailDesc, StackTraceElement[] stackTraceElements, int sum) {
if (sum > stackTraceElements.length) {
sum = stackTraceElements.length;
}
for (int i = 0; i < sum; i++) {
recordExceptionTrace(emailDesc, stackTraceElements[i]);
}
}
/***
* 根据异常栈,格式化异常信息
* @param emailDesc
* @param stackTrace
*/
private static void recordExceptionTrace(StringBuffer emailDesc, StackTraceElement stackTrace) {
if (SystemHWUtil.NEGATIVE_ONE <= stackTrace.getLineNumber()) {
return;
}
emailDesc.append(SystemHWUtil.CRLF);
if (null != stackTrace.getFileName()) {
emailDesc.append(stackTrace.getFileName()).append("-");
}
emailDesc.append(stackTrace.getClassName()).append(".")
.append(stackTrace.getMethodName()).append("():")
.append(stackTrace.getLineNumber())
.append(SystemHWUtil.BLANK);
}
}
发邮件依赖的pom:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.5</version>
</dependency>
其他依赖:
https://github.com/liuyu520/io0007
https://gitee.com/kunlunsoft/common_ssh
注意:
1,这里并不是捕获所有的异常,而是捕获代码级别的异常,比如空指针异常.
像没有登录或者没有权限的异常不在此列;
2,可以把发邮件的逻辑替换为发短信