思路:
1. 针对特定http状态码,返回到指定错误提示页面,例如:403、404、500……
2. 配置全局异常拦截器,针对捕获的异常进行分类,并增加用户简洁错误信息和开发、维护 详细错误信息,并写入日志,最后 跳转到错误页面
3. 对于某些特定异常部分不需要跳转到错误页面的,则自行进行捕获,不往上层抛出即可
web.xml
<!-- 出错页面定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/html/error_page.html</location> </error-page> <error-page> <error-code>500</error-code> <location>/html/error_page_500.html</location> </error-page> <error-page> <error-code>404</error-code> <location>/html/error_page_404.html</location> </error-page> <error-page> <error-code>403</error-code> <location>/html/error_page_403.html</location> </error-page>
struts.xml
<interceptors> <!-- 全局异常拦截器 --> <interceptor name="exceptionInterceptor" class="com.hzp.exception.ExceptionInterceptor" /> <interceptor-stack name="bussdefault"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="exceptionInterceptor" /> </interceptor-stack> </interceptors> <global-results> <result name="forward">${callbackurl}</result> <result name="freemarker" type="freemarker">${callbackurl}</result> <result name="success" type="json"></result> <result name="error" type="freemarker">/html/error_page.html</result> </global-results> <!-- 未到找Action指向页面 --> <default-action-ref name="errorPage" /> <action name="errorPage"> <result type="redirect">/html/error_page_404.html</result> </action>
ExceptionInterceptor.java
package com.hzp.exception;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.xwork.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.dao.DataAccessException;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* 全局异常拦截器
* 对捕捉到的异常进行分类,保存错误提示信息,并跳转到错误页面
* @author hzp
*
*/
public class ExceptionInterceptor extends AbstractInterceptor {
private static final String ERROR="error";
//日志
protected static Log logger = LogFactory.getLog(ExceptionInterceptor.class);
@Override
public String intercept(ActionInvocation actionInvocation) {
logger.debug("########### 全局异常拦截器start #########");
String result = "";
String errorMsg=""; //给用户查看的简洁错误信息
StringBuffer errorMsgDetail=null; //给开发或维护人员查看的详细错误信息
StackTraceElement[] ste=null;
HttpServletRequest request=ServletActionContext.getRequest();
try {
result = actionInvocation.invoke();
} catch (DataAccessException ex) {
errorMsg="数据库操作失败!";
ste=ex.getStackTrace();
result=ERROR;
} catch (NullPointerException ex) {
errorMsg="空指针,调用了未经初始化或者是不存在的对象!";
ste=ex.getStackTrace();
result=ERROR;
} catch (IOException ex) {
errorMsg="IO读写异常!";
ste=ex.getStackTrace();
result=ERROR;
} catch (ClassNotFoundException ex) {
errorMsg="指定的类不存在!";
ste=ex.getStackTrace();
result=ERROR;
} catch (ArithmeticException ex) {
errorMsg="数学运算异常!";
ste=ex.getStackTrace();
result=ERROR;
} catch (ArrayIndexOutOfBoundsException ex) {
errorMsg="数组下标越界!";
ste=ex.getStackTrace();
result=ERROR;
} catch (IllegalArgumentException ex) {
errorMsg="调用方法的参数错误!";
ste=ex.getStackTrace();
result=ERROR;
} catch (ClassCastException ex) {
errorMsg="类型强制转换错误!";
ste=ex.getStackTrace();
result=ERROR;
} catch (SecurityException ex) {
errorMsg="违背安全原则异常!";
ste=ex.getStackTrace();
result=ERROR;
} catch (SQLException ex) {
errorMsg="操作数据库异常!";
ste=ex.getStackTrace();
result=ERROR;
} catch (NoSuchMethodError ex) {
errorMsg="调用了未定义的方法!";
ste=ex.getStackTrace();
result=ERROR;
} catch (InternalError ex) {
errorMsg="Java虚拟机发生了内部错误!";
ste=ex.getStackTrace();
result=ERROR;
} catch (Exception ex) {
errorMsg="程序内部错误,操作失败!";
ste=ex.getStackTrace();
result=ERROR;
}
//捕获到异常时,保存用户查看的简洁异常信息
if(StringUtils.isNotEmpty(errorMsg)){
logger.error(errorMsg);//输出错误信息到日志
request.setAttribute("errorMsg",errorMsg);
}
//捕获到异常时,保存开发或维护人员查看的详细异常信息
if(null!=ste && ste.length>0){
errorMsgDetail=new StringBuffer();
for(StackTraceElement s:ste){
errorMsgDetail.append(s.toString()).append("<br/>");
}
logger.error(errorMsgDetail);//输出错误信息到日志
request.setAttribute("errorMsgDetail",errorMsgDetail.toString());
}
logger.debug("########### 全局异常拦截器end #########");
return result;
}
}
error_page.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD LEVEL1//EN">
<html>
<head>
<title>错误页面</title>
</head>
<body>
<font color="red">
服务器遇到错误<hr><br/>
信息提示:<br/>${errorMsg!}<br/><br/>
<a href="javascript:void()" οnclick="document.getElementById('detail').style.display='block'; ">点击查看详细信息</a>
<div id="detail" style="display:none">
<hr><br/>
详细信息:<br/>${errorMsgDetail!}
</div>
</font>
</body>
</html>