亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Web API 開發(fā)實(shí)踐

doodlewind / 1427人閱讀

摘要:通過(guò)業(yè)務(wù)處理異常,將不正常的業(yè)務(wù)處理結(jié)果返回給調(diào)用者或其他。通常會(huì)在層中寫與數(shù)據(jù)庫(kù)相關(guān)的代碼,如表的關(guān)聯(lián)關(guān)系,表屬性的可取值等。返回此類響應(yīng)表示服務(wù)器拋出了未捕捉處理的異?;蝈e(cuò)誤。

前言

之前在公司負(fù)責(zé)了一個(gè)項(xiàng)目,進(jìn)行了前后端分離,筆者負(fù)責(zé)了整個(gè)項(xiàng)目的基本結(jié)構(gòu)的搭建,在此總結(jié)一些經(jīng)驗(yàn)。本文主要介紹后端web api的設(shè)計(jì)與實(shí)現(xiàn)。demo代碼鏈接:github代碼

基本架構(gòu) 代碼分層

應(yīng)用的基本架構(gòu)主要包含以下5個(gè)部分:

Controller Layer(控制器層)

Transformer Layer(轉(zhuǎn)換層)

Service Layer(服務(wù)層)

Repository Layer(倉(cāng)庫(kù)層)

Model Layer(模型層)

各個(gè)層次的主要職責(zé)如下圖所示

詳細(xì)說(shuō)明

基本的程序流程如上圖所示,從1到8。若業(yè)務(wù)邏輯比較簡(jiǎn)單,可以直接跳過(guò)Service層,由Controller層直接調(diào)用Repository層。

各層次之間可以通過(guò)依賴注入聯(lián)系起來(lái)。

業(yè)務(wù)邏輯主要分布在Service層和Model層。Service層負(fù)責(zé)工作流邏輯,即任務(wù)的具體執(zhí)行流程,如事務(wù)處理等;Model層負(fù)責(zé)領(lǐng)域邏輯,領(lǐng)域邏輯包括了業(yè)務(wù)規(guī)則、業(yè)務(wù)計(jì)算等。

通常情況下,Service層由于包含了主要的工作流邏輯,其可復(fù)用性比較差,但當(dāng)Service層的業(yè)務(wù)邏輯積累到一定程度的時(shí)候,會(huì)沉淀一些通用的業(yè)務(wù)邏輯(工作流邏輯),最好將通用的業(yè)務(wù)邏輯提取出來(lái),形成一個(gè)Service層內(nèi)的子層,稱為“通用處理層”(General Process Layer),可以將這部分代碼放到當(dāng)前Services目錄下的General目錄中。

Service層的返回值: 1.業(yè)務(wù)對(duì)象(model等業(yè)務(wù)數(shù)據(jù))2.bool值,指示處理結(jié)果。

當(dāng)Service層的業(yè)務(wù)邏輯無(wú)法正常執(zhí)行時(shí),需要拋出業(yè)務(wù)處理異常BusinessException(注意,不是程序執(zhí)行異常。業(yè)務(wù)處理異常例子:如賬戶余額不足,無(wú)法轉(zhuǎn)賬)。通過(guò)業(yè)務(wù)處理異常,將不正常的業(yè)務(wù)處理結(jié)果返回給調(diào)用者(eg:Controller或其他Service)。而在正常執(zhí)行業(yè)務(wù)邏輯的情況下,則返回Service層的正常返回值,即上面第5點(diǎn)。

在每一層中,當(dāng)新開一個(gè)子分類時(shí),最好建立一個(gè)子分類的基類。以Controller層為例子,當(dāng)需要在app/Api/Controllers/V1目錄建立一個(gè)Blog子目錄時(shí),最好在建好后的目錄中添加一個(gè)BaseController,作為該目錄下的基類。

Model層可以細(xì)分為AR(ActiveRecord)層和Domain層。Domain層通常是基于AR層。AR層中每個(gè)類對(duì)應(yīng)一張數(shù)據(jù)庫(kù)表,而Domain類中包含的數(shù)據(jù)可以來(lái)自多個(gè)AR類。

