软件技术学习笔记

个人博客,记录软件技术与程序员的点点滴滴。

Dart实现一个HTTP服务

这段时间使用Flutter写一个移动客户端,也学习一下Dart语言。Dart语言也是类C高级编程语言,在熟悉C++或Java的基础上,非常容易上手。

Dart也可以写服务端程序,于是写一个小小的后端服务给移动端使用。虽然其性能比不上GoLang、生态系统不及NodeJS,自己学习语法时玩玩也不错。

1. 实现一个书籍管理列表

创建项目命令:dart create -t console-full dart_demo_server

编辑lib/dart_demo_server.dart文件:

// lib/dart_demo_server.dart
import 'package:json_annotation/json_annotation.dart';

part 'dart_demo_server.g.dart';

@JsonSerializable()
class Book {
  int id;
  String name;
  double price;

  Book(this.id, this.name, this.price);

  factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);

  Map<String, dynamic> toJson() => _$BookToJson(this);
}

class BookStore {
  List<Book> books = [
    Book(1, 'A-1', 10),
    Book(2, 'A-2', 16),
    Book(3, 'A-3', 28),
  ];

  int addBook(String name, double price) {
    var id = books.isNotEmpty ? books.last.id + 1 : 1;
    books.add(Book(id, name, price));
    return id;
  }

  void deleteBook(int id) {
    books.removeWhere((book) => book.id == id);
  }

  List<Book> getBooks() {
    return books;
  }
}

2. 提供HTTP服务

import 'dart:convert';
import 'dart:io';

import 'package:dart_demo_server/dart_demo_server.dart';

Future main() async {
  var server = await HttpServer.bind(
    InternetAddress.anyIPv4,
    18080,
  );

  print('Listening on localhost:${server.port}');

  var store = BookStore();

  await for (HttpRequest request in server) {

    if (request.method == 'GET') {
      request.response.headers.contentType = ContentType.json;
      request.response.write(jsonEncode(store.getBooks()));
    } else if (request.method == 'POST') {
      var queries = request.uri.queryParameters;
      var newId = store.addBook(queries['name'], double.parse(queries['price']));
      request.response.headers.contentType = ContentType.json;
      request.response.write(jsonEncode(newId));
    } else if (request.method == 'DELETE') {
      var id = int.parse(request.uri.queryParameters['id']);
      store.deleteBook(id);
      request.response.headers.contentType = ContentType.json;
      request.response.write(jsonEncode(id));
    }

    await request.response.close();
  }
}

3. 生成JSON转换代码

JSON转换使用json_serializable,在pubspec.yaml中添加json_annotation、build_runner、json_serializable,内容如下:

# pubspec.yaml
name: dart_demo_server
description: A sample command-line application.
environment:
  sdk: '>=2.8.1 <3.0.0'

dependencies:
  json_annotation: ^3.0.0

dev_dependencies:
  pedantic: ^1.9.0
  test: ^1.14.4
  build_runner: ^1.0.0
  json_serializable: ^3.0.0

修改pubspec.yaml之后,拉取新包命令dart pub get

代码适配为lib/dart_demo_server.dart中这几行代码:

part 'dart_demo_server.g.dart';

@JsonSerializable()
class Book {
  factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);

  Map<String, dynamic> toJson() => _$BookToJson(this);
}

生成命令dart pub run build_runner buildflutter pub run build_runner build。将自动生成 lib/dart_demo_server.g.dart 文件。

4. 构建

执行命令:dart compile exe .\bin\dart_demo_server.dart

5. 验证

打开 .\bin\dart_demo_server.exe,使用REST Client验证:

###
POST http://localhost:18080/?name=B-2&price=22.36

###
DELETE http://localhost:18080/?id=2

###
GET http://localhost:18080/