具有高阶功能的异常处理/抑制

时间:2019-01-23 06:57:55

标签: generics kotlin

我在微服务架构中有一个应用程序。该应用程序从不同的源获取数据,并且从其他各种应用程序获得许多不同的错误响应。某些异常(例如404-Not found异常)可以引发并返回给最终用户,但其他异常(错误请求,++)不能并且需要通过抛出其他异常来抑制。

但是,我知道可以通过try-catch设置异常并调节该问题的处理方式来解决,但这会涉及很多代码。有时我想接受4-5个不同的异常,而其他时候只有1-2个例外。


无论如何..我需要一些帮助进行高阶功能。我想要一个将一个或多个“可接受的异常”作为参数(它们是Runtime-exceptions)并仅在try-catch中抛出批准的异常的函数。

这是我尝试过的方法,但似乎语法不正确(伪代码atm。)。任何帮助都非常感谢。

  fun getData() {
    return supressExceptions(
        NotFoundException::class.java, 
        ForbiddenException::class.java, 
        AuthorizationException::class.java) {
      service.getData()
    }
  }

  private inline fun <T, X : RuntimeException> supressExceptions(vararg approvedException: Class<X>, block: () -> T): T =
      try {
        block()
      } catch (ex: Exception) {
        // Loop through the approved exceptions.
        // Throw the approved exception
        throw ex
        // ELSE: do something else if the exception is not approved.
      }

3 个答案:

答案 0 :(得分:2)

以下是您要寻找的东西吗?

private inline fun <T> supressExceptions(vararg approvedException: Class<out RuntimeException>, block: () -> T): T =
        try {
            block()
        } catch (ex: Exception) {
            if (approvedException.contains(ex::class.java)) {
                // Approved exception
                throw ex
            }
            // ELSE: do something else if the exception is not approved.
            else throw Exception("Something else")
        }

答案 1 :(得分:1)

这可以通过any来实现:

  private inline fun <T, X : RuntimeException> supressExceptions(vararg approvedException: Class<X>,
      block: () -> T): T =
      try {
        block()
      } catch (ex: Exception) {
        when {
          approvedException.any { ex::class.java == it } -> throw ex
          else -> {
            throw SupressedException(ex)
          }
        }
      }
  

任何:如果至少一个条目与给定谓词匹配,则返回true。

答案 2 :(得分:1)

正如评论中已经提到的那样:从命名的角度来看,我本以为preventExceptions会接受要抑制的异常的参数。

我想知道您是否真的想检查抛出的异常是否实际上是给定异常类型的实例,即是否也应该批准/禁止给定类型的子类。

在这种情况下,我宁愿使用以下代码:

inline fun <T> suppressAllExceptions(vararg exceptExceptions: Class<out Exception> = emptyArray(),
                                     block: () -> T) = try {
  block()
} catch (e: Exception) {
  throw if (exceptExceptions.any { it.isInstance(e) }) {
    e
  } else SuppressedException(e)
}

您仍将按照显示的方式使用它:

suppressAllExceptions {
  throw IllegalStateException("i am suppressed soon")
}
suppressAllExceptions(IllegalStateException::class.java, 
                      IllegalArgumentException::class.java) {
  throw IllegalStateException("i am not suppressed")
}
class MyIllegalStateException : IllegalStateException()
suppressAllExceptions(IllegalStateException::class.java, 
                      IllegalArgumentException::class.java) {
  throw MyIllegalStateException("i am not suppressed neither")
} 

我想得更多:为什么您在不同的地方批准不同类型的异常?对我来说这听起来不对。您可能宁愿抑制除某些定义明确的例外以外的所有异常,在这种情况下,您一开始不需要此类泛型函数,而是希望其中一个抑制函数包含定义明确的列表:

/**
 * Suppresses all exceptions except the well-defined ones: [NotFoundException], ...
 */
inline fun <T> suppressExceptions(block: () -> T) = try {
  block()
} catch (e: Exception) {
  throw when (e) {
    is NotFoundException,
    is ForbiddenException,
    // all the other well-defined non-suppressable types
    is AuthorizationException -> e
    else -> SuppressedException(e)
  }
}