引言
在Dart官網(wǎng)上看到兩個(gè)現(xiàn)成的服務(wù)端框架,作為技術(shù)棧積累,體驗(yàn)了一把 Dart Frog猾昆,并整理了這篇文章。
安裝 Dart Frog
首先是 dart 環(huán)境的要求 Dart Frog requires Dart ">=2.19.0 <3.0.0"
- 從 pub.dev 安裝 dart_frog 命令行
dart pub global activate dart_frog_cli
安裝完畢如下:
Dart Frog 創(chuàng)建項(xiàng)目
- 使用命令行創(chuàng)建一個(gè) dart frog 項(xiàng)目
dart_frog create 項(xiàng)目名稱
例如創(chuàng)建一個(gè)項(xiàng)目名為:dart_frog_server
目錄結(jié)構(gòu)如下:
使用命令行開(kāi)啟服務(wù) dart_frog dev
:
打開(kāi)瀏覽器訪問(wèn)能看到正常返回即表示服務(wù)已成功開(kāi)啟:
下面我們來(lái)創(chuàng)建自己的 API 路由
創(chuàng)建 Router
在 Dart Frog 中骡苞,我們創(chuàng)建的所有路由需要放置在 /routes 目錄中
- 例如在 routes 目錄內(nèi)新建文件夾 /pages垂蜗,創(chuàng)建一個(gè)通配符路由(通配符路由概念請(qǐng)看截圖內(nèi)注解)
請(qǐng)求效果如下:
- 利用通配符路由楷扬,我們可以做 Api 的邏輯分配,例如:
Future<Response> onRequest(
RequestContext context,
String action,
) async {
// 根據(jù)不同的接口路徑贴见,分配不同的api邏輯處理層
switch (action) {
case 'add':
return Response(body: 'arrival add - api');
case 'query':
return Response(body: 'arrival query - api');
default:
return Response(statusCode: 404);
}
}
獲取請(qǐng)求內(nèi)傳參
通過(guò) RequestContext 對(duì)象可獲取請(qǐng)求內(nèi)各參數(shù):
- 獲取請(qǐng)求類型
final method = context.request.method.value; //返回 POST/GET
- 獲取 Headers
final headers = context.request.headers;
- 獲取 Get 入?yún)?/li>
final params = context.request.uri.queryParameters; //返回 Map<String, String>
- 獲取 Post 入?yún)?/li>
final body = await context.request.body();
業(yè)務(wù)開(kāi)發(fā)中常使用 Post 方式傳入 Json 數(shù)據(jù)作為入?yún)⒑嫫唬覀兛梢宰龇庋b提供便捷獲取數(shù)據(jù):
import 'package:dart_frog/dart_frog.dart';
extension ExRequest on RequestContext {
Future<Map<String, dynamic>> get postParams async {
late Map<String, dynamic> bodyParams;
// 接收 post 傳參
try {
bodyParams =
await request.json().then((value) => value as Map<String, dynamic>);
} catch (e) {
bodyParams = {};
}
return bodyParams;
}
}
修改上面通配符路由中代碼,如下:
import 'package:dart_frog/dart_frog.dart';
import '../exension/ex_request.dart';
Future<Response> onRequest(
RequestContext context,
String action,
) async {
final json = await context.postParams;
late String targetApi;
switch (action) {
case 'add':
targetApi = 'arrival add - api';
case 'query':
targetApi = 'arrival query - api';
default:
return Response(statusCode: 404);
}
final response = <String, dynamic>{};
response['target'] = targetApi;
response['postParams'] = json; //將獲取到的Post傳參打印出來(lái)
return Response.json(body: response);
}
訪問(wèn)/pages/add
請(qǐng)求蝇刀,添加 post 入?yún)⒚樱祷亟Y(jié)果如下:
Middleware 中間件
Dart Frog 中的中間件允許在處理請(qǐng)求之前和之后執(zhí)行代碼⊥趟觯可以修改入站請(qǐng)求和出站響應(yīng)捆探,提供依賴項(xiàng),等等!
注意:routes 目錄內(nèi)只能含有一個(gè) _middleware.dart 文件站粟,為所有入站請(qǐng)求執(zhí)行的中間件黍图。
1. AOP 操作(日志示例)
-
利用中間件,我們可以在每條網(wǎng)絡(luò)請(qǐng)求前后添加日志:
image.png
請(qǐng)求http://127.0.0.1:8080/pages/add
奴烙,查看控制臺(tái)打印結(jié)果:
- 如果不想自己寫日志打印助被,dart frog 提供了一個(gè)日志打印封裝
import 'package:dart_frog/dart_frog.dart';
Handler middleware(Handler handler) {
return handler.use(requestLogger());
}
重新發(fā)起請(qǐng)求,控制臺(tái)打印結(jié)果:
2. 依賴注入
- 中間件可用于通過(guò)提供者將依賴項(xiàng)注入 RequestContext切诀。例如揩环,修改上面的 _middleware.dart 文件:
import 'package:dart_frog/dart_frog.dart';
final _dataSource = DataSource();
Handler middleware(Handler handler) {
return handler
.use(requestLogger())
.use(provider<DataSource>((_) => _dataSource));
}
class DataSource {
//模擬獲取異步數(shù)據(jù)
Future<String> mockFetchData() async {
await Future.delayed(const Duration(seconds: 3));
return 'mockFutureData is 李小轟';
}
}
如上代碼,新建類 DataSource 提供方法模擬數(shù)據(jù)庫(kù)異步查詢幅虑,我們?cè)?server 生命周期內(nèi)維護(hù)了一個(gè) dataSource 實(shí)例丰滑,而不需要在每個(gè) request 中新建實(shí)例。
在 request 中通過(guò) context 上下文獲取 dataSource 實(shí)例:
請(qǐng)求結(jié)果如下:
關(guān)于 Dart Frog 部署
創(chuàng)建一個(gè)包含 DockerFile 的生產(chǎn)構(gòu)建倒庵,這樣你就可以部署到任何地方:
dart_frog build
demo 代碼已上傳 : https://github.com/liyufengrex/dart_frog_server