日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Akka(32): Http:High-Level-Api,Route exception handling

發(fā)布時(shí)間:2025/4/16 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Akka(32): Http:High-Level-Api,Route exception handling 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? Akka-http routing DSL在Route運(yùn)算中拋出的異常是由內(nèi)向外浮出的:當(dāng)內(nèi)層Route未能捕獲異常時(shí),外一層Route會(huì)接著嘗試捕捉,依次向外擴(kuò)展。Akka-http提供了ExceptionHandler類來處理Route運(yùn)算產(chǎn)生的異常:

trait ExceptionHandler extends ExceptionHandler.PF {/*** Creates a new [[ExceptionHandler]] which uses the given one as fallback for this one.*/def withFallback(that: ExceptionHandler): ExceptionHandler/*** "Seals" this handler by attaching a default handler as fallback if necessary.*/def seal(settings: RoutingSettings): ExceptionHandler }object ExceptionHandler {type PF = PartialFunction[Throwable, Route]private[http] val ErrorMessageTemplate: String = {"Error during processing of request: '{}'. Completing with {} response. " +"To change default exception handling behavior, provide a custom ExceptionHandler."}implicit def apply(pf: PF): ExceptionHandler = apply(knownToBeSealed = false)(pf)private def apply(knownToBeSealed: Boolean)(pf: PF): ExceptionHandler =new ExceptionHandler {def isDefinedAt(error: Throwable) = pf.isDefinedAt(error)def apply(error: Throwable) = pf(error)def withFallback(that: ExceptionHandler): ExceptionHandler =if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = false)(this orElse that) else thisdef seal(settings: RoutingSettings): ExceptionHandler =if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = true)(this orElse default(settings)) else this}def default(settings: RoutingSettings): ExceptionHandler =apply(knownToBeSealed = true) {case IllegalRequestException(info, status) ? ctx ? {ctx.log.warning("Illegal request: '{}'. Completing with {} response.", info.summary, status)ctx.complete((status, info.format(settings.verboseErrorMessages)))}case NonFatal(e) ? ctx ? {val message = Option(e.getMessage).getOrElse(s"${e.getClass.getName} (No error message supplied)")ctx.log.error(e, ErrorMessageTemplate, message, InternalServerError)ctx.complete(InternalServerError)}}/*** Creates a sealed ExceptionHandler from the given one. Returns the default handler if the given one* is `null`.*/def seal(handler: ExceptionHandler)(implicit settings: RoutingSettings): ExceptionHandler =if (handler ne null) handler.seal(settings) else ExceptionHandler.default(settings) }

簡(jiǎn)單來說ExceptionHandler類型就是一種PartialFunction:

trait ExceptionHandler extends PartialFunction[Throwable, Route]

因?yàn)镋xceptionHandler就是PartialFunction,所以我們可以用case XXException來捕獲需要處理的異常。留下未捕獲的異常向外層Route浮出。當(dāng)未處理異常到達(dá)最外層Route時(shí)統(tǒng)一由最頂層的handler處理。與RejectionHandler一樣,最頂層的handler是通過Route.seal設(shè)置的:

