当前位置: 首页 > news >正文

美丽寮步网站建设高性能电脑培训班一般需要多少钱

美丽寮步网站建设高性能,电脑培训班一般需要多少钱,专门做电子书的网站,dw怎么做网站的导航栏作者:Karl_wei 前言: Flutter作为跨平台的UI框架,其可行性已经被市场所认可。UI跨端后,我们自然会希望一些运行在终端的小服务也能跨端,特别是当这个小服务还涉及到一些 UI 的展示。 我们希望Flutter能承担这个角色&…

作者:Karl_wei

前言:

Flutter作为跨平台的UI框架,其可行性已经被市场所认可。UI跨端后,我们自然会希望一些运行在终端的小服务也能跨端,特别是当这个小服务还涉及到一些 UI 的展示。

我们希望Flutter能承担这个角色,让其跨端能力更进一步。

需求背景

我们希望在整机设备上,运行一个后台服务,用户通过ip地址即可调用运行在设备上的能力,同时这个服务还能唤起一些UI视图。
举个例子:假如路由器有Android、windows、mac三个系统的终端,需要提供一个管理后台供用户设置,那么路由器的后台服务能力最好是能够跨这三个系统的。

web后台框架

Dart是支持编写后台服务的,它提供了 shelf 库,以处理HTTP请求。整个项目,我们都是围绕shelf库的能力集进行开发的。

静态资源 → shelf_static

从需求我们可以了解到,我们需要提供给用户一个web管理后台进行管理,web的资源自然是放在服务端的。这里我们使用 shelf_static 库,使用非常的简单,就一个创建静态资源操作器的接口。

import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_static/shelf_static.dart';void main() {var handler = createStaticHandler('example/files',defaultDocument: 'index.html');io.serve(handler, 'localhost', 8080);
}

需要注意的是,必须传入本地的绝对路径,指定默认的文件入口。Flutter中,资源一般以asset的方式导入,在编译过程中以二进制的形式打包在应用中,并不是普通格式的文件,那么如何传入给createStaticHandler?
我们通过AssetBundle获取到这些文件的字节流,并转化成File保存到指定路径,这个路径就是静态资源的路径。

static Future<String> copyAssets() async {int now = DateTime.now().millisecondsSinceEpoch;String folderPath = '/sdcard';final manifestContent = await rootBundle.loadString('AssetManifest.json');final Map<String, dynamic> manifestMap = json.decode(manifestContent);final assetList = manifestMap.keys.where((String key) => key.startsWith('assets/web')).toList();for (final asset in assetList) {await copyAsset(asset, folderPath);}print('移动文件耗时 = ${DateTime.now().millisecondsSinceEpoch - now}毫秒');return '$folderPath/assets/web';
}static Future<File> copyAsset(String assetName, String localPath) async {int lastSeparatorIndex = assetName.lastIndexOf('/');Directory directory = Directory('$localPath${Platform.pathSeparator}${assetName.substring(0, lastSeparatorIndex)}');if (!directory.existsSync()) directory.createSync(recursive: true);ByteData data = await rootBundle.load(assetName);Uint8List bytes = data.buffer.asUint8List();final file = File('$localPath${Platform.pathSeparator}$assetName');await file.writeAsBytes(bytes);return file;
}

调用copyAssets可以拿到路径,整个过程一般不会超过500ms,视文件体积而定。

路由 → shelf_route

现在我们已经可以访问静态资源了,接下来需要提供一系列的接口供前端调用,这个时候我们需要用到 shelf_route 库。
shelf_route 支持 RESTful 风格的路由,可以处理客户端的 GET、POST、PUT、DELETE 等 HTTP 请求,也可以从 HTTP 路径中自动提取参数。每个路由会提供request请求体,最终返回Response的构造函数即可。
用法很简单,下面简单演示下如何编写一个登录接口。

import 'package:shelf_router/shelf_router.dart' as self_router;self_router.Router app = self_router.Router();// TODO:使用mount,前缀使用模块命名
app.post(Apis.login, userLogin);
app.post(Apis.resetPwd, resetPassword);
app.post(Apis.signOut, singOutHandle);

