Flutter书架管理插件shelf的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter书架管理插件shelf的使用

简介

pub package package publisher

Shelf 是一个用于创建和组合Web服务器及Web服务器组件的库,它使得在Dart中构建HTTP中间件变得简单。通过暴露少量简单的类型,将服务器逻辑映射到简单的函数中,并支持同步和异步处理,以及灵活地返回字符串或字节流。

有关更多Dart HTTP服务器文档,请参阅Dart HTTP server documentation。你也可以查看pacakge:shelf_routerpackage:shelf_static,它们是基于并扩展package:shelf的包。

示例代码

以下是一个简单的Shelf服务器示例:

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;

void main() async {
  // 创建一个处理器,它会记录所有请求的日志,然后回显请求的URL。
  var handler = const Pipeline()
      .addMiddleware(logRequests())
      .addHandler(_echoRequest);

  // 启动服务器,监听localhost:8080端口。
  var server = await shelf_io.serve(handler, 'localhost', 8080);

  // 启用内容压缩
  server.autoCompress = true;

  print('Serving at http://${server.address.host}:${server.port}');
}

// 定义一个处理器函数,它接收一个请求并返回一个响应。
Response _echoRequest(Request request) =>
    Response.ok('Request for "${request.url}"');

Handlers 和 Middleware

  • Handler:任何处理Request并返回Response的函数。它可以自己处理请求(例如静态文件服务器)或者进行一些处理后转发给另一个处理器(例如日志记录器)。
  • Middleware:一种特殊的处理器,它接受一个处理器并包装成另一个处理器以提供额外的功能。通常,Shelf应用程序由多层中间件组成,最内层是一个或多个处理器,Pipeline类简化了这种应用的构建。

Adapters

适配器是创建Request对象、将它们传递给处理器并处理返回的Response的代码。大多数情况下,适配器从底层HTTP服务器转发请求和响应;shelf_io.serve就是这种适配器。适配器还可能在浏览器中合成HTTP请求,或直接从HTTP客户端管道化请求到Shelf处理器。

API Requirements

适配器必须处理处理器的所有错误,包括返回null响应的情况。适配器应尽可能打印每个错误到控制台,然后像处理器返回500响应一样处理。如果适配器知道自己的URL,则应实现Server接口。

Request Requirements

当实现适配器时,需要遵循一些规则。适配器不应传递urlhandlerPath参数给Request,只应传递requestedUri。如果传递context参数,则所有键必须以适配器的包名加点号开头。如果收到多个同名头,则应根据RFC 2616第4.2节将其合并为一个以逗号分隔的头。

Response Requirements

适配器不应添加或修改任何实体头。如果以下条件均不成立,则适配器应应用分块传输编码并将Transfer-Encoding头设置为chunked

  • 状态码小于200,或等于204或304。
  • 提供了Content-Length头。
  • Content-Type头表示MIME类型为multipart/byteranges
  • Transfer-Encoding头设置为除identity以外的其他值。

适配器可以在响应的Server头中包含关于自身的信息,默认情况下,如果处理器返回的响应设置了Server头,则应优先考虑该头。适配器应在处理器返回响应时包含带有时间戳的Date头,如果处理器返回的响应设置了Date头,则应优先考虑该头。

Inspiration

Shelf受到了以下项目的启发:

完整示例Demo

为了更好地理解如何使用Shelf,下面提供了一个更完整的示例,包括路由和静态文件服务:

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_router/shelf_router.dart';
import 'package:shelf_static/shelf_static.dart';

void main() async {
  // 创建路由器实例
  final router = Router();

  // 定义路由
  router.get('/hello', (Request req) => Response.ok('Hello, World!'));
  router.get('/echo/<path>', (Request req, String path) => Response.ok('Echo: $path'));

  // 创建静态文件处理器
  final staticHandler = createStaticHandler('static/', defaultDocument: 'index.html');

  // 创建处理器管道
  var handler = const Pipeline()
      .addMiddleware(logRequests()) // 记录所有请求
      .addHandler((Request request) {
        // 尝试匹配路由
        var response = router(request);
        if (response == null) {
          // 如果没有匹配到路由,则尝试作为静态文件处理
          response = staticHandler(request);
        }
        return response ?? Response.notFound('Not Found');
      });

  // 启动服务器
  var server = await shelf_io.serve(handler, 'localhost', 8080);

  // 启用内容压缩
  server.autoCompress = true;

  print('Serving at http://${server.address.host}:${server.port}');
}

