服务异常返回的设计

服务异常返回的设计

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

为了实现这个目的,在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) {
            ...
    }
    ...
}

posted on 2017-07-05 21:43  zyunx  阅读(346)  评论(0编辑  收藏  举报

导航