通常會(huì)在AR層中寫與數(shù)據(jù)庫(kù)相關(guān)的代碼,如表的關(guān)聯(lián)關(guān)系,表屬性的可取值等。

通常會(huì)在Domain層中寫相應(yīng)的領(lǐng)域邏輯。eg : 領(lǐng)域模型某些值的取值規(guī)則

Domain類代表一個(gè)完整的領(lǐng)域模型,而AR類則不一定構(gòu)成一個(gè)完整的領(lǐng)域模型。eg : 產(chǎn)品的數(shù)據(jù)存放在多張張表內(nèi):product_a和product_b等,因此會(huì)有多個(gè)AR類對(duì)應(yīng)這些表;同時(shí),可以引入一個(gè)名為“Product”的Domain類,它代表了一個(gè)完整的產(chǎn)品(領(lǐng)域模型)。Domain類可以基于底層AR類中一個(gè)(一般來(lái)說(shuō)是基于主表)。

目錄結(jié)構(gòu)

目錄結(jié)構(gòu)如下所示:

詳細(xì)說(shuō)明

如上圖所示,各個(gè)層次Controller、Service、Transformer、Model、Repository都有自己相應(yīng)的目錄

Controllers目錄說(shuō)明(Controller層)

Controller層,所有api的控制器放在該目錄下,按版本分類(V1,V2...),版本目錄下按照業(yè)務(wù)分類

Controller層的職責(zé):

校驗(yàn)輸入

處理請(qǐng)求&構(gòu)造響應(yīng)

調(diào)用Transformer層、Service層、Repository層,但不應(yīng)該在Controller中包含任何業(yè)務(wù)邏輯

在各個(gè)版本目錄之下(V1,V2...),按照業(yè)務(wù)將Controller分到不同的子目錄中(eg:Blog,Marketing...),而不是按照數(shù)據(jù)庫(kù)進(jìn)行劃分,雖然按照業(yè)務(wù)劃分與按照數(shù)據(jù)庫(kù)劃分的結(jié)果可能一樣

每個(gè)版本目錄下有一個(gè)版本控制器(eg:V1Controller),該版本下的所有控制器需要繼承自該控制器。版本控制器必須繼承自AppHttpControllersApiController

按照業(yè)務(wù)劃分的控制器子目錄中應(yīng)該有一個(gè)控制器基類(eg:BaseController),所有該目錄下的控制器繼承自該基類控制器

Common目錄說(shuō)明

Common目錄用于放置一些在整個(gè)項(xiàng)目中都可以使用的通用代碼,通常這些代碼不應(yīng)該包含特定的業(yè)務(wù)邏輯

子目錄Components用于放置組件代碼(注意:這些組件代碼不應(yīng)該繼承自框架代碼/第三方代碼,否則應(yīng)該將其放置到Extensions目錄)。通常這些代碼能提供一個(gè)特定的功能,但又不依賴框架本身,可以作為其他項(xiàng)目的第三方包使用

子目錄Extensions用于放置擴(kuò)展了框架代碼/第三方代碼原有功能的代碼(通常意味著繼承自框架代碼/第三方代碼),注意與Components區(qū)分

子目錄Enum用于放置“常量定義”的代碼

子目錄Helpers用于放置一些工具類,工具類中通常會(huì)提供一些靜態(tài)方法,方便調(diào)用

子目錄Scopes用于放置與Eloquent ORM相關(guān)的Scopes定義

子目錄Lib用于存放一些底層的庫(kù)文件

Models目錄說(shuō)明(Model層)

Model層,所有的模型類放置在該目錄下。通常按數(shù)據(jù)庫(kù)進(jìn)行分類(eg: DbBlog)

Model層的職責(zé)(繼承自Eloquent class時(shí)):

對(duì)應(yīng)一張數(shù)據(jù)庫(kù)表,一個(gè)model實(shí)例表示表中一條記錄