在这个示例中,我们使用了shelf_router来定义路由,并使用shelf_static来提供静态文件服务。这样可以更清晰地分离不同类型的请求处理逻辑。


更多关于Flutter书架管理插件shelf的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter书架管理插件shelf的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成并使用shelf插件来管理书架的一个基本示例。请注意,shelf插件可能是一个虚构的插件名称,因为在实际Flutter生态系统中,并没有一个广泛知名的名为shelf的插件专门用于书架管理。不过,我会基于一个假设的插件API来展示如何集成和使用它。

首先,确保你已经在pubspec.yaml文件中添加了shelf插件的依赖(假设它存在):

dependencies:
  flutter:
    sdk: flutter
  shelf: ^1.0.0  # 假设的版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以按照以下步骤使用shelf插件来管理书架。

1. 导入插件

在你的Dart文件中导入shelf插件:

import 'package:shelf/shelf.dart';

2. 初始化书架管理

假设ShelfManagershelf插件提供的一个类,用于管理书架。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Shelf Manager',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ShelfHomeScreen(),
    );
  }
}

class ShelfHomeScreen extends StatefulWidget {
  @override
  _ShelfHomeScreenState createState() => _ShelfHomeScreenState();
}

class _ShelfHomeScreenState extends State<ShelfHomeScreen> {
  late ShelfManager shelfManager;

  @override
  void initState() {
    super.initState();
    // 初始化书架管理器
    shelfManager = ShelfManager();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('书架管理'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('添加书籍到书架'),
            ElevatedButton(
              onPressed: () {
                // 假设有一个方法用于添加书籍
                _addBookToShelf(context);
              },
              child: Text('添加书籍'),
            ),
            Text('查看书架中的书籍'),
            ElevatedButton(
              onPressed: () {
                // 假设有一个方法用于查看书架
                _viewShelf(context);
              },
              child: Text('查看书架'),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _addBookToShelf(BuildContext context) async {
    // 假设有一个Book类和一个添加到书架的方法
    Book book = Book(title: '示例书籍', author: '作者名');
    try {
      await shelfManager.addBook(book);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('书籍已添加到书架')),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('添加书籍失败: $e')),
      );
    }
  }

  Future<void> _viewShelf(BuildContext context) async {
    try {
      List<Book> books = await shelfManager.getBooks();
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => ShelfViewScreen(books: books)),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('查看书架失败: $e')),
      );
    }
  }
}

class Book {
  String title;
  String author;

  Book({required this.title, required this.author});
}

class ShelfViewScreen extends StatelessWidget {
  final List<Book> books;

  ShelfViewScreen({required this.books});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('书架'),
      ),
      body: ListView.builder(
        itemCount: books.length,
        itemBuilder: (context, index) {
          Book book = books[index];
          return ListTile(
            title: Text(book.title),
            subtitle: Text(book.author),
          );
        },
      ),
    );
  }
}

3. 假设的ShelfManager

由于shelf插件是假设的,这里提供一个假设的ShelfManager类实现,用于展示如何管理书架。在实际使用中,你需要根据shelf插件的实际API来实现。

import 'dart:async';

class ShelfManager {
  // 假设的书架存储
  List<Book> _books = [];

  // 添加书籍到书架
  Future<void> addBook(Book book) async {
    _books.add(book);
    // 这里可以添加保存到数据库或远程服务器的逻辑
    await Future.delayed(Duration.zero); // 模拟异步操作
  }

  // 获取书架中的书籍
  Future<List<Book>> getBooks() async {
    // 这里可以添加从数据库或远程服务器加载书籍的逻辑
    await Future.delayed(Duration.zero); // 模拟异步操作
    return _books;
  }
}

这个示例展示了如何在Flutter应用中集成并使用一个假设的shelf插件来管理书架。在实际应用中,你需要根据shelf插件的实际API和文档来调整代码。

回到顶部