import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的异常类,用于处理异常信息的转换,以及向前台传递异常信息。<br>
* 有两种用法,一是捕获异常后,将原始异常转换为自定义异常,转换过程中生成容易理解的出错信息,<br>
* 二是主动抛出异常。<br>
*
* 用法一例子:<br>
* try
* {
* stmt.execute("insert into tbl (a) values (3)");
* } catch (Exception e) {
* throw new GeeznException(AliasManager.MODULE_ALIAS, GEZLoggerManager.LOGLEVEL_ERROR, "插入表错误", e, "{a:1}");
* }
*
* 用法二例子:<br>
* ResultSet rs = stmt.executeQuery("select count(*) cnt from tbl where id=" + id);
* rs.next();
* if(rs.getInt("cnt") > 0)
* throw new GeeznException(AliasManager.MODULE_ALIAS, GEZLoggerManager.LOGLEVEL_WARNING, "数据重复", null, "{id:}" + id)
*/
@SuppressWarnings("serial")
public class GeeznException extends Exception {
private String message;
private String errorMessageJson;
/**
*
* @param module 所属模块,用于给记录日志模块提供参数
* @param level 日志级别,用于给记录日志模块提供参数,如果为null,则不记录日志
* @param tipMessage 上下文相关辅助提示信息,用于给用户提供完整的出错信息
* @param e 系统抛出的原始异常,本构造方法将根据原始异常的类型和异常所能提供的具体的出错信息,<br>
* 生成更易于普通用户理解的错误信息,如果此参数为null,则意味着代码主动抛出的异常,message将仅由tipMessage构成
* @param jsonMessage2FrontEnd 用于传递到前台的更精细定位错误的信息,例如出错的是哪个字段,哪条记录,具体格式由应用场景决定
*/
public GeeznException(String module, String level, String tipMessage, Exception e, String jsonMessage2FrontEnd) {
//记录日志
if(level != null){
GEZLoggerManager.log(module, level, e.getMessage());
}
//根据原始异常信息,生成易于理解的出错信息,加上tipMessage,存储于message属性中
if(e == null){
this.message = tipMessage;
} else{
String easyMessage = createCommonMessageByExcepiton(e);
this.message = easyMessage + tipMessage;
}
//将message和jsonMessage2FrontEnd打包存储于errorMessageJson属性中
this.errorMessageJson = this.message + jsonMessage2FrontEnd;
}
/**
* 获取出错信息
*/
public String getMessage() {
return message;
}
/**
* 与前端AJAX接口的servlet,调用此方法获得打包于json字符串中的异常信息,传递到前台
* @return 获取返回前台的json字符串,其中包含用于向终端用户显示的errormessage,也包含用于程序定位错误的jsonMessage2FrontEnd
*/
public String getErrorMessageJson() {
return errorMessageJson;
}
/**
* 根据原始异常信息,生成易于理解的出错信息
* @param e
* @return
*/
private String createCommonMessageByExcepiton(Exception e){
String message = null;
if(e instanceof SQLSyntaxErrorException){
message = processSQLSyntaxErrorException(e);
} else if(e instanceof SQLException){
message = processSQLException(e);
} else if (e instanceof NullPointerException) {
message = processNullPointerException(e);
} else if(e instanceof ClassNotFoundException){
message = processClassNotFoundException(e);
} else if(e instanceof FileNotFoundException){
message = processFileNotFoundException(e);
} else if(e instanceof ClassCastException){
message = processClassCastException(e);
} else if(e instanceof IOException){
message = processIOException(e);
}else if(e instanceof ArrayIndexOutOfBoundsException){
message = "数组越界,当前的index为:" + e.getLocalizedMessage();
} else if(e instanceof IndexOutOfBoundsException){
}else if(e instanceof NumberFormatException){
message = processNumberFormatException(e);
}else{
message = e.getLocalizedMessage();
}
return message;
}
/**
* 处理IndexOutOfBoundsException
*/
private static String processIndexOutOfBoundsException(Exception e){
String message = e.getLocalizedMessage();
if(message.startsWith("Index:")){
message = "index越界,当前的index为:"
+ message.substring(message.indexOf(":")+1,message.indexOf(","))
+ "容器的容量是:" + message.substring(message.lastIndexOf(":") + 1);
}
return message;
}
/**
* 处理SQLSyntaxErrorException
* @param e
* @return
*/
private String processSQLSyntaxErrorException(Exception e){
String errorMessage = e.getMessage();
if(errorMessage.startsWith("You have an error")){
errorMessage += "sql有语法错误,在"+errorMessage.substring(errorMessage.indexOf("near") + 4);
} else{
errorMessage = e.getLocalizedMessage();
}
return errorMessage;
}
/**
* 处理SQLException
* @param e
* @return
*/
private String processSQLException(Exception e){
String errorMessage = e.getMessage();
if(errorMessage.startsWith("You have an error")){
errorMessage += "sql有语法错误,在"+errorMessage.substring(errorMessage.indexOf("near") + 4);
} else{
errorMessage = e.getLocalizedMessage();
if(errorMessage.contains("\n")){
errorMessage = errorMessage.replaceAll("\n", " ");
}
}
return errorMessage;
}
/**
* 处理 NullPointException
* @param e
*/
private String processNullPointerException(Exception e){
String message = "空指针异常:" + e.getMessage() + "\n";
StackTraceElement[] arr = e.getStackTrace();
//缩短stackTrace
for(int i = 0; i < (arr.length < 4 ? arr.length : 3); i++){
message += arr[i].getClassName() + "(" + arr[i].getMethodName() + ":" + arr[i].getLineNumber() + ")\n";
}
return message;
}
/**
* 处理FileNotFoundException
* @param e
*/
private String processFileNotFoundException(Exception e){
return e.getLocalizedMessage() + "文件找不到!" ;
}
/**
* 处理ClassCastException
*/
private String processClassCastException(Exception e){
String message = e.getLocalizedMessage();
String arr[] = message.split("cannot be cast to");
message = arr[0] + "不能强转为:" + arr[1];
StackTraceElement st = e.getStackTrace()[0];
message += "\n " + st.getClassName() + "(" + st.getMethodName() + ":" + st.getLineNumber() + ")";
return message;
}
/**
* 处理ClassNotFoundException
* @param e
*/
private String processClassNotFoundException(Exception e){
return "缺少" + e.getLocalizedMessage() +"类,请查找是否存在相关jar或者class文件!";
}
/**
* 处理NumberFormatException
* @param args
*/
private String processNumberFormatException(Exception e){
String message = e.getLocalizedMessage();
if(message.startsWith("For input string:")){
message = "数字格式异常,输入的字符串为:" + message.replace("For input string:", "");
}
return message;
}
/**
* 处理IOException
* @param e
*/
private static String processIOException(Exception e) {
String message = e.getLocalizedMessage();
if(message.startsWith("Read error")){
message = "文件读取失败!输入流可能已经关闭!";
} else if(message.startsWith("Write error")){
message = "文件写入失败!输出流可能已经关闭!";
}
return message;
}
}