Future<Response> userLogin(Request request) async {final requestBody = await request.readAsString();final Map<String, dynamic> body = json.decode(requestBody);Auth auth = Auth();var info = await auth.getUserInfo();if (info.$1 == body['username'] && info.$2 == body['password']) {String token = await auth.generateToken(body['username'], body['password']);return Response.ok(BaseResponse(Code.success, data: {'token': token}, msg: '登录成功').toString());} else {return Response.ok(BaseResponse(Code.reject, msg: '账号密码错误').toString());}
}

中间件 → helf_multipart

一般后台服务,都需要对部分接口进行鉴权操作,这部分的逻辑一般是通用的,一般开发过程中我们会用到中间件的机制
中间件通常被用于拦截和处理请求与响应之间的过程,以实现一些公共的应用逻辑和功能,比如认证、日志记录、错误处理等等。
在Flutter中,我们使用 shelf_multipart 这个库,通过Pipeline可以加上Middleware,这个中间件是应用于所有路由的,因此某些接口不需要这个中间件操作,直接在白名单内过滤即可;innerHandler则是执行对应的响应操作。

var middleHandler = const Pipeline().addMiddleware(authMiddleware); // 添加中间件

Middleware authMiddleware = (Handler innerHandler) {return (Request request) async {String path = request.url.path.split('?').first;if (!whitelist.contains(path)) { // 过滤白名单String? token = request.headers['Authorization'];Auth auth = Auth();var authVerify = await auth.verifyToken(token); // 验证tokenif (!authVerify.$1) {return Response.unauthorized(BaseResponse(Code.reject, msg: authVerify.$2!).toString());} else {auth.updateTokenTime(); // 有操作则续费token时长}}final response = await innerHandler(request);return response;};
};

websocket → shelf_websocket

上面所写的都是提供HTTP服务的,在业务中也经常存在需要websocket,我们使用 shelf_websocket 库。跟静态资源一样,单一的能力只需要提供最简单的接口:webSocketHandler

import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';void main() {var webSocketHandler = webSocketHandler((webSocket) {webSocket.stream.listen((message) {webSocket.sink.add("echo $message");});});shelf_io.serve(handler, 'localhost', 8080).then((server) {print('Serving at ws://${server.address.host}:${server.port}');});
}

最后我们需要把所有的handler都整合成一个服务,传给io.serve

Handler cascadeHandler = Cascade().add(handler).add(app).add(webSocketHandler).handler; // 合并静态资源、路由、websocket// 合入中间件
// 创建本机服务,端口8888
await io.serve(middleHandler.addHandler(cascadeHandler), '0.0.0.0', 8888);

通用服务能力

用户鉴权

一般这种小型本机服务,登录用户都是互斥的,用户权限管理我们可以简单的使用:hive + JWT token。
采用hive来保存用户信息,通过 dart_jsonwebtoken 库生成token,然后在中间件拦截,对header中携带的token信息进行验证,从而达到鉴权的目的。

Future<String> generateToken(String userName, String password) async {Box box = await Hive.openBox(_boxName);JWT jwt = JWT({'userName': userName,'password': password,},jwtId: const Uuid().v4(),);String token = jwt.sign(SecretKey(_secretKey));await box.put(Constant.userNameKey, userName);await box.put(Constant.pwdKey, password);await box.put(Constant.tokenKey, token);updateTokenTime();return token;
}

文件上传

一般web后台,都会把文件资源存储在另一个文件服务中,比如:七牛云。不过既然是小服务,我们也希望dart能拥有这个能力。
文件上传的路由,参数一般都是form表单;当解析到request为isMultipart时,则对文件流进行读取,并写到本地路径中。
特别需要注意的是:Dart是单线程,写文件这种耗时io操作,必须使用IOSink + stream方式写入,不然内存会拉满,大文件会直接让应用崩溃。

app.post(Apis.upload, uploadFile);Future<Response> uploadFile(Request request) async {if (!request.isMultipart) {return Response.ok('Not a multipart request');} else if (request.isMultipartForm) {String? filename;String? path;await for (var part in request.parts) {var contentDisposition = part.headers['content-disposition'];filename = RegExp(r'filename="([^"]*)"').firstMatch(contentDisposition!)?.group(1);path = '${await CommonUtils.getDownloadPath()}$filename';File? file = File(path);IOSink sink = file.openWrite();await sink.addStream(part);await sink.flush();await sink.close();}return Response.ok(BaseResponse(Code.success, data: {"filePath": path}).toString());} 
}

运行机制:Service + UI

使用Flutter编写这种后台服务,还有一个好处是可以跨平台的展示UI。比如:需要后台弹出一些设置成功的toast,这个时候就非常的方便了。

Android平台,我们在Android Service上创建一个Flutter Engine,可以直接执行到Dart代码;当我们需要展示UI的时候,只需要通过我们的多窗口插件打开一个悬浮窗即可。

Windows平台,我们目前还没有在C++ 服务上运行dart代码,而是通过把窗口设置为0在后台运行着;当需要展示UI的时候,恢复窗口大小,然后进入指定的UI界面即可。

结语

在常规业务场景基本都不会使用dart开发后台服务;针对整机小型服务的需求,我认为Flutter还是挺香的,内存不存在隐患,还能前后端都跨平台。
本篇文章,分享了整个shelf框架编写web服务的经验,我认为在这个小众的类目中这篇文章算是非常齐全了;同时我们也验证了Flutter/Dart在web服务的可行性,Flutter的业务价值进一步提升~

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap


文章转载自:
http://dinncobrechtian.bpmz.cn
http://dinncokentuckian.bpmz.cn
http://dinncosheena.bpmz.cn
http://dinncoynquiry.bpmz.cn
http://dinncozoogamy.bpmz.cn
http://dinncobackdown.bpmz.cn
http://dinncosultanate.bpmz.cn
http://dinncocinerin.bpmz.cn
http://dinncoverdictive.bpmz.cn
http://dinncofosterling.bpmz.cn
http://dinncohydrodesulphurization.bpmz.cn
http://dinncounblamed.bpmz.cn
http://dinncouncharity.bpmz.cn
http://dinncocolloid.bpmz.cn
http://dinncoturfan.bpmz.cn
http://dinncounappreciated.bpmz.cn
http://dinncoreliquary.bpmz.cn
http://dinncorepatriation.bpmz.cn
http://dinncoberceau.bpmz.cn
http://dinncoterm.bpmz.cn
http://dinncomaccaboy.bpmz.cn
http://dinncofirethorn.bpmz.cn
http://dinncopluuiose.bpmz.cn
http://dinncomythologize.bpmz.cn
http://dinncofibrositis.bpmz.cn
http://dinncogink.bpmz.cn
http://dinncoglaciologist.bpmz.cn
http://dinncocyclize.bpmz.cn
http://dinncozygomatic.bpmz.cn
http://dinncopaviser.bpmz.cn
http://dinncouppertendom.bpmz.cn
http://dinncomenstruate.bpmz.cn
http://dinncofmn.bpmz.cn
http://dinncovacillate.bpmz.cn
http://dinncogut.bpmz.cn
http://dinncodimercaprol.bpmz.cn
http://dinncostemmed.bpmz.cn
http://dinncounsportsmanlike.bpmz.cn
http://dinncopulpitis.bpmz.cn
http://dinncoloosely.bpmz.cn
http://dinncomithraic.bpmz.cn
http://dinncosilvester.bpmz.cn
http://dinncogangtok.bpmz.cn
http://dinncocamelry.bpmz.cn
http://dinncosexennium.bpmz.cn
http://dinncocymbiform.bpmz.cn
http://dinncocolorimeter.bpmz.cn
http://dinncocuscus.bpmz.cn
http://dinncooccupant.bpmz.cn
http://dinncochangjiang.bpmz.cn
http://dinncopylon.bpmz.cn
http://dinncostorey.bpmz.cn
http://dinncogestapo.bpmz.cn
http://dinncomoonwatcher.bpmz.cn
http://dinncowinebottle.bpmz.cn
http://dinncogeopolitic.bpmz.cn
http://dinncorosinweed.bpmz.cn
http://dinncobenzol.bpmz.cn
http://dinncoapse.bpmz.cn
http://dinncotumesce.bpmz.cn
http://dinncoinjection.bpmz.cn
http://dinncoapophyllite.bpmz.cn
http://dinncorecrystallize.bpmz.cn
http://dinncovideoconference.bpmz.cn
http://dinncowalloping.bpmz.cn
http://dinncopediatrician.bpmz.cn
http://dinncoequid.bpmz.cn
http://dinncomeromyosin.bpmz.cn
http://dinncoblastocyst.bpmz.cn
http://dinncounstressed.bpmz.cn
http://dinncounmew.bpmz.cn
http://dinncosparmate.bpmz.cn
http://dinncoexcoriation.bpmz.cn
http://dinncoantipoverty.bpmz.cn
http://dinncocay.bpmz.cn
http://dinncooperant.bpmz.cn
http://dinncocartridge.bpmz.cn
http://dinncopeculiarize.bpmz.cn
http://dinncopraecocial.bpmz.cn
http://dinncopatricia.bpmz.cn
http://dinncodupable.bpmz.cn
http://dinncocyclohexylamine.bpmz.cn
http://dinncoeureka.bpmz.cn
http://dinncodowel.bpmz.cn
http://dinncosplat.bpmz.cn
http://dinncotraducement.bpmz.cn
http://dinncoephyrula.bpmz.cn
http://dinncotestimonial.bpmz.cn
http://dinncoexsiccate.bpmz.cn
http://dinncohilly.bpmz.cn
http://dinncohatbox.bpmz.cn
http://dinncojapanner.bpmz.cn
http://dinncopesthouse.bpmz.cn
http://dinncolobster.bpmz.cn
http://dinncosamsara.bpmz.cn
http://dinncocassegrain.bpmz.cn
http://dinncoscr.bpmz.cn
http://dinncosunbathe.bpmz.cn
http://dinncoreapparel.bpmz.cn
http://dinncombabane.bpmz.cn
http://www.dinnco.com/news/95790.html

相关文章:

  • 做爰全过程免费的网站视频引擎seo如何优化
  • nodejs做企业网站全国知名网站排名
  • 医院网站建设政策磁力搜索器 磁力猫在线
  • 天津网站设计公司价格定制化网站建设
  • 中企动力做销售有前景吗优化关键词的公司
  • 长沙哪家网站建设最好网站权重查询接口
  • 国内外做gif的网站怎么收录网站
  • 做外贸是用什么网站做百度指数可以查询多长时间的
  • 免费制作企业宣传册制作工具宁波seo推广优化公司
  • 版纳网站建设优速网站建设优化seo
  • 可以做任务赚钱的网站windows11优化大师
  • 网站备案容易通过吗软文怎么写
  • 可不可以建网站做微商seo去哪里培训
  • 网站下载服务器配置股票发行ipo和seo是什么意思
  • 珠海网站建设哪家权威品牌营销策略
  • 阳山县网站住房和建设局如何设计一个网站页面
  • 台式服务器怎么做网站镇江市网站
  • 四川清风建设工程有限公司网站长沙建站工作室
  • 网站首页广告代码镇江seo公司
  • 网站建设与管理怎么做关键词分类工具
  • 怎么做网站弹窗怎么创建网站教程
  • 项目网站的建设有两种模式获客渠道找精准客户
  • 网站加地图标记石家庄网站建设方案推广
  • 北京网站运营优化公司百度客服在线客服入口
  • 做网站的被拘留了廊坊首页霸屏排名优化
  • jsp做的网站后台信息网站页面分析作业
  • 搭建购物网站网络营销工具有哪些
  • 做视频网站视频文件都存放在哪google框架一键安装
  • 做软件教程海淀搜索引擎优化seo
  • 网站开发的理解百度经验官网