<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    樂在其中

    以JEE為主攻,以Flex為點綴,以Eclipse RCP為樂趣
    請訪問http://www.inframesh.org

    首頁 新隨筆 聯系 管理
      43 Posts :: 0 Stories :: 8 Comments :: 0 Trackbacks

    應用項目大致的體系結構:

        
     

     該異常處理框架滿足的要求:

    • 完整的異常組織結構
    • 異常的統一處理
    • 可配置,受管式,方便使用

     

    完整的異常組織結構:

    • 用戶可以方便的定義自己的異常,但所有UncheckedException需要繼承BaseAppRuntimeException,所有的checked Exception可以繼承BaseAppException,或者需要拋出且不需要check時用WrapperredAppException封裝后拋出
    • 合理地使用checked異常
    • Exception有唯一的error code,這樣用戶報告異常后,可以根據異常號找到相應Exception,把exception直接顯示給用戶也沒有太大的意義,如何紀錄exception那就是下文講到的ExceptionHandler的職責了。
    • 如果是第三方包括jdk中的異常,需要封裝成BaseAppException或者BaseAppRuntimeException后拋出

                                         

       

    統一的異常處理

    異常統一在框架中進行處理,不需要在上層應用的代碼中去處理拋出的異常。為了盡量捕捉到所有的異常,將異常處理放在了ActionBroker中,這樣凡是action以后拋出的異常都可以捕捉到,因為webservice只是簡單的調用action類的方法,一般不會出現異常。當我們捕捉到異常后,需要進行異常處理,定義了ExceptionHandler接口,用接口抽象出異常處理類的具體實現。


                            
     

    USFContextFactory: 創建ExceptionContext的工廠

     1package com.ldd600.exception.context;
     2
     3public class CoreContextFactory {
     4    private static CoreContextFactory instance;
     5
     6    private volatile ExceptionContext exceptionContext;
     7
     8    private Object exceptionContextLock = new Object();
     9
    10    private CoreContextFactory() {
    11
    12    }

    13
    14    public static synchronized CoreContextFactory getInstance() {
    15        if (null == instance) {
    16            instance = new CoreContextFactory();
    17        }

    18        return instance;
    19    }

    20
    21    public ExceptionContext getExceptionContext() {
    22        ExceptionContext tempExpContext = exceptionContext;
    23        if (tempExpContext == null
    24            synchronized (exceptionContextLock) {
    25                tempExpContext = exceptionContext;
    26                if (tempExpContext == null)
    27                    exceptionContext = tempExpContext = new ExceptionContext();
    28            }

    29        }

    30        return tempExpContext;
    31    }

    32}

    33



       

    ExceptionContext: 存放全局的exception信息

      1package com.ldd600.exception.context;
      2
      3import java.util.ArrayList;
      4import java.util.Collection;
      5import java.util.Collections;
      6import java.util.HashMap;
      7import java.util.List;
      8import java.util.Map;
      9import java.util.Set;
     10
     11import org.springframework.util.Assert;
     12
     13import com.ldd600.exception.base.BaseAppRuntimeException;
     14import com.ldd600.exception.base.ConfigException;
     15import com.ldd600.exception.base.handler.ExceptionHandler;
     16import com.ldd600.exception.config.ExceptionDefinition;
     17
     18public class ExceptionContext {
     19    private Map<Class<?>, ExceptionDefinition> exceptionMap;
     20
     21    private Map<String, ExceptionHandler> handlers = new HashMap<String, ExceptionHandler>();
     22
     23    ExceptionContext() {
     24        exceptionMap = new HashMap<Class<?>, ExceptionDefinition>();
     25    }

     26
     27    public boolean containsException(Class<?> expClazz) {
     28        return (exceptionMap.containsKey(expClazz));
     29    }

     30    
     31    public void addExceptionHander(Class<?> expClazz, Class<? extends ExceptionHandler> handlerClazz) {
     32        try {
     33            ExceptionDefinition definition = getRealExceptionDefinition(expClazz);
     34            if (null == definition) {
     35                throw new IllegalArgumentException(expClazz.getName() + "not in the context, please configure or add it to the context first!!");
     36            }
     
     37            ExceptionHandler handler = handlers.get(handlerClazz.getName());
     38            if (null == handler) {
     39                handler = handlerClazz.newInstance();
     40                handlers.put(handlerClazz.getName(), handler);
     41            }

     42            
     43            definition.getHandlerNames().add(handlerClazz.getName());
     44        }
     catch (Exception ex) {
     45            throw new ConfigException("Add exception handler to context failure!", ex);
     46        }

     47    }

     48    
     49    public void addExceptionHandler(Class<?> expClazz, String errorCode, Class<? extends ExceptionHandler> handlerClazz) {
     50        Assert.hasLength(errorCode, expClazz + " errorCode must not be null or empty string!");
     51        ExceptionDefinition definition = getRealExceptionDefinition(expClazz);
     52        if(null == definition) {
     53            definition = new ExceptionDefinition(errorCode);
     54            exceptionMap.put(expClazz, definition);
     55        }

     56        addExceptionHander(expClazz, handlerClazz);
     57    }

     58    
     59    
     60    
     61    public void addExceptionHandlers(Class<?> expClazz, Class<? extends ExceptionHandler> handlerClazzes) {
     62        for(Class<? extends ExceptionHandler> handlerClazz : handlerClazzes) {
     63            addExceptionHander(expClazz, handlerClazz);
     64        }

     65    }

     66
     67    public void removeExceptionHandler(Class<?> expClazz, Class<? extends ExceptionHandler> handlerClazz) {
     68        Assert.isTrue(containsException(expClazz));
     69        String handlerName = handlerClazz.getName();
     70        getExceptionDefinition(expClazz).getHandlerNames().remove(handlerName);
     71        Collection<ExceptionDefinition> definitons = exceptionMap.values();
     72        boolean isClearHandler = true;
     73        for (ExceptionDefinition expDefinition : definitons) {
     74            if (expDefinition.getHandlerNames().contains(handlerName)) {
     75                isClearHandler = false;
     76                break;
     77            }

     78        }

     79
     80        if (isClearHandler) {
     81            handlers.remove(handlers.get(handlerName));
     82        }

     83    }

     84
     85    public void setExceptionDefinition(Class<?> expClazz, ExceptionDefinition definition) {
     86        exceptionMap.put(expClazz, definition);
     87    }

     88
     89    public ExceptionDefinition getExceptionDefinition(Class<?> expClazz) {
     90        if (containsException(expClazz)) {
     91            return exceptionMap.get(expClazz);  
     92        }
     else if (BaseAppRuntimeException.class.isAssignableFrom(expClazz.getSuperclass())) {
     93            return getExceptionDefinition(expClazz.getSuperclass());
     94        }
     else {
     95            return null;
     96        }

     97    }

     98    
     99    public ExceptionDefinition getRealExceptionDefinition(Class<?> expClazz) {
    100        return exceptionMap.get(expClazz);
    101    }

    102
    103    public List<ExceptionHandler> getExceptionHandlers(Class<?> expClazz){
    104        ExceptionDefinition definition = getExceptionDefinition(expClazz);
    105        if (null != definition) {
    106            Set<String> handlerNames = definition.getHandlerNames();
    107            List<ExceptionHandler> handlerList = new ArrayList<ExceptionHandler>(handlerNames.size());
    108            for (String handlerName : handlerNames) {
    109                ExceptionHandler handler = handlers.get(handlerName);
    110                handlerList.add(handler);
    111            }

    112            List<ExceptionHandler> resultHandlerList = new ArrayList<ExceptionHandler>(handlerList);
    113            return resultHandlerList;
    114        }
     else {
    115            return Collections.<ExceptionHandler> emptyList();
    116        }

    117    }

    118    
    119    public String getErrorCode(Class<?> expClazz){
    120        ExceptionDefinition definition = getExceptionDefinition(expClazz);
    121        if (null != definition) {
    122            return definition.getErrorCode();
    123        }
     else {
    124            return "";
    125        }

    126    }

    127    
    128    
    129}

    130
     

    ExceptionDefinition: Exception信息單元

     1package com.ldd600.exception.config;
     2
     3import java.util.LinkedHashSet;
     4import java.util.Set;
     5
     6public class ExceptionDefinition {
     7    private String errorCode;
     8
     9    private Set<String> handlerNames = new LinkedHashSet<String> ();
    10
    11    ExceptionDefinition() {
    12        
    13    }

    14    
    15    public ExceptionDefinition(String errorCode) {
    16        this.errorCode = errorCode;
    17    }

    18    
    19    public String getErrorCode() {
    20        return errorCode;
    21    }

    22
    23    public void setErrorCode(String errorCode) {
    24        this.errorCode = errorCode;
    25    }

    26
    27    public Set<String> getHandlerNames() {
    28        return handlerNames;
    29    }

    30}

    31
     

    ExceptionDefiniton定義了和某個exception相關的具體信息,根據exceptionclass name可以從exceptionContext中的exceptionMap得到指定的exception的相關信息,這些信息是在系統初始化時讀取到exceptionContext中的。并且避免了exception handler的重復初始化。

     

    可配置,受管式,方便使用

     采取兩種配置方式,exception的相關信息比如它的errorCode exceptionHandlers可以配置在外部的xml文件中,也可以用annotation標注。對于exception的處理是有繼承性質的,如果某個exception沒有在exceptionContext中注冊,就使用它的父類的配置信息。如果無任何父類在exceptionContext中注冊,就使用默認機制進行處理。

    XML 方案:

                因為spring2.0支持自定義schema功能,我們可以方便地采用自己的schema只要實現NamespaceHandlerBeanDefinitionPaser,后面一個比較重要,可以將自定義xml文件中的相關類注冊到spring的上下文中,成為spring bean

    Xml schema:

    <xsd:complexType name="exceptionType">
            
    <xsd:sequence>
                
    <xsd:element name="level" default="error" minOccurs="0">
                    
    <xsd:simpleType>
                        
    <xsd:restriction base="xsd:string">
                            
    <xsd:enumeration value="error" />
                            
    <xsd:enumeration value="warning" />
                            
    <xsd:enumeration value="info" />
                            
    <xsd:enumeration value="confirmation" />
                        
    </xsd:restriction>
                    
    </xsd:simpleType>
                
    </xsd:element>
                
    <xsd:element name="handler" maxOccurs="unbounded">
                    
    <xsd:simpleType>
                        
    <xsd:restriction base="xsd:string" />
                    
    </xsd:simpleType>
                
    </xsd:element>
            
    </xsd:sequence>
            
    <xsd:attribute name="errorCode">
                
    <xsd:simpleType>
                    
    <xsd:restriction base="xsd:string">
                        
    <xsd:whiteSpace value="preserve" />
                        
    <xsd:pattern value="LDD600-+"d{1,5}.*" />
                    
    </xsd:restriction>
                
    </xsd:simpleType>
            
    </xsd:attribute>
            
    <xsd:attribute name="class" type="xsd:string" use="required" />
        
    </xsd:complexType>

     

    Annotation方案:

                JDK1.5以上就有了annotation,可以簡化我們的配置,使得配置信息和代碼聯系在一起,增加了代碼的可讀性。如何在spring中注冊自定義的annotation和用annotation標注的class,可以參考文章2和文章:   。對于每個注冊了的classExceptionalAnnotationBeanPostProcessorparse具體的annotation信息(對于annotationparse方法還會在以后繼續改進)。

     1package com.ldd600.exception.annotation;
     2
     3import java.lang.annotation.Documented;
     4import java.lang.annotation.ElementType;
     5import java.lang.annotation.Retention;
     6import java.lang.annotation.RetentionPolicy;
     7import java.lang.annotation.Target;
     8
     9import com.ldd600.exception.base.handler.ExceptionHandler;
    10
    11@Target({ElementType.TYPE})
    12@Retention(RetentionPolicy.RUNTIME)
    13@Documented
    14public @interface Exceptional {
    15    String errorCode();
    16    Class<? extends ExceptionHandler>[] handlers();
    17}

    18


     1package com.ldd600.exception.processor;
     2
     3import org.springframework.beans.BeansException;
     4import org.springframework.beans.factory.config.BeanPostProcessor;
     5
     6import com.ldd600.exception.annotation.Exceptional;
     7import com.ldd600.exception.base.BaseAppException;
     8import com.ldd600.exception.base.BaseAppRuntimeException;
     9import com.ldd600.exception.config.ExceptionDefinition;
    10import com.ldd600.exception.context.ExceptionContext;
    11import com.ldd600.exception.context.CoreContextFactory;
    12
    13public class ExceptionalAnnotationBeanPostProcessor implements BeanPostProcessor {
    14
    15    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    16       if(bean instanceof BaseAppRuntimeException || bean instanceof BaseAppException) {
    17           Exceptional exceptional = bean.getClass().getAnnotation(Exceptional.class);
    18           if(null != exceptional) {
    19               ExceptionContext ctx = CoreContextFactory.getInstance().getExceptionContext();
    20               if(!ctx.containsException(bean.getClass())) {
    21                   ExceptionDefinition expDefinition = new ExceptionDefinition(exceptional.errorCode());
    22                   ctx.setExceptionDefinition(bean.getClass(), expDefinition);
    23               }

    24               ctx.addExceptionHandlers(bean.getClass(), exceptional.handlers());
    25               return null;
    26           }

    27       }

    28       return bean;
    29    }

    30
    31    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    32            return bean;
    33    }

    34
    35}

    36
     

    結果測試:

      1package com.ldd600.exception.test;
      2
      3import org.jmock.Expectations;
      4import org.jmock.Mockery;
      5import org.springframework.beans.factory.BeanFactory;
      6
      7import com.ldd600.exception.action.BusinessAction;
      8import com.ldd600.exception.base.BaseAppException;
      9import com.ldd600.exception.base.BaseAppRuntimeException;
     10import com.ldd600.exception.base.ConfigException;
     11import com.ldd600.exception.base.handler.ConsoleHandler;
     12import com.ldd600.exception.context.CoreContextFactory;
     13import com.ldd600.exception.dto.DefaultRequest;
     14import com.ldd600.exception.dto.DefaultResponse;
     15import com.ldd600.exception.dto.Request;
     16import com.ldd600.exception.dto.Response;
     17import com.ldd600.exception.webservice.ActionBrokerImpl;
     18
     19public class ExceptionTest extends DependencyInjectionExceptionTestCase {
     20    Mockery context = new Mockery();
     21    ActionBrokerImpl broker = new ActionBrokerImpl();
     22    final Request request = new DefaultRequest();
     23    final Response response = new DefaultResponse();
     24
     25    @Override
     26    protected String[] getConfigLocations() {
     27        return new String[] "applicationContext.xml" };
     28    }

     29
     30    public void testExceptionThrow() {
     31        final BusinessAction<Response, Request> action = context
     32                .mock(BusinessAction.class);
     33        final BeanFactory beanFactory = context.mock(BeanFactory.class);
     34        assertThrowing(new Closure() {
     35            public void run() throws Throwable {
     36                context.checking(new Expectations() {
     37                    {
     38                        allowing(beanFactory).getBean("action");
     39                        will(returnValue(action));
     40                        one(action).execute(request, response);
     41                        will(throwException(new BaseAppException()));
     42                    }

     43                }
    );
     44                broker.setExceptionHandler(new ConsoleHandler());
     45                broker.setBeanFactory(beanFactory);
     46                broker.execute("action", request, response);
     47            }

     48
     49        }
    , BaseAppException.class);
     50    }

     51
     52    public void testExceptionalAutoLoad() throws BaseAppException {
     53        final BeanFactory beanFactory = context.mock(BeanFactory.class);
     54        final BusinessAction<Response, Request> action = context
     55                .mock(BusinessAction.class);
     56        context.checking(new Expectations() {
     57            {
     58                allowing(beanFactory).getBean("action");
     59                will(returnValue(action));
     60                one(action).execute(request, response);
     61                will(throwException(new ConfigException()));
     62            }

     63        }
    );
     64        broker.setBeanFactory(beanFactory);
     65        broker.execute("action", request, response);
     66        assertEquals(CoreContextFactory.getInstance().getExceptionContext()
     67                .getErrorCode(ConfigException.class), "LDD600-00002");
     68        context.assertIsSatisfied();
     69    }

     70
     71    public void testRuntimeException() {
     72        final BusinessAction<Response, Request> action = context
     73                .mock(BusinessAction.class);
     74        final BeanFactory beanFactory = context.mock(BeanFactory.class);
     75        assertThrowing(new Closure() {
     76            public void run() throws Throwable {
     77                context.checking(new Expectations() {
     78                    {
     79                        allowing(beanFactory).getBean("action");
     80                        will(returnValue(action));
     81                        one(action).execute(request, response);
     82                        will(throwException(new BaseAppRuntimeException()));
     83                    }

     84                }
    );
     85                broker.setExceptionHandler(new ConsoleHandler());
     86                broker.setBeanFactory(beanFactory);
     87                broker.execute("action", request, response);
     88            }

     89
     90        }
    , BaseAppRuntimeException.class);
     91        // test config
     92        assertEquals(CoreContextFactory.getInstance().getExceptionContext()
     93                .getErrorCode(BaseAppRuntimeException.class), "LDD600-00001");
     94        // test handler
     95        assertFalse(response.isSuccess());
     96        assertEquals(response.getErrorCode(), CoreContextFactory.getInstance()
     97                .getExceptionContext().getErrorCode(
     98                        BaseAppRuntimeException.class));
     99        context.assertIsSatisfied();
    100    }

    101
    102    public void testCheckedException() {
    103        final BusinessAction<Response, Request> action = context
    104                .mock(BusinessAction.class);
    105        final BeanFactory beanFactory = context.mock(BeanFactory.class);
    106        assertThrowing(new Closure() {
    107            public void run() throws Throwable {
    108                context.checking(new Expectations() {
    109                    {
    110                        allowing(beanFactory).getBean("action");
    111                        will(returnValue(action));
    112                        one(action).execute(request, response);
    113                        will(throwException(new ExceptionFaker()));
    114                    }

    115                }
    );
    116                broker.setBeanFactory(beanFactory);
    117                broker.execute("action", request, response);
    118            }

    119
    120        }
    , ExceptionFaker.class);
    121        // test config
    122        assertEquals(CoreContextFactory.getInstance().getExceptionContext()
    123                .getErrorCode(ExceptionFaker.class), "LDD600-00003");
    124        // test handler
    125        assertFalse(response.isSuccess());
    126        assertEquals(response.getErrorCode(), CoreContextFactory.getInstance()
    127                .getExceptionContext().getErrorCode(
    128                        ExceptionFaker.class));
    129        context.assertIsSatisfied();
    130    }

    131}

    132


    參考資料:
     

    文章1http://www.onjava.com/pub/a/onjava/2006/01/11/exception-handling-framework-for-j2ee.html

    文章2http://sannotations.sourceforge.net/

    本文源代碼:源代碼下載

    posted on 2009-02-12 22:58 suprasoft Inc,. 閱讀(298) 評論(0)  編輯  收藏 所屬分類: J2EE
    ©2005-2008 Suprasoft Inc., All right reserved.
    主站蜘蛛池模板: 国产成人免费福利网站| a色毛片免费视频| 最近的中文字幕大全免费版| 久久精品国产亚洲AV电影| 又大又硬又爽又粗又快的视频免费| 亚洲成A人片777777| 国产午夜精品免费一区二区三区 | 亚洲av片不卡无码久久| 亚欧免费视频一区二区三区| 亚洲精品国产免费| 69成人免费视频无码专区| 亚洲国产成人AV在线播放| 国产不卡免费视频| 中文字幕免费视频精品一| 亚洲国产美国国产综合一区二区 | 日韩电影免费在线观看中文字幕| 亚洲国产国产综合一区首页| 亚洲免费电影网站| 亚洲欧美aⅴ在线资源| 亚洲精品国精品久久99热| 免费无码又爽又刺激网站| 亚洲综合一区二区| 免费精品国产自产拍观看| 两个人看的www免费视频中文| 亚洲精品免费观看| 女性自慰aⅴ片高清免费| 青青草国产免费国产是公开| 亚洲va在线va天堂va888www| a毛片基地免费全部视频| 日本视频免费观看| 91亚洲va在线天线va天堂va国产 | 亚洲伦理一区二区| 大学生一级特黄的免费大片视频| 美女视频黄视大全视频免费的| 亚洲情XO亚洲色XO无码| 野花高清在线观看免费完整版中文| 国产一区二区三区亚洲综合| 亚洲AV无码久久精品成人 | 亚洲AV色无码乱码在线观看| 亚洲中文久久精品无码ww16| 97在线观免费视频观看|