聲明:本文首發(fā)于微信訂閱號(hào):Dart客棧,微信后臺(tái)回復(fù)05166獲取本篇源碼
文章為原創(chuàng)藕夫,如需轉(zhuǎn)載請(qǐng)注明出處昌屉,并告知作者,謝謝福扬!
1.介紹
這一節(jié)我們來學(xué)習(xí)一下資源控制器ResourceController
2. 什么是資源控制器腕铸?
可以從名字看出,這個(gè)控制器是用來管理資源的铛碑,也就是上一節(jié)中介紹了控制器B狠裹,也可以稱為端點(diǎn)的控制器,可以用以下圖來描述:
從上圖可以得到的信息為汽烦,控制器可以處理多個(gè)請(qǐng)求路徑涛菠,并可返回不同的內(nèi)容,那么為什么它可以處理這么多個(gè)請(qǐng)求呢撇吞?如果多次請(qǐng)求讓Controller處理俗冻,那么會(huì)不會(huì)出現(xiàn)該控制器會(huì)不斷的實(shí)例化,導(dǎo)致性能出現(xiàn)問題呢牍颈?
3. Recyclable
我們?cè)诓榭丛创a的時(shí)候迄薄,可以看到ResourceController
繼承Controller
并實(shí)現(xiàn)了Recyclable
,這個(gè)Recyclable
就是能讓Controller
實(shí)現(xiàn)在處理完請(qǐng)求后,進(jìn)行回收煮岁,等待下次請(qǐng)求時(shí)不用重新實(shí)例化讥蔽,它主要實(shí)現(xiàn)了recycledState
和restore
從源碼中可以看出,它保存了類名為
BoundController
的一個(gè)實(shí)體画机,那么這個(gè)實(shí)體哪個(gè)地方耗時(shí)冶伞,導(dǎo)致需要循環(huán)再用呢?我們進(jìn)一步看源碼可以看到色罚,它的構(gòu)造方法一開始就調(diào)用了反射碰缔,大家應(yīng)該都知道,反射是比較耗時(shí)的戳护,如果每次請(qǐng)求一下都要反射一次的話金抡,那這個(gè)性能太低了瀑焦,所以需要循環(huán)使用,而歸功于上面的反射梗肝,可以使用元數(shù)據(jù)(注解)進(jìn)行對(duì)請(qǐng)求的處理
4.請(qǐng)求方法
目前Aqueduct
框架支持下面的注解請(qǐng)求方法榛瓮,并且支持0-4
的請(qǐng)求路徑
Operation('請(qǐng)求方法')
Operation.get
Operation.put
Operation.post
Operation.delete
我們來把之前的獲取文章接口使用ResourceController
實(shí)現(xiàn)看看,新建文件article_controller
,然后添加以下代碼
class ArticleController extends ResourceController {
ArticleController(this.context);
final ManagedContext context;
@Operation.get() //獲取文章列表
FutureOr<Response> getArticle() async {
//查詢文章巫击,并根據(jù)createDate進(jìn)行排序
final query = Query<Article>(context)
..sortBy((e) => e.createData, QuerySortOrder.ascending);
final List<Article> articles = await query.fetch();
return Result.data(articles);
}
}
然后把ArticleController鏈接到Router里面
@override
Controller get entryPoint {
//定義路由禀晓、請(qǐng)求鏈接等,在啟動(dòng)期間調(diào)用
return Router(notFoundHandler: (request) async {
//當(dāng)出現(xiàn)請(qǐng)求不到接口的時(shí)候坝锰,返回下面內(nèi)容給客戶端
await request.respond(Response.notFound()
..contentType = ContentType.json
..body = {
'code': 404,
'msg': 'not found',
"data": null,
});
//打印日志
logger.warning("${request.toDebugString()}");
})
//new
..route('/article/[:id([0-9]+)]').link(
() => ArticleController(context),
);
//new
上面代碼就完成了請(qǐng)求文章列表的接口粹懒,讓我們來請(qǐng)求一下http://localhost:8080/article
可以看到,我們成功的拿到了數(shù)據(jù)顷级,下面凫乖,我們繼續(xù)添加文章的增刪改的接口
class ArticleController extends ResourceController {
ArticleController(this.context);
final ManagedContext context;
@Operation.get() //獲取文章列表
FutureOr<Response> getArticle() async {
//查詢文章,并根據(jù)createDate進(jìn)行排序
final query = Query<Article>(context)
..sortBy((e) => e.createDate, QuerySortOrder.ascending);
final List<Article> articles = await query.fetch();
return Result.data(articles);
}
@Operation.post()//添加一篇文章
FutureOr<Response> insertArticle(
@Bind.body(ignore: ["createData"]) Article article) async {
article.createDate = DateTime.now();
//插入一條數(shù)據(jù)
final result = await context.insertObject<Article>(article);
return Result.data(result);
}
@Operation.get('id')//查詢單個(gè)文章
Future<Response> getArticleById(@Bind.path('id') int id) async {
//根據(jù)id查詢一條數(shù)據(jù)
final query = Query<Article>(context)..where((a) => a.id).equalTo(id);
final article = await query.fetchOne();
if (article != null) {
return Result.data(article);
} else {
return Result.successMsg();
}
}
@Operation.put()//修改一篇文章
Future<Response> updateArticleById(
@Bind.body(ignore: ["createData"]) Article article) async {
final query = Query<Article>(context)
..values.content = article.content
..where((a) => a.id).equalTo(article.id);
//更新一條數(shù)據(jù)
final result = await query.updateOne();
// final article = await query.fetchOne();
if (result != null) {
return Result.data(result);
} else {
return Result.errorMsg("更新失敗弓颈,數(shù)據(jù)不存在");
}
}
@Operation.delete('id')//刪除一篇文章
Future<Response> deleteArticleById(@Bind.path('id') int id) async {
final query = Query<Article>(context)..where((a) => a.id).equalTo(id);
//刪除一條數(shù)據(jù)
final result = await query.delete();
if (result != null && result == 1) {
return Result.successMsg("刪除成功");
} else {
return Result.errorMsg("刪除失敗帽芽,數(shù)據(jù)不存在");
}
}
}
以上就是文章的增刪查改,有興趣的朋友可以CV看看效果翔冀,下面我們來學(xué)習(xí)一下在代碼中出現(xiàn)的@Bind
5.請(qǐng)求綁定
目前Aqueduct
框架支持下面的注解請(qǐng)求綁定
-
Bind.path
綁定路徑
具體使用:
@Operation.get('id')//查詢單個(gè)文章
Future<Response> getArticleById(@Bind.path('id') int id) async {
//根據(jù)id查詢一條數(shù)據(jù)
final query = Query<Article>(context)..where((a) => a.id).equalTo(id);
final article = await query.fetchOne();
if (article != null) {
return Result.data(article);
} else {
return Result.successMsg();
}
}
對(duì)應(yīng)請(qǐng)求:http://localhost:8080/article/1
-
Bind.query
綁定Url查詢參數(shù)
具體使用:
@Operation.get() //獲取文章列表或一篇文章
FutureOr<Response> getArticle({@Bind.query('id') int id}) async {//使用中括號(hào)表示參數(shù)可選
if (id != null) {
//查詢一篇文章
final query = Query<Article>(context)..where((a) => a.id).equalTo(id);
final article = await query.fetchOne();
if (article != null) {
return Result.data(article);
} else {
return Result.successMsg();
}
} else {
//查詢文章导街,并根據(jù)createDate進(jìn)行排序
final query = Query<Article>(context)
..sortBy((e) => e.createDate, QuerySortOrder.ascending);
final List<Article> articles = await query.fetch();
return Result.data(articles);
}
}
對(duì)應(yīng)請(qǐng)求:http://localhost:8080/article?id=1
-
Bind.header
綁定請(qǐng)求頭
具體使用:
class ArticleController extends ResourceController {
ArticleController(this.context);
final ManagedContext context;
@Bind.header("token")
String token;//@Bind注解可以在局部變量使用,根據(jù)傳入的key獲取對(duì)應(yīng)的值
//...
}
-
Bind.body
綁定請(qǐng)求體(需要注意纤子,獲取的內(nèi)容為json
形式傳遞的數(shù)據(jù))
具體使用:
@Operation.post() //添加一篇文章
FutureOr<Response> insertArticle(
@Bind.body(ignore: ["createData"]) Article article) async {
//這里可以直接轉(zhuǎn)為實(shí)體搬瑰,但需要注意的是@Bind.body里的參數(shù)含義如下
//ignore表示忽略哪些字段
//reject表示拒絕接收哪些字段
//require表示哪些字段必須有
//啥都不填表示參數(shù)如果不傳則為空
article.createDate = DateTime.now();
//插入一條數(shù)據(jù)
final result = await context.insertObject<Article>(article);
return Result.data(result);
}
6.ResourceController全局參數(shù)
當(dāng)某個(gè)控制器需要獲取和設(shè)置全局參數(shù)時(shí),框架提供一下內(nèi)容:
-
Request request
可獲取請(qǐng)求信息 -
Map<String, String> get pathVariables
可獲取路徑 -
List<ContentType> acceptedContentTypes
可設(shè)置接收的內(nèi)容類型 -
ContentType responseContentType
可設(shè)置響應(yīng)的內(nèi)容類型
7.生命周期
很多時(shí)候计福,一個(gè)請(qǐng)求的到來跌捆,通知伴隨者控制器的生命周期,下面是ResourceController
的生命周期
FutureOr<RequestOrResponse> willProcessRequest(Request req)
//在處理請(qǐng)求之前調(diào)用象颖,如果返回Response類型佩厚,則終止后續(xù)處理
void willDecodeRequestBody(RequestBody body)
//在解碼請(qǐng)求體之前調(diào)用
void didDecodeRequestBody(RequestBody body)
//在解碼請(qǐng)求體之后調(diào)用,如果沒有請(qǐng)求體说订,則不執(zhí)行
FutureOr<RequestOrResponse> handle(Request request)
//該方法繼承自Controller,無需處理
以上就是這一節(jié)的所有內(nèi)容抄瓦,如果小伙伴們覺得有收獲,不妨點(diǎn)一下點(diǎn)個(gè)贊陶冷,讓我能看到你跟我一起學(xué)習(xí)Dart服務(wù)器钙姊,也是對(duì)我寫作的一種肯定??!