j2EE 分层模式中的异常架构设计

来源:互联网 发布:网络号和主机号 编辑:程序博客网 时间:2024/05/02 08:17

Java引入了异常处理给程序调试带来的方便,但给客户带来的烦恼,任何客户都不希望看到一大串堆栈信息。这篇文章就是纪念一个教训。

   事件缘由:老板在给客户做演示的时候,出现长串堆栈信息。尽管之前我们做过很多测试,都没有出现问题。因为数据库数据不完整性带来的灾难被老板碰到了。这让我们感到很尴尬。决定彻底解决这类隐患。

   设计背景:

          我们系统采用3层结构。即 DAO,SERVICE, ACTION(strut2)。DAO利用spring对hibernate的封装实现。 service 是核心业务逻辑的实现,同时也是事务处理层。action扮演controllor层的作用。

   设计过程:

           1dao层的异常分可预测,和不可预测。

           在可预测的异常我们可以抛给service层处理,有些包含了很有用的信息。如入户名重复的异常。

           不可预测的异常我们可以自己封装起来,然后重现包装自定义的异常抛给servic处理。

               2servic层的异常也和dao一样。分两中。处理雷同。     

           3,在action中我们利用struts2的设计理念。action中可以处理任何来自底层的异常。这样如果是有用的信息,我们可以抛给用户,以便提示用户。如果是更友好点,我们可以包装起来抛出。抛给struts2,让她来处理。只要在struts.xml中配置相关处理即可。这样可以统一处理异常。也可以分类处理异常。重用性比较高。也灵活。减少手动编程。

           4,框架本身的异常。struts2等框架自身有时候也会有异常抛出。当然这种情况很少。只要有可能,我们就要预防。以防患于未然。做法也很简单 在web.xml 中配置  <error-page> 标签的信息。这样有服务容器来处理并定向到指定的页面。

     编码实现:

         1,自定义异常(主要用于包装异常)

           

public class AMPException extends RuntimeException {

 

private static final long serialVersionUID = -3888868544018808942L;

 

public String errorCode;

 

public AMPException(String message) {

super(message);

}

 

public String getErrorCode() {

return errorCode;

}

 

public void setErrorCode(String errorCode) {

this.errorCode = errorCode;

}

}

 

public class ActionException extends AMPException {

private static final long serialVersionUID = 7637165153080210218L;

 

public ActionException(String message) {

super(message);

}

 

}

 

public class ServiceException extends AMPException {

 

private static final long serialVersionUID = 4872117656104037525L;

 

public ServiceException(String message) {

super(message);

}

}

 

public class DaoException extends AMPException{

 

private static final long serialVersionUID = 8037899278793078796L;

 

public DaoException(String message) {

super(message);

}

 

}

2接口 定义如下(service为例,dao层类似)

 

  

public interface SigProfileManager {

 

/**

* Save a profile's information

* @param sigProfile  the SigProfile object

* @return the SigProfile object

* @throws Exception

* */

SigProfile saveSigProfile(SigProfile sigProfile) throws Exception;

}

实现类

public class SigProfileManagerImpl implements SigProfileManager {

 

public SigProfile saveSigProfile(SigProfile sigProfile) throws Exception {

try {

   // 逻辑处理代码

} catch (Exception e) {

throw new ServiceException(errorMsg + e.getMessage());

}

}

 

 

}

3action 层。可以处理也可不处理。这要看业务逻辑本身,和信息本身是否需要重包装。更重的是的

controllor层自身是否有异常处理机制。一般比较成熟的框架都会有异常的处理机制的。

  public class SigProfileAction extends BaseAction {

public String list() throws Exception{

          try {

   //service tie call

} catch (Exception e) {

throw new ActionException(errorMsg + e.getMessage());

}

 

return SUCCESS;

}

             }

           我用的是struts2,处理配置起来很方便在struts2.xml 中有两个地方可以配置

             1,批量处理。可以处理每个action的异常

                    

         <global-exception-mappings>

<exception-mapping exception="org.springframework.dao.DataAccessException" result="dataAccessFailure"/>

<exception-mapping exception="java.lang.Exception" result="dataAccessFailure"/>

</global-exception-mappings>

 

  2,单个处理

         

         <action name="users" class="userAction" method="list">

     <interceptor-ref name="adminCheck"/>

     <result name="success">/WEB-INF/pages/admin/userList.jsp</result>

     <result name="failure">/WEB-INF/pages/admin/error.jsp</result>

     <exception-mapping exception="java.lang.Exception" result="failure"/>

 

</action>

 

4,容器处理

     

          <error-page>

<error-code>500</error-code>

<location>/error.jsp</location>

</error-page>

原创粉丝点击