處理property ,如$db, $table,$fillable等;處理scope

Accessors & Mutators : 在從model實(shí)例中獲取或存儲(chǔ)屬性時(shí)對(duì)其進(jìn)行格式化

關(guān)聯(lián)關(guān)系配置: 使用hasMany()、belongsTo()等

model本身行為的代碼(即領(lǐng)域邏輯代碼,屬于業(yè)務(wù)邏輯的一部分),包括了model在運(yùn)行時(shí)的狀態(tài)變化,如status由valid變換成invalid

Model層的職責(zé)(不繼承自Eloquent class時(shí)):

作為一個(gè)領(lǐng)域類,包含領(lǐng)域邏輯

當(dāng)一個(gè)完整的領(lǐng)域類被分割成多個(gè)數(shù)據(jù)庫(kù)表存儲(chǔ)在數(shù)據(jù)庫(kù)中時(shí),可以在各數(shù)據(jù)庫(kù)目錄(eg:DbBlog)下創(chuàng)建Domain目錄,用于存放完整的領(lǐng)域類。

所有對(duì)應(yīng)數(shù)據(jù)庫(kù)表的Model應(yīng)該間接繼承自AppModel。每個(gè)數(shù)據(jù)庫(kù)目錄下(eg: DbBlog)應(yīng)該包含一個(gè)BaseModel(代表該數(shù)據(jù)庫(kù)),其他Model繼承自該BaseModel

注意:對(duì)數(shù)據(jù)庫(kù)表進(jìn)行“增刪改查”的操作代碼請(qǐng)不要放置到Model,應(yīng)該將“增刪改查”的代碼放置到Repository層

Repositories目錄說(shuō)明(Repository層)

Repository層,所有倉(cāng)庫(kù)類放置在該目錄下。通常按照業(yè)務(wù)/數(shù)據(jù)庫(kù)進(jìn)行劃分

Repository層的職責(zé):

僅包含對(duì)數(shù)據(jù)庫(kù)直接進(jìn)行增刪改查操作的代碼,輔助Model層(除此之外請(qǐng)不要放置其他代碼;通常增刪改的邏輯比較單一,而查則會(huì)有多種情況,將各種查詢邏輯在此處實(shí)現(xiàn))

Repository層僅包含直接對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作的代碼,其他涉及外部調(diào)用等功能的代碼應(yīng)該考慮放置在Service層中。

所有的倉(cāng)庫(kù)類應(yīng)該繼承自AppRepository類。

Services目錄說(shuō)明(Service層)

Service層,所有的服務(wù)類放置在該目錄下。通常按業(yè)務(wù)進(jìn)行分類

Service層的職責(zé):

處理牽涉到的外部行為:如發(fā)送郵件,使用外部API(如使用隊(duì)列,調(diào)用thrift,調(diào)用其他團(tuán)隊(duì)的服務(wù)等)

包含業(yè)務(wù)邏輯(主要是工作流邏輯(workflow logic),即完成某個(gè)任務(wù)的具體流程):service層是業(yè)務(wù)邏輯存在的主要地方,輔助Controller層;當(dāng)需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查時(shí),則應(yīng)該調(diào)用相應(yīng)的Repository層

所有的服務(wù)類都應(yīng)該繼承自AppService類

Transformers目錄說(shuō)明(Transformer層)

Transformer層,所有的轉(zhuǎn)換類放置在該目錄下。通常按照業(yè)務(wù)進(jìn)行分類。

Transformer層的職責(zé):

處理顯示邏輯

管理API接口的輸出(使接口的輸出與底層的Service,Repository,Model等解耦,這樣即使底層數(shù)據(jù)庫(kù)表進(jìn)行了修改,也可以不影響接口的使用)

所有的轉(zhuǎn)換類都應(yīng)該繼承自AppTransformer類

響應(yīng)

