• 服务异常返回的设计


    服务异常返回的设计

    服务是不能抛出异常的(在《服务返回对象的设计》中有讨论这个问题)。

    为了实现这个目的,在Java实现中,我们通常会用try-catch-finally语句包含整个方法体。

    这样做是不优美的。

    优美的程序应该是简洁的只专注于做一件事(这里指不考虑异常处理),无重复代码的

    使用AOP处理服务方法抛出的异常

    解决上面问题的一种思路是:引入一个服务方法注解和一个服务异常处理Aspect。
    Aspect拦截服务方法,处理服务方法抛出的异常,并返回一个code为“ERROR”的服务返回对象。

    服务方法注解ServiceMethod

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.RUNTIME)   
    @Documented  
    public @interface ServiceMethod {}
    

    服务异常处理ServiceExcHandlerAspect

    需要依赖aspectjrt

    public class ServiceExcHandlerAspect {
        public Object doAroundMethod(ProceedingJoinPoint point) {
            Object response = null;
            try {
                response =  point.proceed();
            } catch (Throwable e) {
                ServiceResponse<Serializable> err = new ServiceResponse<Serializable>();
                err.setCode(ServiceCode.ERROR);
                response = err;
            }
            return response;
        }
    }
    

    Spring配置

    细粒度的异常码

    服务应该根据不同的服务,返回不同的异常码。
    如果一个服务方法在发生异常时,一概返回ERROR异常码,未免太粗暴。

    改进思路是引入服务异常类,这个异常类包含一个code字段。
    当Aspect处理这类异常时,会根据这个异常的code字段,创建服务返回对象。

    服务异常类

    public class ServiceException extends RuntimeException {
        private String code;
    
        public String getCode() {
            return code;
        }
    
        // 异常构造器
        ...
    }
    

    改进后的ServiceExcHandlerAspect

    public class ServiceExcHandlerAspect {
        public Object doAroundMethod(ProceedingJoinPoint point) {
            Object response = null;
            try {
                response =  point.proceed();
            } catch (ServiceException e) {
                response = exceptionResponse(e.getCode());
            } catch (Throwable e) {
                response = exceptionResponse(ServiceCode.ERROR);
            }
            return response;
        }
    
        private Object exceptionResponse(String code) {
            ServiceResponse<Serializable> err = new ServiceResponse<Serializable>();
            err.setCode(code);
            return err;
        }
    }
    

    另一种方案: 不使用AOP的传统方法

    如果你不喜欢使用AOP, 你可以

    public class ArticleListServiceImpl implements ArticleListService {
        ServiceResponse<ListArticleData> listArticle(ListArticleRequest request) {
            ServiceResponse<ListArticleData> response = null;
            try {
                response =  doListArticle(request);
            } catch (ServiceException e) {
                response = exceptionResponse(e.getCode());
            } catch (Throwable e) {
                response = exceptionResponse(ServiceCode.ERROR);
            }
                return response;
        }
    
        ServiceResponse<ListArticleData> doListArticle(ListArticleRequest request) {
                ...
        }
        ...
    }
  • 相关阅读:
    VisualC#的菜单编程
    利用Mutex实现应用程序的单实例运行
    C#下实现动态系统托盘图标
    C#中TreeView组件使用方法初步
    VisualC#中实现窗体间的数据传递之一
    AJAX在VS2005中的简单应用
    LiteORM学习一:EntityObject 设计
    读书笔记:人月神话的博客积极的心态读后感
    LiteORM学习三:查询设计
    LiteORM学习二:数据库设计
  • 原文地址:https://www.cnblogs.com/zyunx/p/7123476.html
Copyright © 2020-2023  润新知