声明:本文首发于微信订阅号:Dart客栈,微信后台回复05164获取本篇源码
文章为原创,如需转载请注明出处,并告知作者,谢谢!
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/b
、a/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服务器,也是对我写作的一种肯定🙏!