Flutter书架管理插件shelf_plus的使用
Flutter书架管理插件shelf_plus的使用
概述
Shelf Plus 是一个用于服务器端开发的质量提升插件,基于 Shelf 平台。它提供了快速启动应用程序的能力,并且与 Shelf 生态系统完全兼容。Shelf Plus 包含了零配置初始化、内置热重载以及强大的路由增强功能。
快速开始
简单示例
import 'package:shelf_plus/shelf_plus.dart';
void main() => shelfRun(init);
Handler init() {
var app = Router().plus;
app.get('/', () => 'Hello World!');
return app.call;
}
路由增强 (Router Plus)
基本用法
var app = Router().plus;
app.use(middleware());
app.get('/text', () => 'I am a text');
app.get('/html/<name>', (Request request, String name) => '<h1>Hello $name</h1>',
use: typeByExtension('html'));
app.get('/file', () => File('path/to/file.zip'));
app.get('/person', () => Person(name: 'John', age: 42));
处理返回值 (ResponseHandler)
Shelf Plus 提供了一个强大的 ResponseHandler
机制,可以处理多种类型的返回值:
返回类型 | 使用场景 |
---|---|
String |
响应文本(text/plain) |
Uint8List , Stream<List<int>> |
响应二进制数据(application/octet-stream) |
Map<String, dynamic> , List<dynamic> |
响应 JSON 数据(application/json) |
任何具有 toJson() 方法的类 |
序列化支持 |
File |
响应文件内容 |
WebSocketSession |
创建 WebSocket 连接 |
Handler |
处理 Shelf 中间件或处理器 |
示例代码
import 'dart:io';
import 'package:shelf_plus/shelf_plus.dart';
void main() => shelfRun(init);
Handler init() {
var app = Router().plus;
app.get('/text', () => 'a text');
app.get('/binary', () => File('data.zip').openRead());
app.get('/json', () => {'name': 'John', 'age': 42});
app.get('/class', () => Person('Theo'));
app.get('/list-of-classes', () => [Person('Theo'), Person('Bob')]);
app.get('/iterables', () => [1, 10, 100].where((n) => n > 9));
app.get('/handler', () => typeByExtension('html') >> '<h1>Hello</h1>');
app.get('/file', () => File('thesis.pdf'));
app.get('/websocket', () => WebSocketSession(
onOpen: (ws) => ws.send('Hello!'),
onMessage: (ws, data) => ws.send('You sent me: $data'),
onClose: (ws) => ws.send('Bye!'),
));
return app.call;
}
class Person {
final String name;
Person(this.name);
Map<String, dynamic> toJson() => {'name': name};
}
中间件 (Middleware)
使用中间件
var app = Router().plus;
app.use(middlewareA); // 应用于所有路由
// 应用于单个路由
app.get('/request1', () => 'response', use: middlewareB);
// 组合中间件
app.get('/request2', () => 'response', use: middlewareB + middlewareC);
在请求处理器中动态应用中间件
app.get('/request/<value>', (Request request, String value) {
return middleware(value) >> 'response';
});
请求体处理 (Request Body Handling)
解析请求体
app.post('/text', (Request request) async {
var text = await request.body.asString;
return 'You send me: $text';
});
app.post('/json', (Request request) async {
var person = Person.fromJson(await request.body.asJson);
return 'You send me: ${person.name}';
});
自定义访问器 (Custom Accessors)
extension PersonAccessor on RequestBodyAccessor {
Future<Person> get asPerson async => Person.fromJson(await asJson);
}
app.post('/person', (Request request) async {
var person = await request.body.asPerson;
return 'You send me: ${person.name}';
});
Shelf Run
启动服务器
import 'package:shelf_plus/shelf_plus.dart';
void main() => shelfRun(init);
Handler init() {
return (Request request) => Response.ok('Hello!');
}
自定义配置
void main() => shelfRun(init, defaultBindPort: 3000);
多线程支持
import 'dart:isolate';
import 'package:shelf_plus/shelf_plus.dart';
void main() {
const numberOfIsolates = 8;
for (var i = 0; i < numberOfIsolates - 1; i++) {
Isolate.spawn(spawnServer, null, debugName: i.toString()); // isolate 0..7
}
spawnServer(null); // use main isolate as the 8th isolate
}
void spawnServer(_) => shelfRun(init, defaultShared: true);
Handler init() {
var app = Router().plus;
app.get('/', () async {
await Future.delayed(Duration(milliseconds: 500)); // simulate load
return 'Hello from isolate: ${Isolate.current.debugName}';
});
return app.call;
}
示例
启用 CORS
import 'package:shelf_cors_headers/shelf_cors_headers.dart';
import 'package:shelf_plus/shelf_plus.dart';
void main() => shelfRun(init);
Handler init() {
final router = Router().plus;
router.get('/', () => {'data': 'This API is CORS enabled.'});
return corsHeaders() >> router.call;
}
REST 服务
import 'dart:io';
import 'package:shelf_plus/shelf_plus.dart';
import 'person.dart';
void main() => shelfRun(init);
final data = <Person>[
Person(firstName: 'John', lastName: 'Doe', age: 42),
Person(firstName: 'Jane', lastName: 'Doe', age: 43),
];
Handler init() {
var app = Router().plus;
app.get('/', () => File('frontend/page.html'));
app.get('/person', () => data);
app.get('/person/<id>', (Request request, String id) => data.where((person) => person.id == id));
app.post('/person', (Request request) async {
var newPerson = await request.body.as(Person.fromJson);
data.add(newPerson);
return {'ok': 'true', 'person': newPerson.toJson()};
});
app.put('/person/<id>', (Request request, String id) async {
data.removeWhere((person) => person.id == id);
var person = await request.body.as(Person.fromJson);
person.id = id;
data.add(person);
return {'ok': 'true'};
});
app.delete('/person/<id>', (Request request, String id) {
data.removeWhere((person) => person.id == id);
return {'ok': 'true'};
});
return app.call;
}
WebSocket 聊天服务器
import 'dart:io';
import 'package:shelf_plus/shelf_plus.dart';
void main() => shelfRun(init);
Handler init() {
var app = Router().plus;
app.get('/', () => File('public/html_client.html'));
var users = <WebSocketSession>[];
app.get('/ws', () => WebSocketSession(
onOpen: (ws) {
users.add(ws);
users.where((user) => user != ws).forEach((user) => user.send('A new user joined the chat.'));
},
onClose: (ws) {
users.remove(ws);
for (var user in users) {
user.send('A user has left.');
}
},
onMessage: (ws, dynamic data) {
for (var user in users) {
user.send(data);
}
},
));
return app.call;
}
通过以上内容,您可以快速上手并充分利用 shelf_plus
插件的强大功能来构建高效的服务端应用。
更多关于Flutter书架管理插件shelf_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter书架管理插件shelf_plus
的示例代码案例。这个插件假设是用来管理书籍的添加、删除和展示等基本功能。请注意,shelf_plus
是一个假设的插件名称,实际中你可能需要找到一个真实存在的插件或自己实现这些功能。
首先,确保你的Flutter项目中已经添加了shelf_plus
插件。你可以在pubspec.yaml
文件中添加依赖项:
dependencies:
flutter:
sdk: flutter
shelf_plus: ^x.y.z # 替换为实际的版本号
然后运行flutter pub get
来安装依赖。
接下来是一个简单的Flutter应用示例,展示如何使用shelf_plus
插件来管理书架上的书籍。
main.dart
import 'package:flutter/material.dart';
import 'package:shelf_plus/shelf_plus.dart'; // 假设这是插件的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Shelf Management',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ShelfManagerScreen(),
);
}
}
class ShelfManagerScreen extends StatefulWidget {
@override
_ShelfManagerScreenState createState() => _ShelfManagerScreenState();
}
class _ShelfManagerScreenState extends State<ShelfManagerScreen> {
final ShelfPlusController _shelfController = ShelfPlusController();
final TextEditingController _titleController = TextEditingController();
@override
void initState() {
super.initState();
// 初始化书架数据,可以从本地存储或远程服务器加载
_shelfController.initialize();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Book Shelf Manager'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _titleController,
decoration: InputDecoration(labelText: 'Book Title'),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () async {
// 添加书籍到书架
String title = _titleController.text;
if (title.isNotEmpty) {
await _shelfController.addBook(title);
_titleController.clear();
setState(() {}); // 刷新UI以显示新书
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Book title cannot be empty')),
);
}
},
child: Text('Add Book'),
),
SizedBox(height: 16),
Expanded(
child: ListView.builder(
itemCount: _shelfController.bookCount,
itemBuilder: (context, index) {
Book book = _shelfController.getBookAtIndex(index);
return Dismissible(
key: Key(book.id),
onDismissed: (direction) async {
// 从书架中删除书籍
await _shelfController.removeBook(book.id);
setState(() {}); // 刷新UI以删除书籍
},
background: Container(color: Colors.red, alignment: Alignment.centerRight, child: Icon(Icons.delete)),
child: ListTile(
title: Text(book.title),
),
);
},
),
),
],
),
),
);
}
}
// 假设的Book类
class Book {
String id;
String title;
Book({required this.id, required this.title});
}
// 假设的ShelfPlusController类
class ShelfPlusController {
List<Book> _books = [];
int _nextId = 1;
// 初始化书架数据
Future<void> initialize() async {
// 这里可以从本地存储或远程服务器加载数据
// 示例:_books = await fetchBooksFromLocalStorage();
}
// 添加书籍到书架
Future<void> addBook(String title) async {
String id = 'book_$_nextId';
_nextId++;
_books.add(Book(id: id, title: title));
// 这里可以保存数据到本地存储或远程服务器
// 示例:await saveBookToLocalStorage(Book(id: id, title: title));
}
// 从书架中删除书籍
Future<void> removeBook(String id) async {
_books.removeWhere((book) => book.id == id);
// 这里可以删除数据从本地存储或远程服务器
// 示例:await deleteBookFromLocalStorage(id);
}
// 获取书架上的书籍数量
int get bookCount => _books.length;
// 根据索引获取书籍
Book getBookAtIndex(int index) {
return _books[index];
}
}
在这个示例中,我们创建了一个简单的Flutter应用,它使用了一个假设的ShelfPlusController
类来管理书架上的书籍。用户可以在输入框中输入书籍标题,然后点击“Add Book”按钮将书籍添加到书架。书架上的每本书籍都可以通过滑动来删除。
请注意,这个示例中的ShelfPlusController
类和Book
类都是假设的,实际中你可能需要根据你的具体需求和插件API来实现这些功能。此外,数据持久化(如保存到本地存储或远程服务器)的部分也需要根据你的具体需求来实现。