scala - Akka - 声明一个隐式异常处理程序
问题描述
我创建了我的自定义异常处理程序,我希望它作为隐式对象工作,但是尽管在我的演员中抛出了异常,但它没有被调用。我从 API 获得了 OK 状态,而我应该收到无效模型的错误请求。
异常处理程序:
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server._
import Directives._
import akka.http.scaladsl.model.StatusCodes._
import regularmikey.credentials.exception.ValidationException
class CustomExceptionHandler {
implicit def customExceptionHandler(): ExceptionHandler =
ExceptionHandler {
case _: ValidationException =>
extractUri { uri =>
println(s"Request to $uri could not be handled normally")
complete(HttpResponse(BadRequest, entity = "There was a problem with validation"))
}
}
}
object CustomExceptionHandler extends CustomExceptionHandler
API 特征
import akka.actor.{ActorRef, Status}
import akka.actor.Status.Status
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ExceptionHandler, Route}
import akka.pattern.ask
import akka.util.Timeout
import regularmikey.credentials.dto.RegisterRequest
import regularmikey.credentials.dto.RequestMarshaller._
import regularmikey.exception.CustomExceptionHandler
import scala.concurrent.{ExecutionContextExecutor, Future}
trait CredentialsApi {
def createCredentialsActor(): ActorRef
implicit def requestTimeout: Timeout
implicit def executionContext: ExecutionContextExecutor
implicit def exceptionHandler: ExceptionHandler = CustomExceptionHandler.customExceptionHandler()
lazy val credentialsActor: ActorRef = createCredentialsActor()
val credentialsRoute: Route =
path("register") {
post {
pathEndOrSingleSlash {
entity(as[RegisterRequest]) {
request => {
complete {
val response: Future[Status] =
(credentialsActor ? request).mapTo[Status]
OK
}
}
}
}
}
}
}
演员:
import akka.actor.{Actor, ActorLogging, Props, Status}
import akka.util.Timeout
import cats.data.Validated
import regularmikey.credentials.dto.RegisterRequest
import regularmikey.credentials.dto.validation.RegisterRequestValidatorNec
import regularmikey.credentials.exception.ValidationException
import scala.concurrent.Future
object CredentialsActor {
def props(implicit timeout: Timeout) = Props(new CredentialsActor)
}
class CredentialsActor extends Actor with ActorLogging {
def receive: Receive = {
case RegisterRequest(userName, password, passwordRepeated) =>
val result = RegisterRequestValidatorNec.validateRegisterRequest(userName, password, passwordRepeated)
result match {
case Validated.Valid(a) => sender() ! Status.Success
case Validated.Invalid(e) => sender() ! Status.Failure(new ValidationException(e.toString))
}
}
}
class ValidationException(message: String) extends Exception
解决方案
theExceptionHandler
被隐含地拾取,route2HandlerFlow
这就是将 a 变成 aRoute
的原因Flow[Request, Response, _]
。这意味着如果您想隐式提供它,它需要在发生转换的地方可用,通常是在您调用bindAndHandle
并将您的传递Route
给它的地方,这会触发转换。
如果您希望将其作为Route
定义的一部分,您可以使用显式handleExceptions
指令(文档:https ://doc.akka.io/docs/akka-http/current/routing-dsl/directives/execution-指令/handleExceptions.html )
推荐阅读
- android - Android 9 中的 java.lang.IllegalStateException 错误
- vue.js - Vuejs v-bind 类没有动态应用类
- python - 在 python 中更快地从 s3 读取多个文件
- google-sheets - 使用 importhtml 公式时出现“#N/A”错误
- c# - 如何从 HostingEnvironment 中“取消托管”
- html - 如何使用 VBA获取标签的“aria-label”属性
- php - 如何检查数字是否等于某个数字然后执行(Mysqli)
- regex - 包含“演示”术语但不包含“测试演示”的正则表达式
- protractor - 将所有测试分组并显示在浏览器堆栈中
- java - 如何防止用户两次输入相同的文本