在web項目開發中,一個系統應該要考慮到異常情況的處理,並且應該當異常發生時應該需要記錄相應的異常日志,對於用戶而言則不能直接拋出異常,需要考慮到用戶的體驗:
以下就介紹基於spring框架的基礎上的異常處理:
1:如何將異常優雅地顯示給用戶?
如果將一連串的java報錯展示給用戶,對用戶而言是沒有意義的,並且也是危險的;
1)定義錯誤代碼:這里以一個枚舉類來封裝用戶錯誤代碼:ErrorCode:
public enum ErrorCode {
NULL_OBJ("LUO001","對象為空"),
ERROR_ADD_USER("LUO002","添加用戶失敗"),
UNKNOWN_ERROR("LUO999","系統繁忙,請稍后再試...."),
FILE_NOT_FOUND("FILE001","你要讀取的資源找不到");
private String value;
private String desc;
private ErrorCode(String value, String desc) {
this.setValue(value);
this.setDesc(desc);
}
自定義項目的業務異常類:繼承 RuntimeException
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
public BusinessException(Object Obj) {
super(Obj.toString());
}
}
自定義異常處理類:實現 HandlerExceptionResolver 這個類是用來處理異常發生時做出的邏輯處理,和spring框架集成:
public class MySimpleMappingExceptionResolver implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object object, Exception exception) {
// 判斷是否ajax請求
if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request
.getHeader("X-Requested-With") != null && request.getHeader(
"X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
// 如果不是ajax,JSP格式返回
// 為安全起見,只有業務異常我們對前端可見,否則否則統一歸為系統異常
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", false);
if (exception instanceof BusinessException) {
map.put("errorMsg", exception.getMessage());
} else {
map.put("errorMsg", "系統異常!");
}
//這里需要手動將異常打印出來,由於沒有配置log,實際生產環境應該打印到log里面
exception.printStackTrace();
//對於非ajax請求,我們都統一跳轉到error.jsp頁面
return new ModelAndView("/error", map);
} else {
// 如果是ajax請求,JSON格式返回
try {
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = response.getWriter();
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", false);
// 為安全起見,只有業務異常我們對前端可見,否則統一歸為系統異常
if (exception instanceof BusinessException) {
map.put("errorMsg", exception.getMessage());
} else {
map.put("errorMsg", "系統異常!");
}
JSONObject json =new JSONObject();
// writer.write(json.fromObject(map));
// writer.flush();
// writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
在spring容器中注冊這個異常處理類
<!-- 定義異常處理器 -->
<bean id="exceptionResolver" class="bz.beppe.exception.MySimpleMappingExceptionResolver"></bean>
這樣,在項目拋出自定義的業務異常時,都或進入這個異常處理類進行處理,然后展示給用戶;
當然項目還有一些unchecked Exception,由於代碼不要求強制處理,當這些異常發生時,用戶就會面對 404 500等服務器內部的頁面,目前大多數服務器也都支持在Web.xml中通過<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)節點配置特定異常情況的顯示頁面。修改web.xml文件,增加以下內容:
<!-- 出錯頁面定義 -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
這樣一個健全的異常處理系統就好了;
以下是controller層對這些業務異常和系統異常 以及 unchecked exception 的測試代碼:
public class ExceptionController {
@RequestMapping(value = "/controller", method = RequestMethod.GET)
public void controller(Model model,String id) {
throw new BusinessException(ErrorCode.NULL_OBJ.toString());
}
@RequestMapping(value = "/service", method = RequestMethod.GET)
public void service(Model model,String id) {
// String str=null;
// str.substring(10);
// System.out.println("代碼運行了");
File file=new File("c:/a.txt");
try {
FileReader reader = new FileReader(file);
int i = reader.read();
System.out.println(i);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("文件找不到");
throw new BusinessException(ErrorCode.FILE_NOT_FOUND);
// e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("讀取文件出錯");
e.printStackTrace();
}
}
}

