Java异常统一处理
我们知道,当我们访问某个网页出错的时候,会弹出这样的信息
显然,这样对用户是极不友好的,我们应该自定义异常页面,对用户显示用户能够理解的错误信息
自定义异常页面通常需要两步:配置过滤器和使用异常工具类。
首先,我们先做好一些准备:
config4error.properties代码:
e001=传入参数为空
e002=参数转换错误
###数据库###
e101=数据库错误:初始化失败
e102=数据库错误:连接创建失败
e103=数据库错误:Statement创建失败
e104=数据库错误:查询语法失败
e105=数据库错误:更新语法失败
e106=数据库错误:资源释放失败
e107=数据库错误:结果集处理失败
###其它无考虑/处理的异常/错误###
e0001=系统异常
e0002=系统错误
Config4Error.java代码:
package com.haigest.hx.util;
import com.leeyn.util.Configuration.Configuration;
import com.leeyn.util.path.GetRealPath;
public class Config4Error{
public static final String FILE_PATH = GetRealPath.getSrcOrClassesUrl("Classes")+"/config4error.properties";
public static final Configuration CONF = new Configuration(FILE_PATH);
}
BaseException.java代码
(该自定义类继承了RuntimeException类,并重写了的方法,提供一系列的构造方法,将properties中键与错误类型联系起来)
/***
Copyright 2006 bsmith@qq.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.haigest.hx.util;
/**
* uniform exception class, uniform exception process with id+cause.
* the final message is formated from localize message resource.
* @author bsmith.zhao
* @date 2006-05-16 11:22:12
*/
public class BaseException extends RuntimeException
{
protected String key;
protected Object[] args;
/**
*
* @param key 异常提示信息
*/
public BaseException(String key)
{
super(key);
this.key = key;
}
/**
*
* @param key 异常提示信息
* @param cause 异常对象
*/
public BaseException(String key, Throwable cause)
{
super(key, cause);
this.key = key;
}
/**
*
* @param key 异常提示信息
* @param args 在抛异常时把某些数据也抛给异常处理者
*/
public BaseException(String key, Object ... args)
{
super(key);
this.key = key;
this.args = args;
}
/**
*
* @param key 异常提示信息
* @param cause 异常对象
* @param args 在抛异常时把某些数据也抛给异常处理者
*/
public BaseException(String key, Throwable cause, Object ... args)
{
super(key, cause);
this.key = key;
this.args = args;
}
public String getKey()
{
return key;
}
public Object[] getArgs()
{
return args;
}
}
过滤器:DoExceptionInViewFilter.java
思路:先判断该异常是自定义异常还是系统产生的异常/错误,自定义的异常用doBaseException方法来处理,否则写入日志,最后都要调用senderror将参数(error,error_id)传到error页面
值得注意的是,如果是经jsp,会把异常转为jsp定义的异常,这里就接不了自己定义的BaseException,所以在这里要区分开
package com.haigest.hx.filter;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.haigest.hx.util.Config4Error;
import com.haigest.hx.util.BaseException;
/**
* Exception统一捕捉处理过滤器
* @author leeyn
*
*/
public class DoExceptionInViewFilter implements javax.servlet.Filter {
private static Logger logger = Logger.getLogger(DoExceptionInViewFilter.class.getName());
/**
*当请求到达时,会首先被此拦截器拦截,当数据经过获取并在V层显示完毕(响应完毕)后,
*又回到此Filter内部,途中如果下层有异常抛出,在这里进行拦截捕捉,并统一处理
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try{
chain.doFilter(request, response);
}
catch(BaseException e){ //---自己定义、转换的异常---
doBaseException((HttpServletResponse)response, e);
return;
}
catch(Exception e){ //---其它无考虑/处理的异常---
if(e.getCause() instanceof BaseException){
//如果是经jsp,会把异常转为jsp定义的异常,这里就接不了自己定义的BaseException,所以在这里要区分开
doBaseException((HttpServletResponse)response, (BaseException)e.getCause());
return;
}else{
String uuid = UUID.randomUUID().toString();
logger.error(Config4Error.CONF.findProperty("e0001") + uuid, e);
senderror((HttpServletResponse)response, "e0001", uuid);
return;
}
}
catch(Error e){
//---其它无考虑/处理的错误---
//error如果经过servlet一般都会被转化成异常,所以一般也就到不了这里
String uuid = UUID.randomUUID().toString();
logger.error(Config4Error.CONF.findProperty("e0002") + uuid, e);
senderror((HttpServletResponse)response, "e0002", uuid);
return;
}
}
public void doBaseException(HttpServletResponse response, BaseException e)
throws ServletException, IOException {
String e_id = null;
if(e.getArgs()!=null && e.getArgs().length != 0){
e_id = (String)e.getArgs()[0];
}
senderror(response, e.getKey(), e_id);
}
public void senderror(HttpServletResponse response, String error, String error_id)
throws ServletException, IOException {
if(error_id == null){
response.sendRedirect("/hx/hx/error.jsp?error="+error);
}else{
response.sendRedirect("/hx/hx/error.jsp?error="+error+"&error_id="+error_id);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
<%@ page language="java" import="com.haigest.hx.util.Config4Error" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%
//设置请求编码
request.setCharacterEncoding("utf-8");
//获取参数
String error = request.getParameter("error");
String error_id = request.getParameter("error_id");
String user_type = (String)session.getAttribute("user_type");
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>系统错误页面</title>
<!-- basic styles -->
<link href="css/error/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="css/error/font-awesome.min.css" />
<!--[if IE 7]>
<link rel="stylesheet" href="assets/css/font-awesome-ie7.min.css" />
<![endif]-->
<!-- page specific plugin styles -->
<!-- fonts -->
<link rel="stylesheet"
href="http://fonts.googleapis.com/css?family=Open+Sans:400,300" />
<!-- ace styles -->
<link rel="stylesheet" href="css/error/ace.min.css" />
<link rel="stylesheet" href="css/error/ace-rtl.min.css" />
<link rel="stylesheet" href="css/error/ace-skins.min.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="assets/css/ace-ie.min.css" />
<![endif]-->
<!-- inline styles related to this page -->
<!-- ace settings handler -->
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="assets/js/html5shiv.js"></script>
<script src="assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="main-container" id="main-container">
<div class="page-content">
<div class="row">
<div class="col-xs-12">
<!-- PAGE CONTENT BEGINS -->
<div class="error-container">
<div class="well">
<h1 class="grey lighter smaller">
<span class="blue bigger-125">
<%
if(error!=null && !"".equals(error)){
out.println(Config4Error.CONF.findProperty(error));
}
%>
</span>
<br/><br/>
<%
if(error_id!=null && !"".equals(error_id)){
out.println("错误id:"+error_id);
}
%>
</h1>
<hr />
<h3 class="lighter smaller">
抱歉,网站出现错误,请重试或联系网站管理员!
</h3>
<div class="space"></div>
<div>
<!--
<ul class="list-unstyled spaced inline bigger-110 margin-15">
<li> Read the faq</li>
<li> Give us more info
on how this specific error occurred!</li>
</ul>
-->
</div>
<hr />
<div class="space"></div>
<div class="center">
<%
if("admin".equals(user_type)){
%>
<a href="admin/index.jsp" class="btn btn-primary"> 返回首页 </a>
<%
}else if("tutor".equals(user_type)){
%>
<a href="teacher/index.jsp" class="btn btn-primary"> 返回首页 </a>
<%
}else if("student".equals(user_type)){
%>
<a href="student/index.jsp" class="btn btn-primary"> 返回首页 </a>
<%
}
%>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>