Controllers
控制器是一个继承自 Controller 的 Dart 类,用于将相关的请求处理程序组织在一起。每个处理程序方法都返回 Future<String>——即 HTTP 响应体。
Creating a Controller
import 'package:finch/finch_route.dart';
class UserController extends Controller {
UserController();
@override
Future<String> index() async {
return rq.renderData(data: {'message': 'User list'});
}
Future<String> show() async {
var id = rq.getParam('id');
return rq.renderData(data: {'id': id});
}
Future<String> profile() async {
rq.addParam('title', 'User Profile');
return rq.renderView(path: 'user/profile');
}
}
rq 对象
在任何 Controller 子类内部,rq 是一个返回 Context.rq 的 getter——即当前的 Request 对象。它提供了对请求数据、session、cookie 以及所有响应方法的访问。
将控制器附加到路由
final userController = UserController();
FinchRoute(
key: 'users.index',
path: 'users',
methods: Methods.ONLY_GET,
controller: userController, // 调用 userController.index()
),
FinchRoute(
key: 'users.show',
path: 'users/{id}',
methods: Methods.ONLY_GET,
index: userController.show, // 调用一个特定的方法
),
controller 会使用其 index() 方法。index 接受一个 Future<String> Function()?——传入控制器中的某个方法引用即可调用不同的操作。
响应方法
所有响应方法都位于 rq 对象上:
| 方法 | 描述 |
|---|---|
rq.renderView(path: 'template/path') |
从 widgetsPath 渲染 Jinja 模板 |
rq.renderData(data: {...}) |
JSON 响应 |
rq.renderString(text: '...') |
纯文本响应 |
rq.renderHtml(html: '...') |
HTML 字符串响应 |
rq.renderTag(tag: Tag) |
渲染 Htmler Tag |
rq.renderError(404) |
标准错误响应 |
rq.redirect('/path') |
HTTP 重定向 |
rq.renderSSE(stream) |
Server-Sent Events 流 |
rq.renderSocket() |
WebSocket 握手占位符 |
renderView
Future<String> dashboard() async {
rq.addParams({
'title': 'Dashboard',
'user': currentUser,
});
return rq.renderView(path: 'pages/dashboard');
// 加载路径:widgetsPath/pages/dashboard.{widgetsType}
}
renderData (JSON)
Future<String> apiUsers() async {
var users = await UserCollection().getAll();
return rq.renderData(data: {'users': users.map((u) => u.toJson()).toList()});
}
renderError
Future<String> notFound() async {
return rq.renderError(404);
}
读取请求数据
// 读取 GET 或 POST 字段
var name = rq.get<String>('name', def: 'anonymous');
var age = rq.get<int>('age', def: 0);
// 读取来自 {id} 的路径参数
var id = rq.getParam('id');
// 检查请求方法
if (rq.isPost) { ... }
if (rq.method == Methods.DELETE) { ... }
// API 端点?(路径以 /api/ 开头)
bool isApi = rq.isApiEndpoint;
向模板传递数据
Future<String> show() async {
var user = await UserCollection().findById(rq.getParam('id'));
// addParam / addParams 使数据在 Jinja 模板中可用
rq.addParams({
'user': user?.toJson(),
'title': 'User Profile',
});
return rq.renderView(path: 'user/show');
}
在模板中:
<h1>{{ user.name }}</h1>
访问其他控制器
控制器就是普通的 Dart 对象。在顶层实例化它们并共享使用:
final authController = AppAuthController();
final homeController = HomeController();
// 在 AuthController.loginPost() 中:
return homeController.renderView('example/form');