注意 : 這里討論的響應(yīng)格式指的是應(yīng)用業(yè)務(wù)相關(guān)的響應(yīng),由第三方提供的api接口的響應(yīng)不納入處理范圍(eg:laravel passport提供的響應(yīng),swagger提供的響應(yīng))

響應(yīng)分類

成功類響應(yīng):http響應(yīng)碼介于200~300。返回此類響應(yīng)表示服務(wù)器完整處理了該請(qǐng)求,沒(méi)有未捕捉處理的異常或錯(cuò)誤。(除了正常情況,在業(yè)務(wù)邏輯處理失敗時(shí),也會(huì)返回此類響應(yīng),同時(shí)會(huì)帶上相應(yīng)的業(yè)務(wù)處理失敗信息

失敗類響應(yīng) : http響應(yīng)碼不介于200~300。返回此類響應(yīng)表示服務(wù)器拋出了未捕捉處理的異?;蝈e(cuò)誤。

響應(yīng)例子 成功類響應(yīng)

1.業(yè)務(wù)邏輯處理成功

2.業(yè)務(wù)邏輯處理失敗

結(jié)構(gòu)如上圖所示:結(jié)構(gòu)與業(yè)務(wù)邏輯處理成功是一樣。區(qū)別在于成功時(shí)的code為0,失敗時(shí)則為相應(yīng)的錯(cuò)誤碼,code的取值為為appCommonEnumErrorCode.php中的業(yè)務(wù)級(jí)錯(cuò)誤碼(見(jiàn)下面的錯(cuò)誤碼)。

失敗類響應(yīng)


失敗響應(yīng)的格式配置在文件config/api.php中(關(guān)鍵詞為:errorFormat)。主要包括了message、errors、code、status_code、debug。有些信息在生產(chǎn)環(huán)境不會(huì)展示。

響應(yīng)格式化處理的思路

響應(yīng)格式化處理的大致思路:對(duì)特定的請(qǐng)求(對(duì)此類請(qǐng)求做標(biāo)記)的處理結(jié)果,在返回給用戶時(shí)進(jìn)行攔截(使用事件機(jī)制),對(duì)原有響應(yīng)進(jìn)行格式化處理。
響應(yīng)的代碼:

AppHttpMiddlewareBusinessFormatOutput : 路由中間件,在某些路由放置該中間件,則標(biāo)記該請(qǐng)求,表明其響應(yīng)需要進(jìn)行格式化處理

AppListenersAddBusinessStatusToResponse : 事件handler,處理由dingo觸發(fā)的ResponseWasMorphed事件,對(duì)響應(yīng)進(jìn)行格式化處理

AppHttpControllersApiController.php文件中的常量BusinessStatusHeader,通過(guò)響應(yīng)中的header為中介,將業(yè)務(wù)邏輯處理結(jié)果傳遞到2中的事件handler中,并最終構(gòu)成格式化響應(yīng)。

錯(cuò)誤碼

錯(cuò)誤碼相關(guān)的代碼文件為:appCommonEnumErrorCode.php
錯(cuò)誤碼格式:A-BB-CCC

A : 表示錯(cuò)誤級(jí)別,0代表成功,1代表系統(tǒng)級(jí)錯(cuò)誤,2代表服務(wù)(業(yè)務(wù))級(jí)錯(cuò)誤;

B : 表示項(xiàng)目/模塊/分類;

C : 具體錯(cuò)誤編號(hào);

不同錯(cuò)誤級(jí)別錯(cuò)誤碼的使用:

業(yè)務(wù)級(jí)錯(cuò)誤碼用于表示業(yè)務(wù)處理結(jié)果。

Service層業(yè)務(wù)處理失敗,拋出BusinessException時(shí)使用業(yè)務(wù)級(jí)狀態(tài)碼

Controller層構(gòu)造響應(yīng)時(shí),定義響應(yīng)的業(yè)務(wù)處理結(jié)果,eg:return $this->response->array($validator->errors()->toArray())->withHeader(self::BusinessStatusHeader, [ErrorCode::BUSINESS_INVALID_PARAM, "業(yè)務(wù)處理結(jié)果信息"]);

用于日志記錄(業(yè)務(wù)相關(guān)的日志)

系統(tǒng)級(jí)錯(cuò)誤碼用于表示代碼運(yùn)行異常。

用于記錄系統(tǒng)性異常日志,Controller、Service、Transformer、Repository、Model各個(gè)層皆可

注意:

錯(cuò)誤碼文件不能重寫,若有新的錯(cuò)誤碼,請(qǐng)按現(xiàn)有分類添加,不能刪除或修改舊的錯(cuò)誤碼。

異常與異常處理

異常相關(guān)的代碼:app/Exceptions目錄。在應(yīng)用代碼中,只能拋出BusinessException或者是SystemException。請(qǐng)不要拋出其他的異常,不同異常通過(guò)異常的code來(lái)區(qū)分(code的定義在app/Common/Enum/ErrorCode.php)。

當(dāng)業(yè)務(wù)邏輯執(zhí)行失敗時(shí),拋出BusinessException,常見(jiàn)可能情況如下:

Controller層校驗(yàn)輸入失敗,拋出BusinessException

Service層業(yè)務(wù)邏輯執(zhí)行失敗,直接拋出BusinessException(如賬戶余額不足,無(wú)法轉(zhuǎn)賬)

Service層業(yè)務(wù)邏輯執(zhí)行失?。ǖ珱](méi)有拋出異常,而是通過(guò)返回值指明執(zhí)行失?。?,則接受到該返回值的調(diào)用者拋出BusinessException

