Dart-Aqueduct框架開發(四)

  • 2019 年 10 月 6 日
  • 筆記

上一篇

聲明:本文首發於微信訂閱號:Dart客棧 文章為原創,如需轉載請註明出處,並告知作者,謝謝!

1.介紹

這篇文章將詳細介紹URL路由,前幾篇有小夥伴私信留言說講得有點快,感覺跟不上,所以,接下來的文章中,將詳細介紹Aqueduct的相關內容.

2.什麼是URL?

每個http請求都有一個URl,可以作為客戶端訪問伺服器的一個訪問路徑,例如:http://xxxx.com/image/xxx.jpg,當客戶端請求該路徑地址時,服務端將返回對應的圖片資源給客戶端,URL是Web應用程式提供的,客戶端可以通過web應用程式提供的URL來操作web應用程式的資源,例如:資料庫中的數據增刪改和查詢,文件的創建和刪除等

3.URL的組成

URL由許多部分組成,其中一部分是可選的,例如https://www.baidu.com/index.html,當瀏覽器訪問這個URL時,將顯示百度的index.html頁面,這個頁面包含三個必要組件:scheme(https)host(www.baidu.com)path(/index.html),其中,path是可選的而且可以是多個,並且Aqueduct框架只關心path,也就是Aqueduct中的訪問路由

4.匹配路由

如上一節的程式碼中:

  @override    Controller get entryPoint {      //定義路由、請求鏈接等,在啟動期間調用      router.route('/queryArticle').linkFunction((request) async{        final query = Query<Article>(context);        final List<Article> articles=await query.fetch();        return Response.ok(articles);        });      return router;    }

當客戶端訪問的path/queryArticle時,將會匹配到路由,並獲取到程式碼中Response.ok裡面參數的內容,path可以有多段,路由路徑規範為每個段與請求的每個段相匹配,每個段的數量也必須相同,才能訪問到,下面是一個反面例子:/queryArticle/1,這個路徑將訪問不了上面的資源

路由路徑上的變數/:id

路徑規範中,可以擁有變數,最經常用於獲取唯一標識的資源,例如:/queryArticle/1,/queryArticle/2,通常的,我們以:冒號開頭的path作為變數,添加如下程式碼,根據id訪問文章

```dart    @override    Controller get entryPoint {      //定義路由、請求鏈接等,在啟動期間調用      router.route('/queryArticle/:id').linkFunction((request) async {        final id = request.path.variables['id']; //獲取路徑上的id變數        if (int.tryParse(id) != null) {//判斷是否為int類型          final query = Query<Article>(context)            ..where((a) => a.id).equalTo(int.parse(id));//查詢id對應的文章          final articles = await query.fetchOne();//查詢第一條          if(articles!=null){ //判斷是否存在            return Response.ok(articles); //查詢成功,返迴文章          }else{            return Response.ok({"msg":"no exist"});//不存在該文章          }        }else{          return Response.badRequest(body:{"msg":"error"});//查詢失敗,id不是int類型        }      });      return router;    }

在啟動伺服器之前,我們插入幾條數據到資料庫中

然後訪問

?很棒!程式都按照我們的預想成功了

可選路徑變數/[:id][/:id]

當前,我們的路徑在訪問文章的時候,我們之前已經有一個訪問路徑了,現在我們又加了一個,等於程式碼冗餘了,這不是我們想看到的,那麼這個時候,可以使用可選路徑,當存在id的時候,就去訪問對應的id,當不存在id時,我們就查詢所有文章,所以,將之前的程式碼合併到/queryArticle路徑來,使用中括弧:id括起來,說明這個是可選變數,程式碼如下:

  @override    Controller get entryPoint {      //可選變數[:id]      router.route('/queryArticle/[:id]').linkFunction((request) async {        final id = request.path.variables['id'];        if(id==null){          final query = Query<Article>(context);          final List<Article> articles = await query.fetch();          return Response.ok(articles);        }else if (int.tryParse(id) != null) {          final query = Query<Article>(context)            ..where((a) => a.id).equalTo(int.parse(id));          final articles = await query.fetchOne();          if(articles!=null){            return Response.ok(articles);          }else{            return Response.ok({"msg":"no exist"});          }        }else{          return Response.badRequest(body:{"msg":"error"});        }      });      return router;    }

這樣就可以實現了,感興趣的小夥伴可以運行一下,這裡就不一一展示了,路徑規範中,可以包含多個可選路徑變數,例如:/a/[b/[:c]]將匹配/a/a/ba/b/c,不匹配/a/c

限制路徑變數(可使用正則表達式)/:id([0-9]+)

一般的,我們可以使用變數後接括弧,把正則表達式括起來/:變數(正則表達式),讓我們限制一下上面請求的id只能為整數,不匹配將返回404,然後程式碼判斷部分就可以直接去掉

  @override    Controller get entryPoint {      //正則限制變數/:變數(正則)      router.route('/queryArticle/[:id([0-9]+)]').linkFunction((request) async {        final id = request.path.variables['id'];        if(id==null){          final query = Query<Article>(context);          final List<Article> articles = await query.fetch();          return Response.ok(articles);        }else{          final query = Query<Article>(context)            ..where((a) => a.id).equalTo(int.parse(id));          final articles = await query.fetchOne();          if(articles!=null){            return Response.ok(articles);          }else{            return Response.ok({"msg":"no exist"});          }        }      });      return router;    }

匹配路徑下的所有路徑/*

當我們需要做一系列的匹配時,我們可以在路徑的最後一段加上/*,例如:/user/*,當請求/user/12或者/user/12/34等,都將匹配,一般用於一個大系的URL路由處理

404的處理

一般我們的web伺服器都需要對404做訂製處理,下面是自帶的404頁面

這樣的頁面肯定不能滿足我們的請求要求,所以需要訂製,訂製也很簡單,Aqueduct框架為我們在構造路由時,特意留下一個參數設置404頁面,因為我的是API伺服器,所以返回一個json

@override    Controller get entryPoint {  //edit      final router = Router(notFoundHandler: (request) async {        Response response=Response.notFound();//404的狀態碼        response.contentType=ContentType.json;//內容類型        response.body={'code': -1, 'msg': '404'};//內容        await request.respond(response);//把內容相應出去        logger.info("${request.toDebugString()}");//列印日誌      }); //路由對象  //edit      return router;    }

然後再請求404就會看到對應的內容

以上就是這一節的所有內容,如果小夥伴們覺得有收穫,不妨點一下再看,讓我能看到你跟我一起學習Dart伺服器,也是對我寫作的一種肯定?!