Phone 设置项中可以模拟来电和短信:From:选择或输入电话号码;CALL DEVICE:点击来电;HOLD CALL:点击保持通话;END CALL:点击结束通话;SMS message:输入模拟消息的正文内容;SEND MESSAGE:点击发送短信。
国际化的功能离不开错误码的支持,客户端指定语言到服务端去请求,当出错了服务端会根据错误码和语言找到对应的国际化提示语。从上面图中我们发现,错误码不仅仅是客户端与服务端的交互,后台各个服务间的交互也需要约定的一套错误码。一般一个系统的错误码 code 都是唯一确定的。msg 不同场景下可能不一样,提供给用户的肯定是需要友好且不能暴露底层细节,给开发人员看的就要详细专业的错误内容。网关服务上面维护着多套不同语言的错误码提示语,响应的时候会根据客户端带的 Lang 信息进行国际化转译。模块模块编码错误编码底层描述中文提示语英文提示语库存10001商品规格表关联有误商品不存在goods don’t exist一般国际化的系统中会有多份 xxx_lang.properties文件,每一份代表一种语言的消息提示语。中文一般会转为 Unicode 编码进行存储(这个过程一般开发工具可以设置自动转),这样的处理可以规避不同开发环境下不同编码导致中文乱码。
上述例子发现输出的结果是英文的,显然是不适合在国内环境使用,moment.js 提供了国际化支持,在现有的库中,moment 支持的语言可以说是相对完备了。通过引入对应的国际化资源(语言文件),来切换语言。<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/locale/zh-cn.min.js"></script><script> var now = moment().calendar(); console.log(now);// 输出当前日历时间 moment().startOf('hour').fromNow(); // 相对这个小时过去了多少分钟 var timestamp = 1593933593236; // 2020年7曰5日下午15点20分38秒 moment(timestamp).fromNow(); // 相对时间戳多久前</script>有关国际化的更多内容可以参考文档。
试想一下,当我们在公司做某个项目,代码写到一半,回到家以后想用自己的电脑,继续写剩下的代码,那怎么办呢?当然你可以把代码拷贝下来,然后安装到自己的电脑上面,或者借助 QQ、微信、网盘等文件传送方式传送到你自己的电脑上(这里只是举例子,实际工作中一定要遵守公司规定,不要把公司重要代码随意上传或者打包带走)。这样做未免有些繁琐,因为你每次上传都需要传全部的代码,而有些项目的代码还有各种各样的依赖包,实际所占内存会很大,传送也浪费时间。通过 GitHub 我们就能完美解决这个问题,只需要将代码上传到 GitHub 仓库,回家后再拉去一下代码就好了。具体是什么原理,我们后面会讲到。
01 的电频信号在物理介质的传输远不止上面一条横线带过那么简单,想想如果你跟美国的网友进行通信,信号需要跨洋交互,中间经过的设备数量,通信距离有多夸张。
模拟10086来电;gsm call 10086模拟接听来电;gsm accept 10086模拟挂断来电;gsm cancel 10086下面是完整会话示例。pt@Win10-Panda:~$ telnet localhost 5554Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Android Console: Authentication requiredAndroid Console: type 'auth <auth_token>' to authenticateAndroid Console: you can find your <auth_token> in'C:\Users\panda\.emulator_console_auth_token'OKauth KeGgPVHDN7YifXfZAndroid Console: type 'help' for a list of commandsOKgsm call 10086OKgsm accept 10086OKgsm cancel 10086OK
go mod 虽然可以直接帮我们下载好我们需要的包,但是因为 Go 语言很多包都是在国外的服务器上,国内下载具有一定的困难。但是不用担心,go mod 提供了代理服务,同时很多国内的云服务器产商都提供了自己的代理服务:阿里云: https://mirrors.aliyun.com/goproxy 微软: https://goproxy.io 七牛云: https://goproxy.cn GoCenter: https://gocenter.io
命令说明gsm {call\accept\cancel\busy} phonenumber模拟电话的呼入、接听、挂断、繁忙。gsm {data\voice} statedata state 命令用于更改 GPRS 数据连接的状态,data voice state 则用于更改 GPRS 语音连接的状态。gsm hold将通话状态更改为 hold。只有在当前状态为 active 或 waiting 时,才能将通话状态更改为 hold。gsm list列出所有呼入电话和外拨电话及其通话状态。gsm status报告当前的 GSM 语音/数据连接状态。相关的值就是前述 voice 和 data 命令的值。
uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/
注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。
IP 地址,物理地址网站后台访问地址,密码信息家庭成员信息,电话信息生日(很多人的秘密是生日日期)公司信息,同事信息
数据转换成电信号还是比较简单的,将字符根据指定的编码转换成唯一的二进制编码,然后将二进制的 01 映射成高低电平就可以传输出去了。
通过传输层,建立了数据的传输通道。不同应用有自己不同的会话标识,所以传输过来的数据根据会话标识能够知道跟电脑的哪个应用在通信的。
产生原因:包管理器源在国外,网络不好就很难打开甚至打不开。// 国外的源https://packagecontrol.io/channel_v3.json解决方案:设置国内源,步骤如下:Preferences > Package Settings > Package Control > Settings User,添加如下代码并保存,解决。Tips: 如果你的电脑不能科学上网的话,这一步骤还是比较重要的,原因你懂的!类似 npm,google"channels": [ "http://packagecontrol.cn/channel_v3.json"]
移动端大部分指的是手机,大家目前的生活基本已经离不开手机了。但是手机的迭代速度可不同于电脑,相信来到慕课网的小伙伴们都是想学习编程的,想学习编程的话基本上都得有一台电脑。无论是笔记本电脑还是台式电脑,大家可以发现其寿命要远高于手机。通常情况下只要你不是处于一种极端环境下使用电脑的话一般都可以用很多年。这也就是为什么做 PC 网站的程序员有一部分还要去兼容IE的原因, WindowsXP 至今还有人在使用,已经停止维护了的 win7 目前市场份额仍然高居 25% 左右。只要保养得当台式机通常都可以用七年以上,七年之痒不再是难题,笔记本的话也至少可以使用 3 年。
委托对象 (或者被代理对象) 与代理对象需要实现相同的接口;代理对象中保有实际的委托对象引用,外部调用的操作或行为都是代理对象在内部交于实际的委托对象去实现;为了内部隐藏性,外部调用者直接和两者共同的接口通信。
Flask 是一个 Python 实现的 Web 开发微框架,但是这个“微”并不代表着 Flask 功能比较简陋、有所欠缺。微框架中的 “微” 意味着:Flask 旨在保持核心简单而易于扩展;Flask 不会替用户做出太多决策,比如使用何种数据库;Flask 的选项(比如使用何种模板引擎) 通常有多个,用户很容易替换。默认情况下,Flask 不包含数据库抽象层、模板引擎、身份认证或其它任何已有多种库可以胜任的功能,如下图所示。然而,Flask 支持用扩展来给应用添加这些功能,应用程序可以很方便的集成这些扩展。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。
事件日志中包含屏幕电源状态,其中 0 表示屏幕关闭,1 表示屏幕打开,2 表示已锁屏。日志范例如下:grep screen_toggled bugreport-2015-10-18-16-52-22.txt10-18 15:05:04.383 992 992 I screen_toggled: 110-18 15:05:07.010 992 992 I screen_toggled: 010-18 15:23:15.063 992 992 I screen_toggled: 110-18 15:23:25.684 992 992 I screen_toggled: 010-18 15:36:31.623 992 992 I screen_toggled: 110-18 15:36:37.660 3283 3283 I screen_toggled: 2错误报告中还包含关于唤醒锁的统计信息,唤醒锁是应用开发者采用的一种机制,用于表明其应用需要设备保持开启状态。唤醒锁总时长统计信息仅跟踪唤醒锁实际负责使设备保持唤醒状态的时间,不包括屏幕处于开启状态的时间。此外,如果同时持有多个唤醒锁,系统会在它们之间分配唤醒锁时长。
Battery 设置中共用4项参数可以调节,模拟设备的电池属性,了解应用在不同条件下的运行情况:Charge level:设置当前电量值,百分比;Charger connection:设置充电器连接状态,是否连接充电器;battery health:设置电池监控状态,正常或者损坏等;Battery status:设置电池状态,正在充电或者已经充满等。
Http 的整个报文信息,从客户端到服务端到都是明文传输到。信息从我们的电脑发出去,中间需要经历哪些设备才能被另一台电脑接收,我们是不好确定也很难评估的。有可能跨越多个运营商机房,有可能通过海底光缆横跨大洋,有可能穿过 某某学校 / 某某厂房 / 某某集团 的内部 路由器/ 交换机 / 集线器 等。中间这么多节点我们都是控制不到的,所以只要别人有心,我们就很难保证我们的信息不被泄漏。
会话工厂的核心作用:建立和数据库系统的连接,创建会话对象。创建时需要依赖 Configuration 组件解析出来的信息。Hiberante 的会话工厂的源代码实现比较复杂,代码具有良好的结构性,会衍生出很多辅助性组件。因为只是说明问题,本文中的工厂仅仅用来创建会话对象,不考虑性能、缓存、事务等各方面问题,也不刻意讲究代码的结构性。简易框架中的会话工厂的代码简单但具有说明力:public class SessionFactory { private Map<String, String> pros; private List<String> mappings; private ThreadLocal<Session> threadLocal; public SessionFactory(Map<String, String> pros, List<String> mappings) { this.pros = pros; this.mappings = mappings; this.threadLocal = new ThreadLocal<Session>(); } public Connection getConn() { String driverClass = this.pros.get("connection.driver_class"); String url = this.pros.get("connection.url"); String userName = this.pros.get("connection.username"); String password = this.pros.get("connection.password"); try { Class.forName(driverClass); return DriverManager.getConnection(url, userName, password); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return null; } public Session openSession() { return new Session(this.getConn(), this.mappings); } public Session getCurrentSession() { Session session = this.threadLocal.get(); if (session == null) { session = this.openSession(); this.threadLocal.set(session); } return session; }}会话工厂类中有 2 个创建 Session 的方法,一个是普通的创建方法,另一个是从线程上下文中检查是否已经存在 Session 对象。
可以给用户备注 名称、办公、办公电话、住宅电话,命令如下:su rootchfn user_name01执行结果如下图:
而移动端的宽高比刚好相反,手机通常都是竖着的,只有在看电影电视剧或者玩游戏的时候才会横过来,甚至有许多用户直接锁定了竖屏,即使横过来手机也不会发生任何变化。这就导致了移动端与 PC 端的布局有很大的不同,移动端是宽太窄了,通常只能容纳一个列(横行竖列),但是高却很长,尤其是现在的全面屏,让人感觉屏幕超级长,这时候就可以在行(横行竖列)上动手脚了,比较常见的一种布局是上面一行和下面一行固定在屏幕的 header 和 footer,它们并不会随着屏幕的滚动而移动,类似于这样:微信几乎是大家最熟悉的软件了,没有了它就相当于没有了社交,在这样一款用户及其庞大的软件上就运用了移动端最经典的布局。滑动好友列表最上面的灰色那栏并不会移动:同理,下面的那栏控制着微信的会话、通讯录、朋友圈以及设置等重要功能,它也不会被移动:将此种布局稍微抽象一下就能得出这样的一张图:最上面的那行通常被称为 header,最下面的通常被称为 footer,很好理解,头和脚嘛!
代理模式在生活中非常常见,由于最近身边同事都在讨论买房,这里就以买房中介为例来介绍我们今天的代理模式。首先我们需要使用 UML 类图直观地表示出代理模式思想。由上面的 UML 的类图可知,主要涉及到四种角色:Client:客户类,可以看做代理模式调用的外部者 IPurchaseHouse:抽象买房接口,该接口主要职责是声明 HouseOwner (实际房子拥有者) 与 HouseAgent(房产中介)的共同接口方法,该类可以是一个接口或抽象类 HouseOwner:房子拥有者 (房东),也就是代理模式中实际委托对象或被代理对象,外部调用者 Client 类就是通过代理对象 (中介) 间接调用实际的委托对象中定义的方法 HouseAgent:房产中介,也就是代理模式中的代理对象,该类持有一个真实 HouseOwner 引用,在代理类中接口方法中调用 HouseOwner 方法以此来达到代理作用。
计算机的网络模型定义了计算机数据的传输过程,当前有以下 2 种主流模型:国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为 OSI 参考模型或七层模型;工业生产中实际用到的 TCP/IP 四层模型。这两者者的关系就好比,车间里面一个贴在墙上很规范的流程图,一个是实际生产中因为成本/便捷/效率等因素最终采用的流程。但是不管是七层模型还是四层模型,他们实现的目无非是为了解决两个问题:数据转成电信号;目标主机的寻址。
试想一下,如果你在电脑上使用聊天工具,跟对方说了一句 你好,对方的电脑如果只收到了 你好的电频信号,是不能直接解析出来信息的。电脑解析电平信号需要解决很多问题:这个电信号我该用什么规则解析出正确的字符?这信息是谁发给我的?我的电脑现在运行着微信/ QQ /邮件服务等,它到底跟哪个应用交互的?对方的地址是什么,我要怎么回复出去?等等问题很多,所以信息的发送不止是简单的电信号转换,还要给我们的数据添加额外的很多标识,让对方机器清楚你是谁,哪里来的,跟我这台电脑的哪个程序交互等信息。网络模型就很详细的说明了里面具体要处理的事情,这里根据标准的 ISO 七层模型讲解。
在 Scrapy 项目中使用代理是非常简单的一件事情,我们只需要在发送的 Request 请求中添加 meta 参数即可实现代理功能:yield Request(url, callback=回调方法, errback=错误回调, meta={"proxy": proxy, "download_timeout": 10})上面生成的 Request 请求带上了 meta 参数,该参数中又设置了代理服务器的地址以及相应的超时时间。我们可以简单来看看代理服务器的使用:首先我们来自己搭建一个 Nginx 服务,具体的搭建过程可以参考这个教程: Nginx入门手册;接着我们使用9999这个端口做为代理转发端口,相关的配置如下:# nginx.confserver { resolver 114.114.114.114; resolver_timeout 5s; listen 9999; location / { proxy_pass $scheme://$host$request_uri; proxy_set_header Host $http_host; proxy_buffers 256 8k; proxy_max_temp_file_size 0; proxy_connect_timeout 30; proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m; }}启动 nginx 服务后,我们这个代理服务就搞定了。我们可以使用 requests 测试下这个代理服务,看看是不是生效了:import requestsproxies = { "http": "http://180.76.152.113:9999",}response = requests.get("http://www.china-pub.com/browse/", proxies=proxies)response.encoding = 'gbk'print(response.text)上述代码位于另一台云服务器,请求的是互动出版物的图书分类页面,这次我们会在 requests 请求中加上我们刚刚配置的代理,使用 nginx 代理转发请求,请看视频演示:99往往在 Scrapy 中,我们往往会采用这样的方式去使用代理服务:准备好一个 redis 和 web 服务。其中 web 服务往往会使用 django 或者 flask 等 web 框架开发,用于爬取免费的代理 ip,同时会对爬取到的 ip:port 进行校验。如果代理 ip 有效则将其缓存至 redis 服务中,形成有效的 ip 代理池;web 服务会定期检查 ip 代理池的所有数据,对于无效的 ip 及时清除。同时,也会定时爬取新的有效的代理 ip 并保存到 redis 中;web 服务会提供一个获取当前 ip 池内有效 HTTP 代理地址的接口,这样外部应用只需要请求这个接口就能获取一个有效的代理地址;此外,在 Scrapy 的项目中,我们往往会按照如下的思路进行代理爬取:限于篇幅,这里不再对整个流程做案例演示,有兴趣的读者可以下去后一步步完成从 ip 代理池服务的开发到最后对接 Scrapy 框架的整个过程,推荐测试的网站为新浪微博,这也是 github 上许多案例的测试靶场。
实际上 Java 中的动态代理实现已经非常精简了,所以在 Kotlin 在动态代理实现并没有特别不一样的,它和 Java 的实现没有不同。所以这里就不再重复实现,只是换了 Kotlin 语言实现没有什么不一样的。
其实真实的原因是因为雪碧的英文名字是Sprite,而雪碧图的英文名是CSS Sprites,他俩同样都有Sprite这个词。左边是雪碧在国内的 Logo,右边是国外的 Logo。可以看到本来在没进入中国市场之前人家就叫Sprite(精灵),只不过进入了中国市场之后,中国区的负责人表示:用户去商店买汽水的时候如果对老板说:老板你这里有没有精灵?听起来就会感觉很奇怪,所以咱们不要被Sprite这个单词给限制住了,咱们应该起一个更符合中文语义的名字,于是乎“雪碧”诞生了。而雪碧图在国外叫做 CSS Sprite(CSS精灵)反正 Sprite 在国内被叫雪碧,那干脆不如咱们就叫它雪碧图吧!——来自最先接触到这项技术的人。所以后来接触这项技术的人也就跟随前人一起叫它雪碧图了。
一些物理设备的标准,如网卡网线,传输速率定义,最终实现将我们的数据转成电信号传输。