Controller必須捕捉BusinessException(因此即使拋出了BusinessException,依然要返回一個(gè)成功類響應(yīng)(見(jiàn)上文)),并根據(jù)BusinessException的相應(yīng)信息構(gòu)造響應(yīng)。建議所有Controller的action以下面的格式進(jìn)行編寫。

public function add(Request $request, ReserveService $reserveService){
    try{//將所有的控制器邏輯放到try塊中
        $postData = $request->post();
 
        //校驗(yàn)數(shù)據(jù)有效性
        /** @var IlluminateValidationValidator $validator*/
        $validator = Validator::make($postData, [
            "orderName" => "required",
            "reservePhone" => "required",
        ]);
 
        if($validator->fails()){//校驗(yàn)失敗
            new BusinessException(ErrorCode::BUSINESS_INVALID_PARAM, "", $validator->errors()->toArray());
        }
 
        $result = $reserveService->addReservation($postData);
        if(true === $result){
            //業(yè)務(wù)邏輯執(zhí)行成功
            return $this->response->array([]);
        }else{
            //通過(guò)返回值指示業(yè)務(wù)邏輯執(zhí)行失敗
            throw new BusinessException(ErrorCode::BUSINESS_BUSY);
        }
    } catch (BusinessException $e){//捕捉BusinessException,根據(jù)異常的信息構(gòu)造響應(yīng),下面這段代碼可以通用
        return $this->response->array($e->getExtra())
            ->withHeader(self::BUSINESS_STATUS_HEADER, [$e->getCode(), $e->getMessage()]);
    }
}

當(dāng)發(fā)生底層系統(tǒng)異常時(shí),拋出SystemException。沒(méi)有捕捉處理的SystemException會(huì)造成一個(gè)失敗類響應(yīng)(見(jiàn)上文)。

日志與預(yù)警

日志組件與預(yù)警組件的存在是為了更好的維護(hù)項(xiàng)目,及時(shí)處理bug。應(yīng)該根據(jù)自己的需要添加相應(yīng)的日志組件和預(yù)警組件。

文檔

可以選擇集成一個(gè)成熟的文檔工具,如swagger,blueprint等。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/31600.html

