當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 入門(mén)指導(dǎo) > arm webapi遇到異常怎么處理?詳細(xì)步驟告訴你
我們都知道,webapi是作為服務(wù)器來(lái)使用的,每次客戶端發(fā)送http請(qǐng)求到我們的WebApi服務(wù)里面,那么服務(wù)器就會(huì)把結(jié)果輸?shù)絩esponse到客戶端,在這個(gè)步驟中,如果服務(wù)器發(fā)生異常,那么就會(huì)返回500的錯(cuò)誤,那么在這個(gè)時(shí)候我們應(yīng)該如何來(lái)處理這樣的異常呢,在這里給你們提供一些處理異常的小技巧。
通常webapi會(huì)出現(xiàn)的異常一般有下面幾點(diǎn):Controller構(gòu)造方法中出現(xiàn)的異常, MessageHandlers中出現(xiàn)的異常,路由過(guò)程中出現(xiàn)的異常,Body在序列化/反序列化過(guò)程中出現(xiàn)的異常
由于ExceptionFilter解決不了這些異常,那么為了解決這些問(wèn)題,webapi還有兩個(gè)針對(duì)異常記錄、處理的擴(kuò)展點(diǎn):那就是IExceptionLogger 和IExceptionHandler。
對(duì)于這兩個(gè)來(lái)說(shuō),他們是webapi管道組件進(jìn)行注冊(cè)管理的,他們是有不同分工的。
IExceptionHandler作為異常處理組件,負(fù)責(zé)異常發(fā)生后的處理工作,他處于異常處理管道的最末端,當(dāng)IExceptionLogger組件進(jìn)行一場(chǎng)記錄完畢、沒(méi)有相關(guān)的ExceptoinFilter進(jìn)行異常處理時(shí),才會(huì)最終調(diào)用ExceptionHandler進(jìn)行異常處理,在Web API中,有且僅有一個(gè)ExceptionHandler進(jìn)行異常的處理。
IExceptionLogger作為異常日志記錄組件,負(fù)責(zé)異常發(fā)生后的日志記錄,他貫穿于整個(gè)Web API的生命周期中,在Web API框架里,任何一個(gè)請(qǐng)求周期中出現(xiàn)任何一個(gè)未被捕獲/處理的異常都會(huì)首先進(jìn)入這個(gè)異常日志記錄管道進(jìn)行異常Log記錄,在Web API中可以注冊(cè)多個(gè)IExceptionLogger實(shí)例負(fù)責(zé)不同的異常處理。
在Web API框架中給出了兩個(gè)基類(lèi):ExceptionLogger和ExceptionHandler,我們?cè)谑褂肊xceptionLogger基類(lèi)時(shí),他提供了ShouldLog虛方法,該方法在基類(lèi)中被調(diào)用,其作用在于避免同一個(gè)異常被同一個(gè)ExceptionLogger實(shí)例重復(fù)記錄(如當(dāng)后續(xù)的管道中該異常又被拋出,或者同一個(gè)ExceptionLogger對(duì)象不小心被注冊(cè)了兩次就會(huì)出現(xiàn)重復(fù)記錄的可能)我們也能復(fù)寫(xiě)ShouldLog方法加入我們自己的異常記錄判斷邏輯以針對(duì)不同的場(chǎng)景進(jìn)行不同的ExceptionLogger調(diào)用。如果有興趣可以反編譯一下ExceptionLogger基類(lèi)看看,他使用了顯示接口實(shí)現(xiàn),挺有意思的一個(gè)技巧。下面我們來(lái)看一個(gè)ExceptionLogger使用的例子:
public class ErroLogger : ExceptionLogger
{
public async Task LogAsync(ExceptionLoggerContext context, CancellationToken cancellationToken)
{
var sb = new StringBuilder();
//獲取Log組件
ILogger log = LogManager.GetCurrentClassLogger();
var request = context.Request;
sb.AppendLine("URL:");
//獲取URL
var url = request.RequestUri.ToString();
sb.AppendLine(url);
log.Error(context.Exception,sb.ToString(),"");
}
public override bool ShouldLog(ExceptionLoggerContext context)
{
return context.Exception is DemoException && base.ShouldLog(context);
}
}
在這里,我們重新寫(xiě)了ShouldLog,就是為了保證ExceptionLogger只記錄DemoException這個(gè)類(lèi)型的異常,而且他也調(diào)用了基類(lèi)的方法不會(huì)重復(fù)記錄同一個(gè)異常。在LogAsync方法中,我通過(guò)Log組件記錄了導(dǎo)致異常的請(qǐng)求URL,也記錄了異常信息。
那接下來(lái)我們就是要開(kāi)始對(duì)組件來(lái)注冊(cè)了:
在App_Start/WebApiConfig.cs文件中的Register方法中寫(xiě)入
config.Services.Add(typeof(IExceptionLogger),new ErroLogger());
這樣,針對(duì)DemoException的異常記錄組件就完成了,當(dāng)Web API執(zhí)行管道中出現(xiàn)未處理的DemoException異常,均會(huì)調(diào)用則個(gè)組件進(jìn)行記錄。
接下來(lái)我們來(lái)寫(xiě)一個(gè)ExceptionHandler,在整個(gè)Web API框架中,ExceptionHandler只能提供一個(gè)實(shí)例,與ExceptionLogger一樣,我們可以繼承ExceptionHandler基類(lèi)來(lái)簡(jiǎn)化異常處理,在ExceptionHandler中也提供了ShouldHandle方法來(lái)判斷該異常是否應(yīng)該處理,避免重復(fù)處理管道中其他環(huán)節(jié)重復(fù)拋出的異常。我們也同樣提供一個(gè)例子:
public class ErrorHandler : ExceptionHandler
{
public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
if (context.Exception is DemoException)
{
context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.BadRequest,new {Message=context.Exception.Message}));
}
else
{
context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError,new {Message = "服務(wù)器已被外星人綁架"}));
}
}
}
在這個(gè)例子中,我們判斷了異常的類(lèi)型,并根據(jù)不同的異常返回客戶端不同的響應(yīng)內(nèi)容和不同的HTTP狀態(tài)碼。
然后在配置中注冊(cè)這個(gè)異常處理模塊,在App_Start/WebApiConfig.cs文件中的Register方法中寫(xiě)入
config.Services.Replace(typeof(IExceptionHandler),new ErrorHandler());
這樣就替換了系統(tǒng)默認(rèn)的ExceptionHandler,可以使用我們自定義的Handler進(jìn)行異常的處理了。
在異常記錄、處理過(guò)程中,我們都碰到相應(yīng)的異常上下文參數(shù),我們能通過(guò)這個(gè)參數(shù)獲取當(dāng)前請(qǐng)求的上下文,獲取請(qǐng)求、響應(yīng)(小心有時(shí)會(huì)為空哦)、捕獲到該異常的catch塊信息等內(nèi)容,我們可以利用這些信息更好地描述、記錄、處理異常。
到這里ExceptionLogger組件和ExceptionHandler組件簡(jiǎn)單的開(kāi)發(fā)就完成了。在開(kāi)發(fā)的過(guò)程中我們可以看到,ExceptionLogger負(fù)責(zé)了全局的異常記錄,在Web API框架管道下出現(xiàn)未處理的異常ExceptionLogger都會(huì)進(jìn)行捕獲、記錄。而ExceptionHandler和ExceptionFilter功能是有重疊的,那么問(wèn)題來(lái)了,如何使用這兩個(gè)呢?下面讓你清楚的了解:
現(xiàn)在你是否已經(jīng)get到這些小竅門(mén),小方法了嗎,要多加練習(xí),在出現(xiàn)異常時(shí),要想到這些對(duì)于ExceptionHandler和ExceptionFilter而言,我覺(jué)得ExceptionHandler比ExceptionFilter更有優(yōu)勢(shì)。