数据库
PostgreSQL
读音:"post-gress-Q-L"。被简略念为 "postgres",官方读音文件 https://www.postgresql.org/files/postgresql.mp3
什么是PostgreSQL?
PostgreSQL是一个功能强大的开源对象关系数据库管理系统(ORDBMS)。 用于安全地存储数据; 支持最佳做法,并允许在处理请求时检索它们。
它由PostgreSQL全球开发集团(全球志愿者团队)开发。 它不受任何公司或其他私人实体控制。 它是开源的,其源代码是免费提供的。它也是跨平台的,可以在许多操作系统上运行,如Linux,FreeBSD,OS X,Solaris和Microsoft Windows等。
安装
Dart 服务端
使用Dart语言的原生API开发HTTP服务器仍显得过于繁琐,因此我们需要一个HTTP服务器框架,这样我们就只需要关注业务逻辑的处理。如果大家使用过任何一款成熟的HTTP服务器框架,那么对于新框架上手就会易如反掌,因为绝大多数服务器框架的概念都是相同的,主要就是ORM、路由映射、模板渲染、中间件等等这些东西。
根据我所知的,目前可用的仍在维护的Dart的HTTP服务器框架主要有四个,依次按照star最多的从上到下来排序:
其中排第一的 aqueduct 是功能、文档、示例最完善的,因此我们就以此框架做演示
安装
pub global activate aqueduct
创建项目
执行命令,生成项目api_server
pub global run aqueduct create api_server
最简示例——hello world
其中bin/main.dart下的入口文件可以不用修改,主要修改lib/channel.dart,删除多余注释,代码如下
import 'package:api_server/controller.dart';
import 'api_server.dart';
class ApiServerChannel extends ApplicationChannel {
@override
Future prepare() async {
logger.onRecord.listen((rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
}
@override
Controller get entryPoint {
final router = Router();
router
.route("/")
.linkFunction((request) async {
return Response.ok('hello world!');
});
return router;
}
}
简单说一下,这里有两个实现,其中prepare()方法一般用于预处理,例如连接数据库等,我们暂时用不到,不需理会。entryPoint方法是我们真正需要关注的方法,它的执行在prepare()方法之后,当有请求到来时,就会被回调。我们在该方法中注册路由,这里注册一个根路径,并设置一个响应请求的匿名回调方法。当我们打开浏览器访问http://localhost:8888时,它返回一个响应,即向浏览器打印一句hello world!
cd到项目根路径下,执行以下命令启动服务
dart bin/main.dart
或者
pub global run aqueduct serve
在浏览器访问http://localhost:8888,可以看输出hello world!
路由
Router除了可以注册回调方法,还可以关联一个Controller用于处理来自客户端的请求。自定义一个Controller。它需要继承自框架的Controller类,并实现一个handle方法。
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:aqueduct/aqueduct.dart';
class ItemsController extends Controller {
@override
Future<RequestOrResponse> handle(Request request) async {
final content = await File('asset/data.json').readAsString();
return Response.ok(json.decode(content));
}
}
注册路由
@override
Controller get entryPoint {
final router = Router();
router
.route("/")
.linkFunction((request) async {
return Response.ok('hello world!');
});
// 注册一个新的url,并关联到我们自定义的Controller上
router
.route('/api/all')
.link(() => ItemsController());
return router;
}
通常的,涉及到更复杂请求,如post等,应继承自ResourceController,通过注解定义请求类型
class ItemDataController extends ResourceController{
ItemDataController(this.context);
final ManagedContext context;
@Operation.get()
Future<Response> getItems(@Bind.query('offset') int offset, @Bind.query('limit') int limit) async {
// 查询数据库
final query = Query<Paragraph>(context)
..offset = offset
..fetchLimit = limit;
// 返回json结果
return Response.ok(await query.fetch());
}
PostgreSQL ORM
定义与数据库中表映射的实体类
class Paragraph extends ManagedObject<_Paragraph> implements _Paragraph {}
// 设置表名称
@Table(name: "paragraph")
class _Paragraph {
// 表映射的实体类
// 属性对应表中字段
@primaryKey
int id;
String nick_name ;
String avatar ;
String content ;
String img_url ;
String date ;
int like_no ;
int tap_no ;
}
连接数据库
@override
Future prepare() async {
// 读取配置文件
final config = AppConfiguration.fromFile(File(options.configurationFilePath));
final db = config.database;
final persistentStore = PostgreSQLPersistentStore.fromConnectionInfo(
db.username, db.password, db.host, db.port, db.databaseName);
// 连接数据库
context = ManagedContext(
ManagedDataModel.fromCurrentMirrorSystem(), persistentStore);
}
更多细致功能可参考 aqueduct官方文档
后续涉及到Flutter课程后,会再介绍如何开发注册、登录以及生成token等功能,以便于配合Flutter 演示token的储存和使用。
公众号“编程之路从0到1”