思路:
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()" onclick="document.getElementById('detail').style.display='block'; ">点击查看详细信息</a> <div id="detail" style="display:none"> <hr><br/> 详细信息:<br/>${errorMsgDetail!} </div> </font> </body> </html>