/*** "Seals" a route by wrapping it with default exception handling and rejection conversion.** A sealed route has these properties:* - The result of the route will always be a complete response, i.e. the result of the future is a* ``Success(RouteResult.Complete(response))``, never a failed future and never a rejected route. These* will be already be handled using the implicitly given [[RejectionHandler]] and [[ExceptionHandler]] (or* the default handlers if none are given or can be found implicitly).* - Consequently, no route alternatives will be tried that were combined with this route* using the ``~`` on routes or the [[Directive.|]] operator on directives.*/def seal(route: Route)(implicitroutingSettings: RoutingSettings,parserSettings: ParserSettings = null,rejectionHandler: RejectionHandler = RejectionHandler.default,exceptionHandler: ExceptionHandler = null): Route = {import directives.ExecutionDirectives._// optimized as this is the root handler for all akka-http applications(handleExceptions(ExceptionHandler.seal(exceptionHandler)) & handleRejections(rejectionHandler.seal)).tapply(_ ? route) // execute above directives eagerly, avoiding useless laziness of Directive.addByNameNullaryApply}

上面的exceptionHandler沒有默認(rèn)值,看起來好像有可能有些異常在整個(gè)Route運(yùn)算里都不會(huì)被捕獲。但實(shí)際上Akka-http提供了默認(rèn)的handler ExceptionHandler.default:

/*** Creates a sealed ExceptionHandler from the given one. Returns the default handler if the given one* is `null`.*/def seal(handler: ExceptionHandler)(implicit settings: RoutingSettings): ExceptionHandler =if (handler ne null) handler.seal(settings) else ExceptionHandler.default(settings)

通過這個(gè)ExceptionHandler.seal函數(shù)設(shè)置了最頂層的exception handler。

我們可以通過下面的方法來定制異常處理的方式:

自定義ExceptionHandler,然后:

1、把Exceptionhandler的隱式實(shí)例放在頂層Route的可視域內(nèi)(implicit scope)

2、或者,直接調(diào)用handleExceptions,把自定義handler當(dāng)作參數(shù)傳入,把Route結(jié)構(gòu)中間某層及其所有內(nèi)層包嵌在handleExceptions中,例如:

val route: Route =get {pathSingleSlash {complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))} ~path("ping") {handleExceptions(customExceptionHandler) { onSuccess(Future.successful("ok"))complete("PONG!")}} ~path("crash") {sys.error("BOOM!")}}

第一種辦法是一種頂層對(duì)所有未捕獲異常統(tǒng)一處理的方式,第二種辦法可以限制處理區(qū)域針對(duì)某層以內(nèi)的Route進(jìn)行異常捕捉。

下面是第一種辦法的使用示范:

object ExceptiontionHandlers {implicit def implicitExceptionHandler: ExceptionHandler =ExceptionHandler {case _: ArithmeticException =>extractUri { uri =>complete(HttpResponse(InternalServerError, entity = s"$uri: Bad numbers, bad result!!!"))}}def customExceptionHandler: ExceptionHandler =ExceptionHandler {case _: RuntimeException =>extractUri { uri =>complete(HttpResponse(InternalServerError, entity = s"$uri: Runtime exception!!!"))}}}

第二種方式的使用示范如下:

val route: Route =get {pathSingleSlash {complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))} ~path("ping") {onSuccess(Future.successful("ok"))complete("PONG!")} ~handleExceptions(customExceptionHandler) {path("crash") {sys.error("BOOM!")}}}

下面是本次討論中的示范源代碼:

import akka.actor._ import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.http.scaladsl.server._ import akka.http.scaladsl.server.Directives._ import akka.stream._ import StatusCodes._ import scala.concurrent._object ExceptiontionHandlers {implicit def implicitExceptionHandler: ExceptionHandler =ExceptionHandler {case _: ArithmeticException =>extractUri { uri =>complete(HttpResponse(InternalServerError, entity = s"$uri: Bad numbers, bad result!!!"))}}def customExceptionHandler: ExceptionHandler =ExceptionHandler {case _: RuntimeException =>extractUri { uri =>complete(HttpResponse(InternalServerError, entity = s"$uriRuntime exception!!!"))}}}object ExceptionHandlerDemo extends App {import ExceptiontionHandlers._implicit val httpSys = ActorSystem("httpSys")implicit val httpMat = ActorMaterializer()implicit val httpEc = httpSys.dispatcherval (port, host) = (8011,"localhost")val route: Route =get {pathSingleSlash {complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))} ~path("ping") {onSuccess(Future.successful("ok"))complete("PONG!")} ~handleExceptions(customExceptionHandler) {path("crash") {sys.error("BOOM!")}}}val bindingFuture: Future[Http.ServerBinding] = Http().bindAndHandle(route,host,port)println(s"Server running at $host $port. Press any key to exit ...")scala.io.StdIn.readLine()bindingFuture.flatMap(_.unbind()).onComplete(_ => httpSys.terminate())}

?

轉(zhuǎn)載于:https://www.cnblogs.com/tiger-xc/p/7735377.html

總結(jié)

以上是生活随笔為你收集整理的Akka(32): Http:High-Level-Api,Route exception handling的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。