Spring mvc 从应用程序服务层报告错误

Spring mvc 从应用程序服务层报告错误,spring-mvc,error-handling,domain-driven-design,Spring Mvc,Error Handling,Domain Driven Design,我正在基于SpringMVC实现web应用程序,并围绕DDD概念进行组织。目前我尝试实现机票预订功能。客户可以查看特定活动的可用门票数量。然后,他可以输入要预订的车票数量并提交表单。请求由调用负责注册的应用程序服务的控制器接收。应用程序服务逻辑如下: 验证传入参数: 1A。检查具有给定ID的事件是否存在 1B。检查可用票数是否允许预订 如果验证通过,则继续注册;否则,请报告错误 我对报告验证错误的正确方法有一些疑问,特别是对于1B点。门票数量不允许预订的情况并不罕见。客户可以在数据库中看到未

我正在基于SpringMVC实现web应用程序,并围绕DDD概念进行组织。目前我尝试实现机票预订功能。客户可以查看特定活动的可用门票数量。然后,他可以输入要预订的车票数量并提交表单。请求由调用负责注册的应用程序服务的控制器接收。应用程序服务逻辑如下:

  • 验证传入参数:
    • 1A。检查具有给定ID的事件是否存在
    • 1B。检查可用票数是否允许预订
  • 如果验证通过,则继续注册;否则,请报告错误
  • 我对报告验证错误的正确方法有一些疑问,特别是对于1B点。门票数量不允许预订的情况并不罕见。客户可以在数据库中看到未与当前票证数量完全同步的票证数量(最终一致性)-其他人可以同时预订一些票证

    最初我想通过抛出一些特定的异常来报告这个问题。然而,我可以想到另外两种有问题的情况,每种情况都有一个例外,这听起来不太好

    我考虑的另一个选项是抛出一种包含错误代码的异常类型。然而,我不知道如何在SpringMVC中正确处理这种情况


    解决此类问题的最佳做法是什么?在MVC应用程序中如何处理它们?非常感谢您的建议。

    我认为这些是无法恢复的业务约束中断

    我当前的解决方案是异常层次

    public abstract class UncheckedApplicationException extends RuntimeException {
    
        //omitted factory methods and constructors
        public abstract String getStatusCode();
    
        public abstract String getI18nCode();//ignore this if you don't need i18n    
    
        public abstract String[] getI18nArgs();//ignore this if you don't need i18n 
    }
    
    任何自定义异常都会扩展此异常。我认为这可以避免这样的代码:

    try {  
        //invoke your application service
    } catch (InsufficientInventoryException e) {  
        statusCode = INSUFFICIENT_INVENTORY;  
    } catch (ExpriedPriceException e) {  
        statusCode = EXPIRED_PRICE;  
    } catch (NoSuchProductException e) {  
        statusCode = NO_SUCH_PRODUCT;  
    } catch (Exception e) {  
        statusCode = UNKNOWN;  
    }
    
    控制器代码段:

    try {  
        //invoke your application service here 
        statusCode = SUCCESS;
        message = messageSource.getSuccess(locale));
    } catch (UncheckedApplicationException e) {  
        statusCode = e.getStatusCode();  
        message = messageSource.getMessage(e, locale));
    } catch (Exception e) {  
        statusCode = UNKNOWN;  
        message = messageSource.getUnknownError(e, locale));
    }
    //add statusCode & message to modelAttribute
    
    如果控制器组织良好(但相当困难),则可以使用@ExceptionHandler来减少样板文件try-catch代码


    使用Excepton的另一个原因是,应用程序服务通常用于划分事务边界。如果要回滚,必须抛出异常。

    谢谢,另一个有趣的选项可能是只将消息代码放在异常中,然后(通过此代码)从MessageSource检索它。