異常處理(一)業務異常


在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();
            }
        }
       
       
}
復制代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM