?
企業管理及信息化解決方案;--因為專注,所以專業!
客服熱線:028-86272612
成都藍源 -> > EDP資訊 -> 詳細內容
Lanyo EDP中的錯誤處理問題
時間: 2011-10-09    來源:

錯誤處理是一個比較細節的問題。在傳統的SSH中,錯誤處理一般有以下幾種方式:1,級別的錯誤使用error-page來處理;2,中小應用可以使用Strutsglobal-exception或者局部的exception來統一處理;3,servicedao中的錯誤都簡單包裝后向上拋出,在包裝類中記錄一下root cause,用來追溯錯誤鏈,在spring中,即錯誤從HibernateException(PersistenceException)包裝為SpringDataAccessException,這幾個錯誤都是在DAO(或者某些service中)會出現的錯誤,接著這些錯誤在service1,可能會重新包裝成checked錯誤,這些錯誤會被Action強制的使用try..catch來處理,在catch中處理后,返回給用戶可以接受的提示頁面。2,service不管這些錯誤,action在執行的時候,如果遇到unchecked錯誤,使用global-exception,或者error-page處理。但是在控制的比較細節的應用中,RuntimeException也是會在Actiontry..catch,來個性化處理。另外,還可以采用配置AfterThrowing的增強來統一攔截錯誤,但基于性能,調試方便,等因素來考慮,這個個人不是很推薦使用。

錯誤處理涉及到的另一個問題是事務的回滾,在使用聲明式事務配置中,被代理的service中一旦拋出了任何的RuntimeException,即回滾事務。在傳統的SSH中,這點是沒有任何問題的,完全符合SSH中錯誤的拋出原則。

錯誤處理,jweb中使用了一個錯誤處理鏈來統一處理錯誤。終,有一個叫DefaultExceptionHandle的錯誤處理器,這個錯誤處理器會攔截任何action中的錯誤,并統一返回一個提示頁面。

這樣處理沒有問題,但是這樣處理在和事務綁定在一起的時候,問題就出現了。從上面的時序圖中,我們可以看到,事務是開在DefaultRequestProcessorprocess方法上的,但錯誤處理是包含在process方法里面的,意思就是說,默認情況下,在Action中拋出的任何錯誤,不可能被spring攔截。這是一個非常有趣的問題,就是說,無論拋出任何錯誤,事務都不會被自動回滾,除非在service上在重新開啟一個傳播級別為REQUIRESNEW的事務。為了避免這種問題的發生,我們的處理問題核心就在于,要將需要回滾事務的錯誤包裝成任何的RuntimeException,并繞過DefaultExceptionHandle處理器拋出給spring。在EDP中,添加了一個com.lanyo.ria.exception.RiaExceptionHandler,該錯誤處理器會在DefaultExceptionHandle執行之前攔截PersistenceException,并直接拋出?;蛘邔崿F自定義的RuntimeException,繼承EDP中提供了CustomerException。該錯誤也會被拋出到spring中。

上面面已經提到了一些EDP中的錯誤處理,關鍵的核心問題還是在錯誤處理鏈上,如果拋開事務的問題,EDP中的錯誤處理總體來說還是很優雅的,至少提供了一個很簡單的機制來統一處理錯誤,不管是基于JSP,Velocity的傳統頁面,還是基于AJAX的請求,都能很好的處理,但是問題還是在于一旦綁定了事務,為了使事務正?;貪L,必須要將錯誤拋出Actionspring中??赡軙斐珊笈_大量的錯誤日志產生。

下面來看看怎么解決這個問題的(該問題的解決,包括事務的解決,在EDP2.0中已經完成)。

EDP中提供了一個簡單的CustomerException錯誤基類,但是這個基類并不能記錄整個錯誤棧信息,下面就簡單來完善一下整個錯誤處理。首先,需要明確一點,就是整個應用的錯誤級別和結構??梢赃@樣來規劃錯誤:DAO層的錯誤不管,就直接是使用spring提供的DataAccessException或者TranscationManager,由于這些錯誤又都是繼承NestedRuntimeException,可以統一處理,service中的所有邏輯錯誤和checked異常都使用一個基類來處理:我們的錯誤結構可以像這樣:

其中,ServiceLogicException是代表應用邏輯錯誤,CheckedWrapperException是對應用中遇到的checkedException攔截后的封裝?;愂?/font>spring提供的NestedRuntimeException,該Exception是一個RuntimeException,并且能很好的記錄錯誤棧信息。

接下來只需要在JWEBerrorHandler中統一處理這些錯誤即可。

public boolean handle(Throwable exception, Object arg1, Method arg2, Object[] arg3) throws Exception {

       if (exception instanceof NestedRuntimeException) {

           NestedRuntimeException e = (NestedRuntimeException) exception;

           log.error(e.getMessage());

           String msg = "";

           if (e instanceof ServiceLogicException) {

               msg = e.getMessage();

           }else if (e instanceof CheckedWrapperException) {

               msg = I18n.get("checked.wrapper.exception.info");

           }else{

               msg=I18n.get("default.service.exception.info");

           }

           HttpServletResponse response = ActionContext.getContext().getResponse();

           HttpServletRequest request = ActionContext.getContext().getRequest();

           String contentType = "application/x-json;charset=UTF-8";

           if (request.getContentType().indexOf("multipart/form-data") == 0) {

               contentType = "text/html";

           }

           response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

           response.setContentType(contentType);

           PrintWriter out = response.getWriter();

           Map<String, Object> map = new HashMap<String, Object>();

           map.put("err", msg);

           out.print("function(){");

           out.print(AjaxUtil.getJSON(map));

           out.print("}()");

           out.close();

           return false;

       }

    return true;

}

在這里面,可以單獨的為每一種錯誤配置不同的處理方式,然后在mvc.xml中聲明該bean即可。當然,也可以為每一種錯誤編寫一個ExceptionHandler,然后通過在mvc.xml中為每一種錯誤分別配置exceptionHandler即可。



3.62K
上一篇:沒有了
下一篇:Lanyo EDP系統結構
  贵州快3走势图带连线