我以为后端就是web后端,后来我才知道这叫服务(器)端。
我以为后端就是黑窗程序,现在我明白它是一种特别的存在。
从基础的dart:io开始
安装环境
参考flutter环境的安装,flutter会自带的安装上dart最新版本
项目构建
作为一个flutter项目,你将会执行以下命令:
flutter create projuct_name --org com.xxxdomain -a kotlin -i swift --version 0.0.1 --description "this is a flutter projuct description."
一般不会真的输入完整的命令,这里解释一下
`create` 后面默认带了一个 `--project-name` 的参数用于指定项目名字,所以这里直接跟了一个 `projuct_name` ,注意:这个项目名一定是符合dart的包名的格式的蛇形命名法`--org` 后跟域名,最好符合安卓软件包名规范。一般会指定域名,默认是 `com.example``-a -i` 用于指定安卓和iOS下的技术栈,可以通过--help查看默认类型,然后根据需求来指定技术栈。`--version` 默认是 1.0.0 但是我喜欢从 0.0.1 开始`--description` 后期可以改,没有必要在这里写
所以最后只剩下
flutter create projuct_name --org com.lilua --version 0.0.1
那么作为一个dart项目,也是很乖巧的和flutter神似,这是我没想到,但是又在情理之中的。
dart create projuct_name
并且dart的默认不带版本号,可以自己在 pubspec.yaml 文件中去设置
执行一个dart项目
dart run
或者单独执行某一个dart文件
dart bin/xx_module.dart
调试dart项目
dart是一个支持JIT的语言,可以实时热更新,也可以AOT编译好了再执行,提高运行效率。
参考https://www.jianshu.com/p/9567f798a353可以得到一个服务端热重载的实例。
调试和其他语言无异。打断点然后debug即可。
服务端 hello wold
将以下代码复制到main.dart里替换原来的代码。
import 'dart:io';void main() async {var requestServer = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);print('监听 localhost 地址,端口号为${requestServer.port}');//监听请求await for (HttpRequest request in requestServer) {//监听到请求后response回复它一个Hello World!然后关闭这个请求var httpResponse = request.response..write('Hello World!');await httpResponse.close();}}
然后在浏览器中输入 http://localhost:8080/ 就可以看到我们的第一个后端程序结果。
原理
一个简单的请求做完了,我们来看看发生了什么
从main函数进来,后面跟了一个async表示这是一个异步的函数(异步自己补习吧)
通过 HttpServer.bind 来绑定一个本地的8080端口作为请求的路口。
通过await for来解决异步获取到的每一个请求,他们会装在 requestServer 里,一个个的拿给 request 做请求的回复。
执行close结束请求。建议直接在拿到结果后直接切断请求,不要挂着导致多次请求堆叠起来。
(不明白的,直接评论区见,反正我没考虑零基础,毕竟没有出零基础的dart入门)
注意事项
尽量使用自己手敲 dart run 这个不会出问题。次之,你可以使用 vscode 的 runner 但是你也看得出来那是运行单文件的。千万避免使用vscode右上角的运行按钮,到时候运行到后台还没法点退出,需要手动在任务管理器中杀掉。
做得更加安全
为了避免其他类型的请求干扰,我们手动屏蔽掉他们。
import 'dart:io';/// 对请求分类处理void handleMessage(HttpRequest request) {// 方便后期维护try {if (request.method == 'GET') {handleGet(request);} else if (request.method == 'POST') {handlePost(request);} else {// 返回错误的请求request.response..statusCode = HttpStatus.methodNotAllowed..write('have not ${request.method} method!!!')..close();}} catch (e) {print('get a $e');}}/// 单独处理postvoid handlePost(HttpRequest request) {/// 语法糖,..表示直接引用原来的对象来继续执行方法,可以连续执行多个方法。request.response..write('post')..write('something')..close();}/// 单独处理getvoid handleGet(HttpRequest request) {request.response..write('get')..close();}void main() async {var requestServer = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);//HttpServer.bind(主机地址,端口号)//主机地址:InternetAddress.loopbackIPv4和InternetAddress.loopbackIPv6都可以监听到print('监听 localhost地址,端口号为${requestServer.port}');//监听请求await for (HttpRequest request in requestServer) {handleMessage(request);}}
对于请求结果的状态值:
abstract class HttpStatus {//继续static const int continue_ = 100;//交换协议static const int switchingProtocols = 101;//可以static const int ok = 200;//已创建static const int created = 201;//认可的static const int accepted = 202;//非授权信息static const int nonAuthoritativeInformation = 203;//没有内容static const int noContent = 204;//重置内容static const int resetContent = 205;//部分内容static const int partialContent = 206;//多项选择static const int multipleChoices = 300;//永久迁移static const int movedPermanently = 301;//已发现static const int found = 302;//临时迁移static const int movedTemporarily = 302; // Common alias for found.//查看其它static const int seeOther = 303;//未修改的static const int notModified = 304;//使用代理static const int useProxy = 305;//暂时重定向static const int temporaryRedirect = 307;//请求失败static const int badRequest = 400;//没有授权static const int unauthorized = 401;//要求付款static const int paymentRequired = 402;//被禁止static const int forbidden = 403;//未找到static const int notFound = 404;//请求方法不允许static const int methodNotAllowed = 405;//不接受static const int notAcceptable = 406;//需要代理身份认证static const int proxyAuthenticationRequired = 407;//请求超时static const int requestTimeout = 408;//冲突static const int conflict = 409;//过去了static const int gone = 410;//长度要求static const int lengthRequired = 411;//先决条件失败static const int preconditionFailed = 412;//请求实体过大static const int requestEntityTooLarge = 413;//请求地址过长static const int requestUriTooLong = 414;//非支持的媒体类型static const int unsupportedMediaType = 415;//请求范围不可满足static const int requestedRangeNotSatisfiable = 416;//期望失败static const int expectationFailed = 417;//升级要求static const int upgradeRequired = 426;//内部服务器错误static const int internalServerError = 500;//未实现static const int notImplemented = 501;//网关坏了static const int badGateway = 502;//服务不可用static const int serviceUnavailable = 503;//网关超时static const int gatewayTimeout = 504;//http版本不支持static const int httpVersionNotSupported = 505;// 连接超时static const int networkConnectTimeoutError = 599;}
可以直接点进 HttpStatus 类里面看看它的实现,dart易学在于,官方代码注释非常漂亮。
从uri中拿到参数
例如:http://localhost:8080/?id=4234
我们修改一下 handleGet 函数
void handleGet(HttpRequest request) {var value = request.uri.queryParameters['id'];request.response..write('get id is $value')..close();}
就是这样简单,使用 request.uri 拿到地址,使用 queryParameters 来匹配id。这样就拿到了传入的值
