首页
留言
导航
统计
Search
1
追番推荐!免费看动漫的网站 - 支持在线观看和磁力下载
3,170 阅读
2
推荐31个docker应用,每一个都很实用
1,508 阅读
3
PVE自动启动 虚拟机 | 容器 顺序设置及参数说明
1,055 阅读
4
一条命令,永久激活!Office 2024!
680 阅读
5
优选 Cloudflare 官方 / 中转 IP
540 阅读
默认分类
服务器
宝塔
VPS
Docker
OpenWRT
Nginx
群晖
前端编程
Vue
React
Angular
NodeJS
uni-app
后端编程
Java
Python
SpringBoot
SpringCloud
流程引擎
检索引擎
Linux
CentOS
Ubuntu
Debian
数据库
Redis
MySQL
Oracle
虚拟机
VMware
VirtualBox
PVE
Hyper-V
计算机
网络技术
网站源码
主题模板
登录
Search
标签搜索
Java
小程序
Redis
SpringBoot
docker
Typecho
Cloudflare
uni-app
docker部署
虚拟机
WordPress
群晖
CentOS
Vue
Java类库
Linux命令
防火墙配置
Mysql
脚本
Nginx
微醺
累计撰写
266
篇文章
累计收到
11
条评论
首页
栏目
默认分类
服务器
宝塔
VPS
Docker
OpenWRT
Nginx
群晖
前端编程
Vue
React
Angular
NodeJS
uni-app
后端编程
Java
Python
SpringBoot
SpringCloud
流程引擎
检索引擎
Linux
CentOS
Ubuntu
Debian
数据库
Redis
MySQL
Oracle
虚拟机
VMware
VirtualBox
PVE
Hyper-V
计算机
网络技术
网站源码
主题模板
页面
留言
导航
统计
搜索到
266
篇与
的结果
2023-02-14
专为折腾而生!老旧电脑安装PVE虚拟机保姆教程
专为折腾而生!老旧电脑安装 PVE 虚拟机保姆教程这几天玩VMware 虚拟机上瘾,感觉特别有意思。然而我其实并不满足于只是在这种软件层面上玩玩,而想挑战更高级的玩法,比如说玩玩可以安装在实体机上的虚拟机系统~~说直接点就是我想在我闲置多年的笔记本上折腾下虚拟机,让它继续发挥它的价值(简单来说我就是闲得慌~~)我其实早在很多年前就玩过同是 VMware 公司出的一款虚拟机系统,叫做【VMware vSphere Hypervisor】,简称【ESXi】,但是这个这个虚拟机主要是多用于企业级主机或者服务器上,所以在配置要求上比较高,我之前的笔记本虽说装上了,但是用起来非常卡顿,最主要的是,这个系统还是收费的,这对于我一个天天吃泡面酸菜的搬砖工,很明显是极不友好的。于是,我又找到了一个适合我们白 P 党练手的虚拟机系统,它就是今天要给大家展示的【Proxmox virtualization environment】系统,简称【PVE】。PVE 简介简单的说,PVE 是一个基于 Debian 的 linux 系统,内置了一套虚拟机管理工具,并提供了 web 管理页面,让我们可以非常简单的通过网页管理虚拟机。介绍:PVE 是专业的虚拟机平台,并且还是永久免费的开源平台。它提供一个家庭设备集中管理平台,你可以利用它安装任何你想要的系统,如 win 系统(Win7、10、PE、XP 等)、linux 系统(黑群晖、centos、路由 openwrt、ROS、LEDE、ubuntu 等),并且它还是一款在低配置的小主机上都能轻松运行的一款轻量级平台,可玩性非常高!一般来说,PVE 系统适合安装的环境非常多,不管是企业用户有工作站需求安装虚拟机平台,还是个人用户,有软路由或者小主机,都可以尝试安装 PVE 系统来拓展更多功能与玩法。所以今天我就教大家以闲置的的笔记本电脑来安装 PVE 系统,然后来挖掘它更多有意思的玩法。安装前的准备主机(笔记本)配置要求:CPU:64 位 CPU( Intel EMT64 或 AMD64),且支持 Intel VT/AMD-V 虚拟化,如果需要硬件直通,需要 CPU 支持 VD (b75 芯片组以上)内存:2GB 以上即可,如果同时运行的虚拟机很多,建议加大内存。硬盘:理论上 16G 以上硬盘即可,但是你后期安装的虚拟机系统肯定不止一个,所以越大越好。网卡:至少一个网口,多网口的更佳!如果是用网卡直通的,还要求使用 Intel 品牌的网卡。由此可见,目前市面上 99%的闲置电脑都可以顺利的安装到 PVE 虚拟机系统,除非你的机器拿去换不锈钢盘都没人收了。需要重点声明的是:等下安装 PVE 虚拟机系统会清空你的电脑硬盘,请务必提前做好备份,切记!!!软件准备:PVE 固件(镜像文件)官网链接:Download Proxmox software, documentation, agreements写盘工具(Ventoy,软碟通或者其它都可以,这里我以软碟通为例)软碟通官网下载:最新 UltraISO 官方免费下载 - UltraISO 软碟通中文官方网站其它:一个 8G 以上 U 盘,请务必备份好数据,等下安装会清空 U 盘,切记!!!安装操作步骤安装思路:下载最新 PVE 系统镜像,然后通过写盘工具(软碟通)写到准备好的 U 盘当中,在把写好的 U 盘插入需要安装 PVE 虚拟机系统的主机或者电脑的 USB 接口,开机进 BIOS,设置第一启动顺序,选择 U 盘启动,然后再将 U 盘上的系统文件写到主机或者电脑中。一句话概括就是:和我们安装 Windows 系统几乎一样!PVE 启动盘制作🔺 先在上面给出的 PEV 官网进行系统镜像下载,直接选择最前面的就是最新的系统镜像。如果你那边下载比较慢,建议选择后面一个带【BitTorrent】的文件来下载,使用种子下载软件(某雷,或者 Qb)基本是满速下载。🔺 然后就是将下载下来的镜像文件用软碟通写到 U 盘中。操作步骤其实很简单,之前演示过多次,这里就不再重复了。搞定之后就可以拔掉 U 盘,然后把它插到需要安装 PVE 系统的电脑中,进行安装操作了。PVE 虚拟机安装操作🔺 将写入 PVE 镜像的启动 U 盘插入需要安装 PVE 主机或者电脑的 USB 口上,然后按快捷键选择从 U 盘引导系统启动。🔺 选择默认的【Install Proxmox VE】进行安装🔺 安装 Proxmox VE 界面,不用管,数秒即可完成。🔺 说的啥咱也看不懂,直接点击右下角的【I agree】按钮吧🔺PVE 安装位置界面。你有多个的话直接选择你要安装的那个即可,我这里就一个,保持默认就好,然后直接点击【Next】按钮🔺 这个界面在【Country】后面的方框内输入“ China”,其它默认,继续点击【Next】按钮🔺 填写密码,一定别忘记了,等下你登录后台界面会用到。邮箱建议填写真实邮箱,如果有啥问题邮箱可能是你最后的救命稻草。输入完成后点击【Next】按钮进入下一步操作。🔺 然后这步很重要,也就是 PVE 系统的安装设置分配 IP、掩码、网关。完成之后继续【Next】Management Interface:网口选择,一般是针对有多网口设计的主机或者电脑,根据自己的需要选择即可Hostname:主机名,可以填写自己的真实域名(还记得之前我教大家申请免费域名吗),后期可以通过域名远程访问。没有就保持默认吧。IP Address:访问管理的 IP 地址,一定要改成你路由器 DHCP 分配的同一网段 IP,这样局域网才能直接访问。Getway:网关,根据实际填写。我这里直接填写我家的华硕路由器网关。DNS Server:DNS 服务器,根据实际填写,我这里保持默认。🔺 确认 PVE 系统安装信息无误后,点击【Install】按钮进行系统安装🔺PVE 系统安装界面,我们只需要等待进度条跑完即可,完成之后系统会自动重启。记得重启的时候直接拔掉 U 盘,有的电脑会默认的又进入 U 盘系统了。🔺 重启之后的启动项界面,不用管,默认的就是我们安装的 PVE 系统,稍等一会就会自动静茹。🔺 等到这个界面的出现,恭喜你!PVE 系统安装成功!而图中红色方框就是你的 PVE 系统控制台的 URL 访问地址。我们只需要用局域网内的另一台电脑在浏览器中输入这个 URL 就可以访问 PVE 的控制台了!控制台访问🔺 打开局域网内的另一台电脑,浏览器输入上面出现的 PVE 系统控制台的 URL 访问地址,浏览器可能会弹出隐私错误的提示,不用理会,点击【高级】,选择【继续访问】即可。🔺 来到登录界面。用户名输入:root,密码输入之前系统安装时你设置的密码,语言选择:chinese。勾选【保存用户名】,完成之后点击【登录】🔺OK!终于来到了 PVE 系统管理界面!至此,PVE 虚拟机系统安装成功!后期我还会用它来折腾更多有意思的玩法,有兴趣的小伙伴记得关注我!
2023年02月14日
98 阅读
0 评论
0 点赞
2023-02-13
Mysql 创建用户,指定数据库
1.远程登录 mysqlmysql -h ip -u root -p 密码2.创建用户格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by “密码”;例 1:增加一个 test1 用户,密码为 123456,可以在任何主机上登录,并对所有数据库有查询,增加,修改和删除的功能。需要在 mysql 的 root 用户下进行mysql>grant select,insert,update,delete on *.* to test1@'%' identified by '123456'; mysql>flush privileges;例 2:增加一个 test2 用户,密码为 123456,只能在 192.168.2.12 上登录,并对数据库 student 有查询,增加,修改和删除的功能。需要在 mysql 的 root 用户下进行mysql>grant select,insert,update,delete on student.* to test2@192.168.2.12 identified by '123456'; mysql>flush privileges;例 3:授权用户 test3 拥有数据库 student 的所有权限mysql>grant all privileges on student.* to test3@localhost identified by ’123456′; mysql>flush privileges;3.修改用户密码mysql>update mysql.user set password=password(’123456′) where User=’test1′ and Host=’localhost’; mysql>flush privileges;4.删除用户mysql>delete from user where user=’test2′ and host=’localhost’; mysql>flush privileges;5.删除数据库和删除表mysql>drop database 数据库名; mysql>drop table 表名;6.删除账户及权限drop user 用户名@’%’ drop user 用户名@localhostgrant 详细解析如下:MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一、grant 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。grant select on testdb.* to common_user@'%'; grant insert on testdb.* to common_user@'%'; grant update on testdb.* to common_user@'%'; grant delete on testdb.* to common_user@'%';或者,用一条 MySQL 命令来替代:grant select, insert, update, delete on testdb.* to common_user@'%'二、grant 数据库开发人员,创建表、索引、视图、存储过程、函数。。。等权限。grant 创建、修改、删除 MySQL 数据表结构权限。grant create on testdb.* to developer@'192.168.0.%'; grant alter on testdb.* to developer@'192.168.0.%'; grant drop on testdb.* to developer@'192.168.0.%';grant 操作 MySQL 外键权限。grant references on testdb.* to developer@'192.168.0.%';grant 操作 MySQL 临时表权限。grant create temporary tables on testdb.* to developer@'192.168.0.%';grant 操作 MySQL 索引权限。grant index on testdb.* to developer@'192.168.0.%';grant 操作 MySQL 视图、查看视图源代码 权限。grant create view on testdb.* to developer@'192.168.0.%'; grant show view on testdb.* to developer@'192.168.0.%';grant 操作 MySQL 存储过程、函数 权限。grant create routine on testdb.* to developer@'192.168.0.%'; — now, can show procedure status grant alter routine on testdb.* to developer@'192.168.0.%'; — now, you can drop a procedure grant execute on testdb.* to developer@'192.168.0.%';三、grant 普通 DBA 管理某个 MySQL 数据库的权限。grant all privileges on testdb to dba@'localhost'其中,关键字 “privileges” 可以省略。四、grant 高级 DBA 管理 MySQL 中所有数据库的权限。grant all on *.* to dba@'localhost'五、MySQL grant 权限,分别可以作用在多个层次上。grant 作用在整个 MySQL 服务器上:grant select on _._ to dba@localhost; — dba 可以查询 MySQL 中所有数据库中的表。 grant all on _._ to dba@localhost; — dba 可以管理 MySQL 中的所有数据库grant 作用在单个数据库上:grant select on testdb.\* to dba@localhost; — dba 可以查询 testdb 中的表。grant 作用在单个数据表上:grant select, insert, update, delete on testdb.orders to dba@localhost;grant 作用在表中的列上:grant select(id, se, rank) on testdb.apache_log to dba@localhost;grant 作用在存储过程、函数上:grant execute on procedure testdb.pr_add to dba@localhost; grant execute on function testdb.fn_add to dba@localhost;六、查看 MySQL 用户权限查看当前用户(自己)权限:show grants;查看其他 MySQL 用户权限:show grants for dba@localhost;七、撤销已经赋予给 MySQL 用户权限的权限。revoke 跟 grant 的语法差不多,只需要把关键字 “to” 换成 “from” 即可:grant all on *.* to dba@localhost; revoke all on *.* from dba@localhost;八、MySQL grant、revoke 用户权限注意事项grant, revoke 用户权限后,该用户只有重新连接 MySQL 数据库,权限才能生效。如果想让授权的用户,也可以将这些权限 grant 给其他用户,需要选项 “grant option“grant select on testdb.\* to dba@localhost with grant option;这个特性一般用不到。实际中,数据库权限最好由 DBA 来统一管理。=========================================================1.创建用户并授权grant 语句的语法:grant privileges (columns) on what to user identified by “password” with grant option要使用该句型,需确定字段有: privileges 权限指定符权限允许的操作 alter 修改表和索引 create 创建数据库和表 delete 删除表中已有的记录 drop 抛弃(删除)数据库和表 index 创建或抛弃索引 insert 向表中插入新行 reference 未用 select 检索表中的记录 update 修改现存表记录 file 读或写服务器上的文件 process 查看服务器中执行的线程信息或杀死线程 reload 重载授权表或清空日志、主机缓存或表缓存。 shutdown 关闭服务器 all 所有; all privileges同义词 usage 特殊的“无权限”权限以上权限分三组: 第一组:适用于数据库、表和列如:alter create delete drop index insert select update 第二组:数管理权限 它们允许用户影响服务器的操作 需严格地授权 如:file process reload shut* 第三组:权限特殊 all 意味着“所有权限” uasge 意味着无权限,即创建用户,但不授予权限 columns 权限运用的列(可选)并且你只能设置列特定的权限。如果命令有多于一个列,应该用逗号分开它们。 what 权限运用的级别。权限可以是全局,定数据库或特定表. user 权限授予的用户,由一个用户名和主机名组成,许两个同名用户从不同地方连接.缺省:mysql用户password赋予用户的口令(可选),如果你对用户没有指定 identified by 子句,该用户口令不变. 用 identified by 时,口令字符串用改用口令的字面含义,grant 将为你编码口令.注:set password使用password()函数with grant option用户可以授予权限通过 grant 语句授权给其它用户(可选) 实例讲解:grant all on db_book.* to test@kk.com identified by '123456' 只能在本地连接 grant all on db_book.* to test@vpn.kk.com identified by '123456' 允许从此域连接 grant all on db_book.* to test@% identified by '123456' 允许从任何主机连接 注:”%”字符起通配符作用,与like模式匹配的含义相同。 grant all on db_book.* to test@%.kk.com identified by '123456'; 允许test从kk.com域的任何主机连接 grant all on db_book.* to test@192.168.1.189 identified by '123456' grant all on db_book.* to test@192.168.1.% identified by '123456' grant all on db_book.* to test@192.168.1.0/17 identified by '123456'允许从单 IP 段 IP 或一子网 IP 登陆 注:有时 用户@IP 需用引号 如 ‘test@192.168.1.0/17’grant all on *.* to test@localhost identified by '123456' with grant option添加超级用户 admin 可在本地登陆做任何操作.grant reload on *.* to admin@localhost identified by '123456'; 只赋予reload权限 grant all on db_book to admin@kk.com indetified by '123456'; 所有权限 grant select on db_book to admin@% indetified by '123456'; 只读权限 grant select,insert,delete,update on db_book to admin@kk.com indetified by '123456'; 只有select,insert,delete,update的权限 grant select on db_book.storybook to admin@localhost indetified by '123456'; 只对表 grant update(name) on db_book.storybook to admin@localhost; 只对表的name列 密码不变 grant update(id,name,author) on db_book.storybook to admin@localhost; 只对表的多列 grant all on book.* to ''@kk.com; 允许kk.com域中的所有用户使用库book grant all on book.* to admin@%.kk.com indetified by '123456' with grant option; 允许admin对库book所有表的管理员授权.2.撤权并删除用户 revoke的语法类似于grant语句 to用from取代,没有indetifed by和with grant option子句. 如下: revoke privileges (columns) on what from user user:必须匹配原来grant语句的你想撤权的用户的user部分。 privileges:不需匹配,可以用grant语句授权,然后用revoke语句只撤销部分权限。 revoke语句只删权限不删用户,撤销了所有权限后user表中用户记录保留,用户仍然可以连接服务器. 要完全删除一个用户必须用一条delete语句明确从user表中删除用户记录: delete from user where user=”admin” flush privileges; 重载授权表注:使用 grant 和 revoke 语句时,表自动重载,而你直接修改授权表时不是.实例:1.创建数据库CREATE DATABASE `fypay` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;2.为创建的数据库增加用户 fypaygrant create,select,insert,update,delete,drop,alter on fypay.* to fypay@”%” identified by “testfpay”;3.删除 fypay 用户delete from user where user=”fypay” drop user fypay@localhost4.刷新数据库flush privileges;
2023年02月13日
81 阅读
0 评论
0 点赞
2023-02-13
最新v2ray搭建完全手册-科学上网必备
视频教程参考:Debian 系统基于 nginx 搭建 v2ray 服务端配置 vmess+tls+websocket 详细教程。篇首语:科学上网(fanqiang)的大体原理都是通过一台在防火墙之外的 VPS 作为媒介,实现国内网络和防火墙之外的网络之间的互通,因此一台不受防火墙骚扰的 VPS 是必备的。而 v2ray 负责的是你的网络和 VPS 之间的网络通信功能。借助 V2ray 你可以实现透过防火墙,自由穿梭于网络。你需要做的是分别在你的设备(手机、PC 等)和 VPS 上分别部署一下 V2ray。搭建 v2ray 的步骤大体如下:购买一个 VPS,购买后你会获得 VPS 的 IP、root 用户及密码、SSH 端口等信息;登录 VPS,可以借助Xshell这个工具;安装 v2ray,使用 xshell 成功登录 VPS 后,开始搭建;在你的设备上配置与 VPS 对应的 v2ray 信息,就可以成功使用了;在开始下面的搭建工作之前,请自行购买 VPS 并获得 VPS 的相关连接信息,保证能通过 Xshell 等远程连接工作连接后才能进行搭建,不论使用哪家的 VPS,第一步是购买完 VPS 之后,获取到 VPS 的 IP、root 用户及密码、SSH 端口等信息,本文主要说明搭建过程,因此这里将购买 VPS 及使用 XSHELL 进行连接的过程放在:史上最详细搬瓦工 VPS 注册/购买图文教程(内附优惠券) 。正文开始之前,先插播个广告,推荐一些性价比较高的 VPS,有购买 VPS 打算的,可以使用我的推介链接,这样你不仅可以优惠购买,我也会得到一定的返券,感谢你对我写文创作的支持!没有购买 VPS 打算的,可以跳过这一部分。一、搬瓦工 VPS 推荐速度、性价比都较好: 老牌商家,一分价钱一分货,套餐选择上肯定是越好的越贵,选择适合自己的,但从速度上来说,VPS 速度:香港线路 > CN2 GIA 线路 > CN2 线路 > 普通线路。搬瓦工优惠券: BWH3HYATVBJW,此券为全网当前最高优惠力度:6.58%。二、Rackerd VPS 推荐性价比较高: 提供大流量、大硬盘,支持 PayPal、支付宝、微信等多种付款方式,电信走 CN2 GT,联通直达机房(极佳),移动强制走联通链路,算是非 CN2 线路之外优化的相当不错的。三、Vultr 主机推荐国外 VPS Vultr 云主机:最低每月$2.5。下面再来通过图文,来详细说明上面的步骤。四、环境信息服务器系统:Debian GNU/Linux 10服务端:v2ray-core v5.1.0;客户端:v2rayN v5.38 ;五、搭建脚本说明使用到的官网安装脚本:https://github.com/v2fly/fhs-install-v2ray,该脚本在执行时会提供 info 和 error 等信息,请仔细阅读。六、开始搭建提个醒:搭建的过程中难免会碰到一些错误和难题,每个人的服务器版本之类的都有区别。6.1 连接 VPS6.2 更新apt update6.3 安装 curlapt install curl6.4 安装 v2ray使用 curl 进行安装bash <(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)输入vi /usr/local/etc/v2ray/config.json命令,编辑配置文件的内容为以下内容:{ "log": { "access": "/var/log/v2ray/access.log", "error": "/var/log/v2ray/error.log", "loglevel": "warning" }, "inbounds": [{ "port": 11055, "protocol": "vmess", "settings": { "clients": [{ "id": "27848739-7e62-4138-9fd3-098a63964b6b", "level": 1, "alterId": 0 } ] }, "streamSettings": { "network": "ws", "wsSettings": { "path": "/tech" } } } ], "outbounds": [ { "protocol": "freedom" } ] }6.5 启动 v2ray 服务启动并加入开机自启systemctl start v2raysystemctl enable v2ray6.6 安装 nginx执行安装apt install -y nginx新建网页目录这里在假设是/root/www。mkdir -p /root/www新建首页在/root/www目录下新建一个index.html文件,vi /root/www/index.html内容如下:<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Hello Word</title> </head> <body> <div> <h1>Hello Word</h1> </div> </body> </html>新建配置文件注: 不同版本的 nginx 配置文件可能有区别,我的是nginx/1.18.0,配置文件/etc/nginx/sites-enabled/default。或者你的配置文件可能在/etc/nginx/conf.d/default.conf。输入vi /etc/nginx/sites-enabled/default命令,编辑 nginx 配置文件为如下内容: server{ listen 80; server_name v1.xxxx.com; index index.html; root /root/www/; }这里你可能需要将/etc/nginx/nginx.conf中第一行user www-data改为user root,即当前用户。启动 nginx 服务启动Nginx并设置为开机自启systemctl start nginxsystemctl enable nginx查看nginx启动状态systemctl status nginx在浏览器里访问v1.xxxx.com,如果正常则说明 nginx 配置没问题,这是是没有加密的,不带 HTTPS 的网址:http://v1.xxxx.com。6.7 安装 certbot 并申请 ssl 证书详细的申请证书流程参考: certbot instructions – Nginx on Debian 10 (buster)。具体如下:安装 snapdapt install -y snapd确保 snapd 为最新版本snap install core; snap refresh core安装 certbotsnap install --classic certbot创建软链ln -s /snap/bin/certbot /usr/bin/certbot申请证书运行certbot --nginx开始申请证书,如下:稍等一会,会提示证书安装成功! 你会发现 nginx 的配置已经更改,我的/etc/nginx/sites-enabled/default文件被自动修改为以下内容: server{ server_name v1.xxxx.com; index index.html; root /root/www/; listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/v1.xxxx.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/v1.xxxx.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server{ if ($host = v1.xxxx.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name v1.xxxx.com; return 404; # managed by Certbot }此时,在浏览器里访问v1.xxxx.com已经是https开头的了,地址:https://v1.xxxx.com。6.8 添加 v2ray 转发将/etc/nginx/sites-enabled/default更改为以下内容: server{ server_name v1.xxxx.com; index index.html; root /root/www/; listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/v1.xxxx.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/v1.xxxx.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot ## 添加这部分内容,22055对应/usr/local/etc/v2ray/config.json 里面inbounds端口 ## /tech客户端配置的时候需要,对应/usr/local/etc/v2ray/config.json streamSettings里的path location /tech { proxy_redirect off; proxy_pass http://127.0.0.1:11055; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; } } server{ if ($host = v1.xxxx.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name v1.xxxx.com; return 404; # managed by Certbot }然后运行systemctl restart nginx重启 nginx。6.9 客户端 v2rayN 配置大体截图:6.10 使用 Google BBR 开启加速细节参考: Debian 9/10 快速开启 Google BBR 实现 v2ray 高效单边加速。观看 Youtube 4k 高清视频,播放速度还可以:6.11 优化网络,隐藏真实 IP细节参考: 安装 warp 解决 Google 搜索出现人机验证、解锁 Netfix 非自制剧最新教程 。七、卸载执行脚本的卸载命令即可:bash <(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh) --remove
2023年02月13日
253 阅读
0 评论
0 点赞
2023-02-13
jodconvert 配置
版本: 4.2.0端口 和 管道文档转换使用TCP端口或者管道 . 管道比TCP更快, 但是需要为jvm指定本地库, 因此默认使用TCP端口模式.要为jvm配置本地库, 即配置 java.library.path 系统属性.On Linux it's e.g.: java -Djava.library.path=/opt/openoffice.org/ure/lib On Windows it's e.g.: java "-Djava.library.path=C:\Program Files (x86)\OpenOffice 4\program" 默认的TCP端口是2002 :OfficeManager officeManager = LocalOfficeManager.builder() .portNumbers(2002, 2003, 2004, 2005) .build(); 上面的代码指定了4个端口, 因此在OfficeManager启动时, 将启动4个office进程来进行处理转换.officeHome该属性是office的安装目录 .// This example will force JODConverter to use the OpenOffice 4 // installation that can be found using the specified path. // 示例设置officeHome OfficeManager officeManager = LocalOfficeManager.builder() .officeHome("D:\\Program Files (x86)\\OpenOffice 4") .build(); processManager当jodconvert需要工作时, 需要一个processManager , 用于在需要时关闭进程.默认情况下: 会根据os寻找最佳的processManager . 也可以自己实现ProcessManager接口来改变之.// This example will create an instance of the com.example.foo.CustomProcessManager // class that will be used by the created OfficeManager. OfficeManager officeManager = LocalOfficeManager.builder() .processManager("com.example.foo.CustomProcessManager") .build(); workingDir当每个office进程启动时都会创建一个临时目录. 临时目录创建在workingDir中. 该目录也用来存放转换的中间结果.默认使用: java.io.tmpdir 目录templateProfileDir每个LocalOfficeManager都会创建一个临时文件夹来存放当前进程属性, 从而可以避免多个进程间的相互干扰. 通过该属性可以提供一个属性模板来定制属性. OfficeManager 将从模板拷贝属性到临时文件夹中, 这样进程间使用相同的设置的同时避免相互干扰.这些设置可以是 Tools>Options菜单中的 . 如:Load/Save > General: 可以禁用保存互联网urlLoad/Save > Microsoft Office : 这个可以避免文档中的excel被丢失.默认: 创建时使用新的, 受 -nofirststartwizard命令影响.killExistingProcess在新进程启动时是否杀死已存在进程. 默认 : trueprocessTimeout处理超时时间, 单位毫秒 . 默认 : 120000 (2分钟)processRetryInterval重试执行的时间间隔, 毫秒.默认: 250taskExecutionTimeout允许进程执行一个task的最大时间 . 超时将终止, 然后处理下一个task.默认 : 120000(2分钟)maxTasksPerProcess每个office进程可执行的最大task数, 超过将重启. 默认: 200disableOpengl设置当前office进程启动时是否需要禁用opengl ( 仅 libreOffice) . 若opengl已禁止则不会进行任何处理 . 当该属性改变时, office必须重启. 若你遇到LO挂掉, 可以测试该属性.默认: falsetaskQueueTimeout设置task在队列的最大存活时间 , 超时将被从队列移除 并抛出 OiffceException .默认: 30000(30分钟)
2023年02月13日
55 阅读
0 评论
0 点赞
2023-02-13
记Ubuntu16.04 下 LibreOffice的安装与使用
LibreOffice主包和语言包wget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/6.4.6/deb/x86_64/LibreOffice_6.4.6_Linux_x86-64_deb.tar.gzwget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/6.4.6/deb/x86_64/LibreOffice_6.4.6_Linux_x86-64_deb_langpack_zh-CN.tar.gztar xf LibreOffice_6.4.6_Linux_x86-64_deb.tar.gzsudo dpkg -i LibreOffice_6.4.6.2_Linux_x86-64_deb/DEBS/*.debtar xf LibreOffice_6.4.6_Linux_x86-64_deb_langpack_zh-CN.tar.gzsudo dpkg -i LibreOffice_6.4.6.2_Linux_x86-64_deb_langpack_zh-CN/DEBS/*.deb字体wget https://mirrors.tuna.tsinghua.edu.cn/adobe-fonts/source-han-serif/SubsetOTF/SourceHanSerifCN.zipwget https://mirrors.tuna.tsinghua.edu.cn/adobe-fonts/source-han-sans/SubsetOTF/SourceHanSansCN.zipunzip SourceHanSansCN.zipunzip SourceHanSerifCN.zipsudo cp -r SourceHanSansCN /usr/share/fonts/sudo cp -r SourceHanSerifCN /usr/share/fonts/sudo apt install fontconfigfc-cache -fv其它依赖sudo apt install -y openjdk-8-jdk libxinerama1 libcairo2 libcups2 libsm6使用(word转pdf)libreoffice6.4 --invisible --convert-to pdf input.docx --outdir .
2023年02月13日
233 阅读
0 评论
0 点赞
2023-02-13
ubuntu怎么切换到root用户,切换到root账号方法
ubuntu怎么切换到root用户,我们都知道使用su root命令,去切换到root权限,此时会提示输入密码,可是怎么也输不对,提示“Authentication failure”,此时有两种情况一个是真的是密码错了,另一种就是刚安装好的Linux系统,没有给root设置密码。打开Ubuntu,输入命令:su root,回车提示输入密码,怎么输入都不对步骤1:给root用户设置密码:命令:sudo passwd root输入密码,并确认密码。步骤2:重新输入命令:su root然后输入密码:发现可以切换到root权限了。步骤3:使用su xyx命令,切换到普通用户。
2023年02月13日
149 阅读
0 评论
0 点赞
2023-02-13
Linux中unzip解压时中文乱码的解决办法
Linux 中 unzip 解压时中文乱码的解决办法当我们在 linux 中解压一个含有中文名字的压缩包如“资料.zip”时,如果直接使用如下的命令,将会出现中文乱码。unzip 资料.zip主要的原因是因为 unzip 在解压的时候会将编码转化为其内部默认的编码,而默认的编码根本不支持中文 CP936 编码。因此我们需要在解压的时候明确的指定需要使用的编码。目前可以采用如下两种方式解决方法一 在解压的时候直接指定编码格式指定 GBK GB18030 编码也是可以的unzip -O CP936 资料.zip方法二 配置环境变量,指定 unzip 的参数在环境变量中,指定 unzip 参数,总是以指定的字符集显示和解压文件比如,需要在/etc/environment中加入 2 行:UNZIP="-O CP936"ZIPINFO="-O CP936"
2023年02月13日
66 阅读
0 评论
0 点赞
2023-02-13
详解 Java8 Stream 用法
Java8(jdk1.8)的新特性主要是 Lambda 表达式和流,当流和 Lambda 表达式结合起来一起使用时,因为流申明式处理数据集合的特点,可以让代码变得简洁易读如果有一个需求,需要对数据库查询到的菜肴进行一个处理:筛选出卡路里小于 400 的菜肴对筛选出的菜肴进行一个排序获取排序后菜肴的名字菜肴:Dish.javapublic class Dish { private String name; private boolean vegetarian; private int calories; private Type type; // getter and setter } Java8 以前的实现方式private List<String> beforeJava7(List<Dish> dishList) { List<Dish> lowCaloricDishes = new ArrayList<>(); //1.筛选出卡路里小于400的菜肴 for (Dish dish : dishList) { if (dish.getCalories() < 400) { lowCaloricDishes.add(dish); } } //2.对筛选出的菜肴进行排序 Collections.sort(lowCaloricDishes, new Comparator<Dish>() { @Override public int compare(Dish o1, Dish o2) { return Integer.compare(o1.getCalories(), o2.getCalories()); } }); //3.获取排序后菜肴的名字 List<String> lowCaloricDishesName = new ArrayList<>(); for (Dish d : lowCaloricDishes) { lowCaloricDishesName.add(d.getName()); } return lowCaloricDishesName; } Java8 之后的实现方式 private List<String> afterJava8(List<Dish> dishList) { return dishList.stream() .filter(d -> d.getCalories() < 400) //筛选出卡路里小于400的菜肴 .sorted(comparing(Dish::getCalories)) //根据卡路里进行排序 .map(Dish::getName) //提取菜肴名称 .collect(Collectors.toList()); //转换为List } 不拖泥带水,一气呵成,原来需要写24代码实现的功能现在只需5行就可以完成了高高兴兴写完需求这时候又有新需求了,新需求如下:对数据库查询到的菜肴根据菜肴种类进行分类,返回一个Map<Type, List<Dish>>的结果这要是放在jdk8之前肯定会头皮发麻Java8 以前的实现方式private static Map<Type, List<Dish>> beforeJdk8(List<Dish> dishList) { Map<Type, List<Dish>> result = new HashMap<>(); for (Dish dish : dishList) { //不存在则初始化 if (result.get(dish.getType())==null) { List<Dish> dishes = new ArrayList<>(); dishes.add(dish); result.put(dish.getType(), dishes); } else { //存在则追加 result.get(dish.getType()).add(dish); } } return result; } 还好 jdk8 有 Stream,再也不用担心复杂集合处理需求Java8 以后的实现方式private static Map<Type, List<Dish>> afterJdk8(List<Dish> dishList) { return dishList.stream().collect(groupingBy(Dish::getType)); } 又是一行代码解决了需求,忍不住大喊Stream API牛批,接下来将详细介绍流什么是流流是从支持数据处理操作的源生成的元素序列,源可以是数组、文件、集合、函数。流不是集合元素,它不是数据结构并不保存数据,它的主要目的在于计算如何生成流生成流的方式主要有五种通过集合生成,应用中最常用的一种List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = integerList.stream(); 通过集合的stream方法生成流通过数组生成int[] intArr = new int[]{1, 2, 3, 4, 5}; IntStream stream = Arrays.stream(intArr); 通过Arrays.stream方法生成流,并且该方法生成的流是数值流【即IntStream】而不是Stream<Integer>。补充一点使用数值流可以避免计算过程中拆箱装箱,提高性能。Stream API提供了mapToInt、mapToDouble、mapToLong三种方式将对象流【即Stream<T>】转换成对应的数值流,同时提供了boxed方法将数值流转换为对象流通过值生成Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5); 通过Stream的of方法生成流,通过Stream的empty方法可以生成一个空流通过文件生成Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset()) 通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行通过函数生成 提供了iterate和generate两个静态方法从函数中生成流iteratorStream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5); iterate方法接受两个参数,第一个为初始化值,第二个为进行的函数操作,因为iterator生成的流为无限流,通过limit方法对流进行了截断,只生成 5 个偶数generatorStream<Double> stream = Stream.generate(Math::random).limit(5); generate方法接受一个参数,方法参数类型为Supplier<T>,由它为流提供值。generate生成的流也是无限流,因此通过limit对流进行了截断流的操作类型流的操作类型主要分为两种中间操作 一个流可以后面跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的filter、map等终端操作 一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。终端操作的执行,才会真正开始流的遍历。如下面即将介绍的count、collect等流使用流的使用将分为终端操作和中间操作进行介绍中间操作filter 筛选List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5); Stream<Integer> stream = integerList.stream().filter(i -> i > 3); 通过使用filter方法进行条件筛选,filter的方法参数为一个条件distinct 去除重复元素List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5); Stream<Integer> stream = integerList.stream().distinct(); 通过distinct方法快速去除重复的元素limit 返回指定流个数List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5); Stream<Integer> stream = integerList.stream().limit(3); 通过limit方法指定返回流的个数,limit的参数值必须>=0,否则将会抛出异常skip 跳过流中的元素 List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5); Stream<Integer> stream = integerList.stream().skip(2); 通过skip方法跳过流中的元素,上述例子跳过前两个元素,所以打印结果为2,3,4,5,skip的参数值必须>=0,否则将会抛出异常map 流映射所谓流映射就是将接受的元素映射成另外一个元素List<String> stringList = Arrays.asList("Java 8", "Lambdas", "In", "Action"); Stream<Integer> stream = stringList.stream().map(String::length); 通过map方法可以完成映射,该例子完成中String -> Integer的映射,之前上面的例子通过map方法完成了Dish->String的映射flatMap 流转换将一个流中的每个值都转换为另一个流List<String> wordList = Arrays.asList("Hello", "World"); List<String> strList = wordList.stream() .map(w -> w.split(" ")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList()); map(w -> w.split(" "))的返回值为Stream<String[]>,我们想获取Stream<String>,可以通过flatMap方法完成Stream<String[]> ->Stream<String>的转换元素匹配提供了三种匹配方式allMatch 匹配所有List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().allMatch(i -> i > 3)) { System.out.println("值都大于3"); } 通过allMatch方法实现anyMatch 匹配其中一个List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().anyMatch(i -> i > 3)) { System.out.println("存在大于3的值"); } 等同于for (Integer i : integerList) { if (i > 3) { System.out.println("存在大于3的值"); break; } } 存在大于 3 的值则打印,java8中通过anyMatch方法实现这个功能noneMatch 全部不匹配List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); if (integerList.stream().noneMatch(i -> i > 3)) { System.out.println("值都小于3"); } 通过noneMatch方法实现终端操作统计流中元素个数通过 countList<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Long result = integerList.stream().count(); 通过使用count方法统计出流中元素个数通过 countingList<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Long result = integerList.stream().collect(counting()); 最后一种统计元素个数的方法在与collect联合使用的时候特别有用查找提供了两种查找方式findFirst 查找第一个List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> result = integerList.stream().filter(i -> i > 3).findFirst(); 通过findFirst方法查找到第一个大于三的元素并打印findAny 随机查找一个List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> result = integerList.stream().filter(i -> i > 3).findAny(); 通过findAny方法查找到其中一个大于三的元素并打印,因为内部进行优化的原因,当找到第一个满足大于三的元素时就结束,该方法结果和findFirst方法结果一样。提供findAny方法是为了更好的利用并行流,findFirst方法在并行上限制更多【本篇文章将不介绍并行流】reduce 将流中的元素组合起来假设我们对一个集合中的值进行求和jdk8 之前int sum = 0; for (int i : integerList) { sum += i; } jdk8 之后通过 reduce 进行处理int sum = integerList.stream().reduce(0, (a, b) -> (a + b)); 一行就可以完成,还可以使用方法引用简写成:int sum = integerList.stream().reduce(0, Integer::sum); reduce接受两个参数,一个初始值这里是0,一个BinaryOperator<T> accumulator 来将两个元素结合起来产生一个新值, 另外reduce方法还有一个没有初始化值的重载方法获取流中最小最大值通过 min/max 获取最小最大值Optional<Integer> min = menu.stream().map(Dish::getCalories).min(Integer::compareTo); Optional<Integer> max = menu.stream().map(Dish::getCalories).max(Integer::compareTo); 也可以写成:OptionalInt min = menu.stream().mapToInt(Dish::getCalories).min(); OptionalInt max = menu.stream().mapToInt(Dish::getCalories).max(); min获取流中最小值,max获取流中最大值,方法参数为Comparator<? super T> comparator通过 minBy/maxBy 获取最小最大值Optional<Integer> min = menu.stream().map(Dish::getCalories).collect(minBy(Integer::compareTo)); Optional<Integer> max = menu.stream().map(Dish::getCalories).collect(maxBy(Integer::compareTo)); minBy获取流中最小值,maxBy获取流中最大值,方法参数为Comparator<? super T> comparator通过 reduce 获取最小最大值Optional<Integer> min = menu.stream().map(Dish::getCalories).reduce(Integer::min); Optional<Integer> max = menu.stream().map(Dish::getCalories).reduce(Integer::max); 求和通过 summingIntint sum = menu.stream().collect(summingInt(Dish::getCalories)); 如果数据类型为double、long,则通过summingDouble、summingLong方法进行求和通过 reduceint sum = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum); 通过 sumint sum = menu.stream().mapToInt(Dish::getCalories).sum(); 在上面求和、求最大值、最小值的时候,对于相同操作有不同的方法可以选择执行。可以选择collect、reduce、min/max/sum方法,推荐使用min、max、sum方法。因为它最简洁易读,同时通过mapToInt将对象流转换为数值流,避免了装箱和拆箱操作通过 averagingInt 求平均值double average = menu.stream().collect(averagingInt(Dish::getCalories)); 如果数据类型为double、long,则通过averagingDouble、averagingLong方法进行求平均通过 summarizingInt 同时求总和、平均值、最大值、最小值IntSummaryStatistics intSummaryStatistics = menu.stream().collect(summarizingInt(Dish::getCalories)); double average = intSummaryStatistics.getAverage(); //获取平均值 int min = intSummaryStatistics.getMin(); //获取最小值 int max = intSummaryStatistics.getMax(); //获取最大值 long sum = intSummaryStatistics.getSum(); //获取总和 如果数据类型为double、long,则通过summarizingDouble、summarizingLong方法通过 foreach 进行元素遍历List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); integerList.stream().forEach(System.out::println); 而在 jdk8 之前实现遍历:for (int i : integerList) { System.out.println(i); } jdk8 之后遍历元素来的更为方便,原来的 for-each 直接通过 foreach 方法就能实现了返回集合List<String> strings = menu.stream().map(Dish::getName).collect(toList()); Set<String> sets = menu.stream().map(Dish::getName).collect(toSet()); 只举例了一部分,还有很多其他方法 jdk8 之前 List<String> stringList = new ArrayList<>(); Set<String> stringSet = new HashSet<>(); for (Dish dish : menu) { stringList.add(dish.getName()); stringSet.add(dish.getName()); } 通过遍历和返回集合的使用发现流只是把原来的外部迭代放到了内部进行,这也是流的主要特点之一。内部迭代可以减少好多代码量通过 joining 拼接流中的元素String result = menu.stream().map(Dish::getName).collect(Collectors.joining(", ")); 默认如果不通过map方法进行映射处理拼接的toString方法返回的字符串,joining 的方法参数为元素的分界符,如果不指定生成的字符串将是一串的,可读性不强进阶通过 groupingBy 进行分组Map<Type, List<Dish>> result = dishList.stream().collect(groupingBy(Dish::getType)); 在collect方法中传入groupingBy进行分组,其中groupingBy的方法参数为分类函数。还可以通过嵌套使用groupingBy进行多级分类Map<Type, List<Dish>> result = menu.stream().collect(groupingBy(Dish::getType, groupingBy(dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET; else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT; }))); 进阶通过 partitioningBy 进行分区分区是特殊的分组,它分类依据是 true 和 false,所以返回的结果最多可以分为两组Map<Boolean, List<Dish>> result = menu.stream().collect(partitioningBy(Dish :: isVegetarian)) 等同于Map<Boolean, List<Dish>> result = menu.stream().collect(groupingBy(Dish :: isVegetarian)) 这个例子可能并不能看出分区和分类的区别,甚至觉得分区根本没有必要,换个明显一点的例子:List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5); Map<Boolean, List<Integer>> result = integerList.stream().collect(partitioningBy(i -> i < 3)); 返回值的键仍然是布尔类型,但是它的分类是根据范围进行分类的,分区比较适合处理根据范围进行分类总结通过使用Stream API可以简化代码,同时提高了代码可读性,赶紧在项目里用起来。
2023年02月13日
71 阅读
0 评论
0 点赞
2023-02-11
移动APP开发框架盘点
移动APP开发框架盘点 总体概述 现在比较流行的移动APP开发框架有以下六种:网页、混合、渐进、原生、桥接、自绘。前三种体验与Web的体验相似,后三种与原生APP的体验相似。这六种框架形式,都有自己适用的范围。无所谓好坏,适用就是好。 l 网页应用适用于传统网站APP化,比如淘宝、京东,有大量WEB页面嵌入到APP中。 l 混合应用适用于小成本应用开发,全部代码都基于Web,好处是开发快速、成本低。 l 渐进应用适用于高机会成本的场合,边下载边使用,能快速获取,快速体验。 l 原生应用适用于大型和高体验要求的应用,能做出让人满意的体验效果。 l 桥接应用适用于高速迭代的创意类应用,让体验与成本都处于可接受的范围。 l 自绘应用适用于游戏和有特殊效果的应用,最大的好处是没有平台约束和表达瓶颈。 一、网页WebApp WebApp与传统Web的主要区别,在于前端框架,特别是V-DOM框架的应用。此类前端框架使得WebApp与NativeApp在机理上已经没有任何区别了。在众多的前端框架中, React、Vue和Angular是最有竞争力的选择。 React V-Dom技术的开创者,主流框架中的NO.1。React的贡献都是开创性的,在它基础上,也有很多兼容框架,比如Anu,Nerv。用以解决React在性能或IE兼容性上的问题。 主流技术方案: React + Redux + ReactRouter + Material-UI/AntD/Semantic-UI Vue 由国人创建,在中国拥有大量使用者,也有很多配套的开源项目。它的是要特点是学习成本低,容易上手。 主流技术方案: Vue + Vuex + Vue-Router + Vuetify/Quasar/vux/ Mint-UI Angular 大而全型的框架,为大型项目所推崇,深度整合Typescript和Rxjs。 主流技术方案: Angular + Typescript 二、原生NativeApp 由于操作系统的限制,原生应用只有那么几种。对于原生应用,架构是基础,框架是核心,加上海量的UI组件。 IOS iOS开发已经从OC全面转向Swift,最新的架构VIPER基本上可以视为MMVPP。 主流技术方案: VIPER + RxSwift + Moya + Alamofire + SwiftyJSON/ObjectMapper Android Android开发语言从Java更换为Kotlin。编译时依赖注入框架Dagger也成为不二法宝。 主流技术方案: MVP + Dagger + RxKotlin + Retrofit + OkHttp + Kotson(Gson) 三、混合HybridApp HybridApp的关键不在本身,而在WebApp。好的WebApp改为HybridApp很容易。所以混合应用框架实际是指WebApp的基础设施库,有Cordova(PhoneGap)就足够了。 Cordova PhoneGap开源而来。 官方网站: https://cordova.apache.org/ 四、桥接BridgeApp 桥接应用的特点在于使用原生界面,但应用逻辑使用脚本语言编写,通用桥接来控制原生界面。这样达到使用脚本编写原生应用的目的,甚至可以网页与原生应用使用同一套代码,节省大量开发成本。但是操作手感比网页应用强不少。 ReactNative与Weex代表了两种不同的思路。ReactNative提供工具,将平台差异化开放出来(Learn Once, Write Anywhere);而Weex提供框架,将平台差异化屏蔽(Write Once, Run Everywhere)。所以ReactNative最大的痛点是使用难度大,必须熟悉所有平台;Weex则注定功能相对弱小,并且坑比较多。 React Native React的大热,实际始于ReactNative的发布。 官方网站: https://facebook.github.io/react-native/ Weex 小众的框架,能不能壮大,关键在于学习者是否能有效率地编写应用。所以很多人认为文档是决定一个开源框架生死的关键。其实有几个使用框架的开源应用,比文档还要关键。因为这些应用活着,间接地证明了框架还有生存的价值和能力,也能成为更好的文档教材。Weex号称有一堆知名的应用,但开源项目就乏善可陈了。 官方网站: http://weex.apache.org/ Xamarin(C#) Xamarin在IOS与Android中的实现方式不一致,在IOS中是AOT直接编译,在Android中是使用桥接技术。 官方网站: http://xamarin.com/ RubyMotion(Ruby) 动态语言编写移动应用,对语言社区而言是能力问题,必须要证明语言的优越性和无所不能。但除开狂热爱好者,正确的做法是使用最有效率的平台和语言。Ruby的长处在于Web后端,所以编写APP并无多少继承性,编写效率也由于太过小众而存在掉坑的风险。有免费版本,但只支持最新的操作系统版本。 官方网站: http://www.rubymotion.com/ Titanium 这个框架的核心就是使用JavaScript开发应用,与Web开发的在形式上区别很大。所以从根本上,这就是一种脚本语言框架,和RubyMotion如出一辙。 官方网站: http://www.appcelerator.com/ 五、自绘OwndrawApp 自绘一直以来都是游戏界面的势力范围,事实上除开Flutter,其它的框架都是偏游戏开发的。所以Flutter的横空出世,吸引了很大的关注,毕竟这是真正跨平台的唯一可行方案。 Flutter(Dart) 除了使用Dart语言有些争议外,Flutter是真正值得关注的跨平台方案,没有之一。最近它的目标平台除开iOS 和 Android,Flutter Desktop Embedding项目将Flutter引入到桌面操作系统,Hummingbird项目将 Flutter 应用引入浏览器。它利用 Dart 平台的特性不仅可以编译原生 ARM 代码,还可以编译JavaScript 。这使得 Flutter 代码可以在基于标准的 Web 上运行而无需任何更改。 官方网站: https://flutter.dev/ CrossApp(C++) CrossApp是基于Cocos2d-x引擎的,而Cocos2d-x是基于OpenGL的 。9秒社团是由手游社区发展而来的,由此可见CrossApp的背景,使用C++开发也有一些忠实拥趸。 官方网站: https://crossapp.9miao.com/ Corona(Lua) 更适合做游戏,不适合做应用程序,主要是因为界面部分,官方提供的UI部分代码非常不好用,自己实现又很耗时耗力。 官方网站: https://coronalabs.com/ Kivy(Python) 又一个动态语言开发框架,和游戏引擎结合起来使得它在特定领域还是很有市场的。而且它还跨windows平台,可以在windows下直接运行,可以真正实现跨平台运行。 官方网站: https://kivy.org/ 六、渐进ProgressiveApp 渐进有边下载边使用这一层意思,也有下载完成后不依赖网络这一层意思。从类型上来讲,有Google主导的PWA(ProgressiveWebApp),还有微信主导的小程序。相比PWA一统天下的野心,小程序明显是实用主义导向,能用就好,没有长远的布局。急于与微信竞争的百度、支付宝、中国九大手机厂商联盟的QuickApp也复制了这种风格。随着各种跨平台转译工具(如Taro)的兴起,各个小程序平台也随之变成了一个专有浏览器实现,变成了前端千框万架大战中的小小注脚了。 PWA 全称Progressive Web App,即渐进式网页应用。相对于国内厂商的私有平台,谷歌主导的PWA从一开始就瞄准下一代浏览器标准。与传统网页最大的不同,是引入了Service Worker了,相当于本地服务器,能在离线时替代网站服务器继续工作。除此之外,PWA大致就是一个SPA(single page web app),开放标准的继承性还是比较高的。不过由于各平台厂商(如微软,苹果)对PWA的态度不明,PWA的推广进展缓慢。 MiniProgram 微信小程序,由于微信的体量与使用频度,使得小程序可以承载足够的野心。不过从技术上讲,也就是个使用人数较多的浏览器实现。小程序和大量的跟随者,促使多端统一框架也发展起来了。 官方网站: https://mp.weixin.qq.com/ Taro React兼容的跨平台多端统一开发框架。一键生成可以在微信/百度/支付宝/字节跳动小程序、H5、React Native等端运行的代码。虽然多端统一框架看似可以在不同类型的平台运行,但它还是要依赖那些平台工具,还是寄居之上的小程序而已。 官方网站: https://taro.aotu.io/ Nanachi 司徒正美开发的React兼容Anu框架的多端转译脚手架。但是对比Taro是一堆工具打包而成,nanachi仅是一个脚手架,未免寒酸。不包装一下? 官方网站: https://rubylouvre.github.io/nanachi/ Chameleon 类Vue的跨平台多端统一开发框架。专门拜读了昨天出炉的《Chameleon原理详解:其它跨多端统一框架都是假的?》。它有神奇的多态组件,就是重新定义了一个组件声明框架;严格全面的检查,不会不让你的代码不能不跨平台;更多的适配代码,听说有后端统一接口,而且还有一个后台管理系统。好吧,祝您玩得愉快。 官方网站: https://cmljs.org/ 趋势分析 国内由于微信开放了小程序流量主的广告收入,引爆了小程序的热潮,进一步催生了多端转译框架。但是这些框架所做的事并不多,引擎还是React/Vue,做了一套各平台统一的UI组件而已。由于个性化的原因,UI组件是大家一直都想统一,而不能如愿的目标。Taro框架也只是推销了自己的一套UI组件而已。在我看来,还不如提供一套组件“标准”,允许并鼓励用户自己实现。 如果有一套能在React/Vue,ReactNative/Weex,甚至Android,iOS,Flutter上使用的“标准”组件,那么全平台大一统,Write Once, Run Everywhere这个目标才有可能实现吧。 问题:试求React-Native、Taro、Weex、Chameleon框架组件的“最大公约数”和“最小公倍数”。 抽象的“公约数”好求,结合实现的“最小公倍数”只能在实践中证明了。 框架 组件 组件名称 抽象类型 ReactNative View 视图容器 <View> Text 文本 <Text> Image 图片 <Image> ImageBackground 图片背景 <View> TextInput 文本输入框 <Input> ScrollView 滚动视图 <View> Button 按钮 <Button> Picker 选择器 <Picker> Slider 范围值选择 <Slider> Switch 开关组件 <Checkbox> FlatList 简单列表 <List> SectionList 分组列表 <List> DatePickerIOS 日期/时间选择器 <DatePicker> MaskedViewIOS 带蒙版的视图 <Modal> ProgressViewIOS 进度条 <Progress> SegmentedControlIOS 分段显示多个选项 <Tab> SafeAreaView 非遮挡可视区域 <View> SnapshotViewIOS 截屏视图 <View> DrawerLayoutAndroid 抽屉导航 <View> ProgressBarAndroid 进度条 <Progress> ToolbarAndroid 工具栏 <Card> ActivityIndicator 加载提示符 <Loading> KeyboardAvoidingView 随键盘调整视图 <View> Modal 模式视图 <Modal> RefreshControl 下拉刷新 <Trigger> StatusBar 状态栏 <Card> TouchableHighlight 高亮触摸响应 <Trigger> TouchableOpacity 透明度触摸响应 <Trigger> Taro View 视图容器 <View> ScrollView 可滚动视图 <View> Swiper 滑块视图容器 < Swiper> MovableView 可移动的视图容器 <View> CoverView 覆盖在原生组件之上的文本视图 <View> Icon 图标 <Text> Text 文本 <Text> Progress 进度条 <Progress> RichText 富文本 <View> Button 按钮 <Button> CheckboxGroup 多项选择器 <View> Form 表单 <View> Input 文本输入框 <Input> Label 表单标签 <Text> Picker 普通选择器 <Picker> PickerView 嵌入的滚动选择器 <View> Radio 单项选择器 <Radio> Slider 滑动选择器 <Slider> Switch 开关选择器 <Checkbox> Textarea 多行输入框 <Input> Navigator 页面导航链接 <Card> Audio 音频 <Audio> Image 图片 <Image> Video 视频 <Video> Camera 系统相机 <Camera> LivePlayer 实时音视频播放 <Service> LivePusher 实时音视频录制 <Service> Map 地图 <Map> Canvas 画布 <Canvas> OpenData 展示微信开放的数据 <Card> WebView 网页承载容器 <Web> Weex a 页面间的跳转 <A> div 通用容器 <View> text 文本 <Text> image 图片 <Image> list 垂直列表 <List> cell 列表子组件 <View> loading 容器上拉加载 <Trigger> Refresh 容器下拉刷新 <Trigger> recycle-list 复用列表容器 <List> scroller 滚动的容器 <View> slider 轮播图 < Swiper> indicator 轮播图子组件 < Swiper> textarea 多行文本输入 <Input> input 输入 <Input> waterfall 瀑布流布局容器 <View> video 视频 <Video> web 网页 <Web richtext 富文本容器 <View> Chameleon view 视图容器 <View> text 文本容器 <Text> page 基础页面容器 <View> block 包装容器 <View> cell 子列表项容器 <View> scroller 可滚动视图区域 <View> list 可滚动长列表 <List> container 布局容器 <View> row flex布局行容器 <View> col flex布局列容器 <View> carousel 轮播图 < Swiper> carousel-item 轮播图子容器 < Swiper> button 按钮 <Button> input 输入框 <Input> textarea 多行输入框 <Input> switch 开关 <Checkbox> radio 单选框 <Radio> checkbox 复选框 <Checkbox> image 图片 <Image> video 视频播放器 <Video> c-animation 动画组件 <Animation> c-toast 提示框 <Toast> c-loading 加载中 <Loading> c-dialog 对话框 <Modal> c-popup 蒙层 <Modal> c-tip 提示 <Card> c-actionsheet 操作列表 <List> c-tab 标签页 <Tab> c-picker 底部弹起的选择器 <Picker> c-picker-panel 底部弹起的控制板 <Picker> c-picker-item 滚动选择器 <Picker> c-checkbox-group 复选框列表 <View> c-radio-group 单选框列表 <View> c-refresh 上拉&下拉刷新 <Trigger> <完>
2023年02月11日
120 阅读
0 评论
0 点赞
2023-02-11
Ubuntu SSH root 登录 Permission denied 错误
问题:$ ssh root@40.125.21.75 root@40.125.21.75's password: Permission denied, please try again.解决方式,编辑40.125.21.75服务器中的vim /etc/ssh/sshd_config配置文件:PermitRootLogin without-password --改为 PermitRootLogin yes然后重启 SSH:$ sudo service ssh restart
2023年02月11日
185 阅读
0 评论
0 点赞
1
...
25
26
27