相關(guān)文章

  • [直播視頻] 《Java 微服務(wù)實(shí)踐 - Spring Boot 系列》限時(shí)折扣

    摘要:作為微服務(wù)的基礎(chǔ)設(shè)施之一,背靠強(qiáng)大的生態(tài)社區(qū),支撐技術(shù)體系。微服務(wù)實(shí)踐為系列講座,專題直播節(jié),時(shí)長(zhǎng)高達(dá)小時(shí),包括目前最流行技術(shù),深入源碼分析,授人以漁的方式,幫助初學(xué)者深入淺出地掌握,為高階從業(yè)人員拋磚引玉。 簡(jiǎn)介 目前業(yè)界最流行的微服務(wù)架構(gòu)正在或者已被各種規(guī)模的互聯(lián)網(wǎng)公司廣泛接受和認(rèn)可,業(yè)已成為互聯(lián)網(wǎng)開發(fā)人員必備技術(shù)。無(wú)論是互聯(lián)網(wǎng)、云計(jì)算還是大數(shù)據(jù),Java平臺(tái)已成為全棧的生態(tài)體系,...

    Enlightenment 評(píng)論0 收藏0
  • 前端開發(fā)者手冊(cè)2019

    摘要:年,和前端開發(fā)者與應(yīng)用程序前端開發(fā)者之間產(chǎn)生了巨大的分歧。開發(fā)最常見(jiàn)的解決方案有手機(jī)和平板的原生應(yīng)用程序桌面應(yīng)用程序桌面應(yīng)用程序原生技術(shù)最后,前端開發(fā)者可以從瀏覽器開發(fā)中學(xué)習(xí)到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊(cè)2019 Cody Lindley 編著 原文地址 本手冊(cè)由Frontend Masters贊助,通過(guò)深入現(xiàn)代化的前端工程課程來(lái)提高你的技能。 下載:PDF ...

    church 評(píng)論0 收藏0
  • 前端開發(fā)者手冊(cè)2019

    摘要:年,和前端開發(fā)者與應(yīng)用程序前端開發(fā)者之間產(chǎn)生了巨大的分歧。開發(fā)最常見(jiàn)的解決方案有手機(jī)和平板的原生應(yīng)用程序桌面應(yīng)用程序桌面應(yīng)用程序原生技術(shù)最后,前端開發(fā)者可以從瀏覽器開發(fā)中學(xué)習(xí)到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊(cè)2019 Cody Lindley 編著 原文地址 本手冊(cè)由Frontend Masters贊助,通過(guò)深入現(xiàn)代化的前端工程課程來(lái)提高你的技能。 下載:PDF ...

    xiao7cn 評(píng)論0 收藏0
  • 前端開發(fā)者手冊(cè)2019

    摘要:年,和前端開發(fā)者與應(yīng)用程序前端開發(fā)者之間產(chǎn)生了巨大的分歧。開發(fā)最常見(jiàn)的解決方案有手機(jī)和平板的原生應(yīng)用程序桌面應(yīng)用程序桌面應(yīng)用程序原生技術(shù)最后,前端開發(fā)者可以從瀏覽器開發(fā)中學(xué)習(xí)到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊(cè)2019 Cody Lindley 編著 原文地址 本手冊(cè)由Frontend Masters贊助,通過(guò)深入現(xiàn)代化的前端工程課程來(lái)提高你的技能。 下載:PDF ...

    鄒立鵬 評(píng)論0 收藏0
  • 前端開發(fā)者指南(2017)

    摘要:第二部分學(xué)習(xí)前端開發(fā)第二部分指出了學(xué)習(xí)成為一個(gè)前端開發(fā)者所需的自學(xué)資源和教學(xué)資源譯者注教學(xué)資源包括有講師指導(dǎo)的付費(fèi)課程計(jì)劃學(xué)院和訓(xùn)練營(yíng)。第三部分前端開發(fā)工具第三部分簡(jiǎn)要地介紹和指出了一些前端圈內(nèi)的工具。 參與者(排名不分先后):blueken; brucecham; cfanlife; DDU1222; LittlePineapple; MatildaJin; MAYDAY1993;...

    kviccn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<