首页 文章 精选 留言 我的

精选列表

搜索[鸿蒙课程],共8086篇文章
优秀的个人博客,低调大师

使用Python-Flask框架开发Web网站系列课程(一)构建项目

版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/81907475 前言 使用IDE:PyCharm 操作系统: Mac Python版本:3.6 我的邮箱:51263921@qq.com 交流群: 372430835 请注意,既然要学习开发,那么要注意以下几个问题。 1、开发语言版本不一样,尤其是Python,会导致同一段代码压根跑不起来的情况。所以请保证版本一致。 2、操作系统不一样,自然也会有区分,但是Mac环境和Linux环境基本还是比较相近,贴合生产,所以使用Mac作为演示环境。但与Window的差别也不会很大。 3、简易使用一样的IDE工具,但是不强求。 4、本课代码的github地址在页面最底。 构建项目 一、创建虚拟环境venv 1、从前我很皮,不喜欢创建这东西,都是直接用系统环境的Python,后来项目一多,呵呵哒,这个项目用的Django1.9,那个项目又用Django2.0。得,乱套了。所以,请养成良好的习惯,使用venv大人。 2、通过PyCharm添加虚拟环境venv ,Windows在File->Settings,Mac在PyCharm->Preferences, 打开页面后,按下图配置。Add local Python Interpreter。最后 Apply -> OK。 二、安装flask 2.1 看下图,在Terminal控件里面执行 pip install flask==1.0.2 。 2.2 然后我们将这个阶段的依赖包记录下来,使用的命令为: pip freeze>requirement.txt 2.3 我们开始构建目录结构 我们需要一个目录放前端的代码(frontend),一个放后端代码(backend),一个放公共方法代码(utils),一个放配置文件(config)。 我们在根目录myproject里面右键New->Python Package,用这个创建包。按上面括号里面的名字建。 2.4 构建后端代码 2.4.1 添加config.py,在/myproject/config下。 这东西就是我们网站以后所有配置存放的地方啦,其中Config放的是各个环境都一致的配置,ProdConfig放的是生产环境的配置,SitConfig存放SIT环境配置,其他类比。 最后的一行,代表config = SitConfig() 当前获取的是SIT环境的配置。 全路径为:/myproject/config/config.py 内容如下: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2017/11/8. """ import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) class Config(object): """Base config class.""" # 版本 VERSION = 'beta 0.1' # 项目名称 PROJECTNAME = 'myproject' # 端口 PORT = 10101 SECRET_KEY = '1234567890!@#$%^&*()' class ProdConfig(Config): """Production config class.""" # 是否开启调试 DEBUG = False # 主机ip地址 HOST = '0.0.0.0' class SitConfig(Config): """Development config class.""" # Open the DEBUG # 是否开启调试 DEBUG = True # 主机ip地址 HOST = '127.0.0.1' class DevConfig(Config): pass # Default using Config settings, you can write if/else for different env config = SitConfig() 2.4.2 修改/myproject/backend/__init__.py 这个是未来整个后端的入口文件,具体内容如下: 全路径:/myproject/backend/__init__.py 具体代码如下: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/21 下午2:41. """ from flask import Flask from config.config import config def create_app(): #初始化项目实例 app = Flask(__name__) app.secret_key = app.config['SECRET_KEY'] #导入配置项 app.config.from_object(config) # 钩子 在请求执行之前 @app.before_request def before_request(): print('hi') return app 2.4.3 在根目录添加后端项目管理文件 manage.py 要先补一个模块 pip install Flask-Script==2.0.6 添加一个空的python脚本,manage.py 全路径:/myproject/manage.py 内容如下: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/21 下午3:40. """ from flask_script import Manager, Server from backend import create_app app = create_app() app.debug = app.config["DEBUG"] # 获取根目录config.py的配置项 host = app.config["HOST"] port = app.config["PORT"] # Init manager object via app object manager = Manager(app) # Create a new commands: server # This command will be run the Flask development_env server manager.add_command("runserver", Server(host=host,port=port,threaded=True)) @manager.shell def make_shell_context(): """Create a python CLI. return: Default import object type: `Dict` """ # 确保有导入 Flask app object,否则启动的 CLI 上下文中仍然没有 app 对象 return dict(app=app) if __name__ == '__main__': manager.run() 2.4.4 添加视图文件,views.py 我们访问一个链接,要显示或者返回什么东西,就是在这里处理后返回给浏览器或者接口的。 全路径:/myproject/backend/views.py 内容如下: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/21 下午3:51. """ from flask import Blueprint,jsonify #账户的蓝图 访问http://host:port/account 这个链接的子链接,都会跳到这里 account = Blueprint('/account', __name__) # 访问http://host:port/account/test 这个链接,就会跳到这里 @account.route('/test') #上面的链接,绑定的就是这个方法,我们给浏览器或者接口请求 一个json格式的返回 def test(): return jsonify({'code':0,'content':'hi flask'}) 2.4.5 添加路由文件,urls.py 全路径:/myproject/backend/urls.py 内容为: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/21 下午3:50. """ from backend.views import account # 蓝图注册 def register(app): app.register_blueprint(account, url_prefix='/account', strict_slashes=False) 2.4.6 最后一步,添加内容到入口文件__init__.py 我们添加了两行代码 from backend.urls import register register(app) 用来干啥的呢,是要把我们路由蓝图的对应关系注册到我们的 flask实例里面。和我们之前把配置文件注册到app.config里面是一个道理。 路径:/myproject/backend/__init__.py 内容如下: #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/21 下午2:41. """ from flask import Flask from config.config import config from backend.urls import register def create_app(): #初始化项目实例 app = Flask(__name__) app.secret_key = app.config['SECRET_KEY'] #导入配置项 app.config.from_object(config) # 注册路由 register(app) # 钩子 在请求执行之前 @app.before_request def before_request(): print('hi') return app 三、启动项目 3.1 点击根目录的manage.py,右键执行 执行方式如图1,然后我们会发现还是缺了参数,请看图2、图3,通过edit configurations,在弹出框中的 Parameters 里面输入runserver。Apply后OK。 现在再次点击根目录的manage.py,右键执行。 * Serving Flask app "backend" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: on * Running on http://127.0.0.1:10101/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 110-176-230 现在,我们在浏览器输入 http://127.0.0.1:10101/account/test 图1: 图2 图3 四、GITHUB地址 https://github.com/lyy8510a/myproject/releases/tag/v1

优秀的个人博客,低调大师

Linux运维课程 第一阶段 重难点摘要(四)CISCO

一、路由器接口操作: 1、#show running-config查看接口 2、#interface fastethernet 0/1进入f0/1配置(0/1,0代表插槽1代表端口、若是s0/0/0,第一个0表示路由器本身) 3、#interface fastEthernet 0/1 #description tachingroute接口描述 4、#do show running-config do可让命令在其它模式运行 5、#int f0/0 #no shutdown 激活接口,接口默认是关闭状态 6、#int f0/0 #ip add 192.168.1.10 255.255.255.0给端口配IP #do sh int f0/0 7、#show controllers s1/0确认此端是DCE端 #int s1/0 #clock rate 64000 #do sh contro s1/0 #bandwidth 1000 时钟频率,在生成环境下不用配置,一般由服务器运营商进行控制,时钟频率只对串口连接的路由器有效,串口用于老式的广域网连接的,主要用于E1网络(带宽2.048Mbps),现已被光纤取代。如使用串口连接两台路由器,仅在DCE端配置(数据通信设备),DTE不需配置(数据终端设备)。 8、#copy running-config startup-config保存配置 #erase startup-config删除配置 #reload 二、查看路由器验证配置 1、#ping IP地址探测IP是否畅通 2、traceroute域名或IP测试路由路径 3、telnet IP或域名端口远程管理或探测端口 4、#clear counters f0/0清除接口的计数器 5、#show ip interface查看接口IP信息 6、#show ip interface brief查看所有接口的IP信息及状态 7、#show protocols查看所有接口上的协议 三、高级IOS操作 1、路由器启动顺序 (1)路由器执行POST开机自检,检查硬件以验证设备的所有组件,POST存储在ROM中,并从中运行; (2)bottstrap查找并加载IOS,它位于ROM中,用于启动时加载IOS,加载IOS的顺序是闪存-TFTP服务器-ROM,默认从闪存中加载IOS; (3)IOS接管启动过程,并在NVRAM中查找启动配置文件(startup-config),破解密码的关键是忽略startup-config; (4)如果在NVRAM中找到startup-config,复制到RAM中,生成running-config,加载登录界面,如没找到startup-config,则向所有接口发送广播,查找TFTP,用于配置路由器,若没找到TFTP,则启动用户交互设置对话模式进行初始化配置。 注:NVRAM非易失性随机存储器,指断电后仍能保存数据,用于保存永久生效的配置文件。 2、破解密码 (1)console线连接路由器,开机60秒后按ctrl+break,中断启动过程,进入rom-moritor模式,此时提示符为rommon 1> (2)修改寄存器的值,>config 0x2142 (3)重启,>reset (4)#copy startup-config running-config #enable secret lamp (5)#config-register 0x2102 #copy run start 四、思科发现协议CDP(CISCO discovery protocol) 1、#show cdp #show cdp interface #cdp timer 60 #cdp holdtime 180获取定时器和保存时间信息 #cdp run激活CDP 2、#show cdp neighbors 收集邻居信息 #showcdp entry * #showcdp entry * protocol #showcdp entry * version 五、路由器备份、升级和恢复 1、#copy tftp: flash: #copy flash: tftp: 路由器的存储器主要有: ROM:一分IOS附本; RAM:IOS将随机访问存储器分成共享和主存,主要用来存储运行中的路由配置和与路由器协议有关的IOS数据结构; FLASH:存储IOS软件映像,闪存是可擦除内存,能用IOS的新版本覆写; NVRAM:存储系统的配置文件。 本文转自 chaijowin 51CTO博客,原文链接:http://blog.51cto.com/jowin/1634858,如需转载请自行联系原作者

优秀的个人博客,低调大师

CCNA系列课程(2) 路由器的启动及Cisco设备管理

第二节课路由器的启动及管理方式 杜飞 2009-06-24 我们今天的内容就涉及到二个方面,一个是路由器的启动,当然这里包括路由器的启动过程,路由器的组件,以及IOS相关的操作,二是介绍对Cisco设备进行管理的几种方式。 我们先来看一下路由器的启动过程,其实路由器和计算机一样,也有一个加电启动的过程,如果想了解路由器的启动过程就必须要先了解路由的内部组件,我们来看一下 路由器内部组件: 一般来说路由器就由这么几部分组成,我们来介绍一下: Flash如同PC机上的BIOS(基本输入输出系统),其中存放的是Cisco路由器的IOS,对它的维护主要就是对IOS文件的备份和恢复。在路由器的enable状态下用“dir”命令,就可以查看到Flash上存储的IOS文件名及其大小。Flash是可编程的存储器,因此可以对Flash进行编程而升级IOS,也能用“eraseflash”删除Flash中的IOS,所以这一命令的使用必须非常谨慎。我们可以通过备份一个IOS映像文件在计算机上,以在需要时修复IOS。用作备份的计算机要作为TFTP服务器,即它需要运行TFTP Server的软件。 NVRAM我个人认为翻译成非易失性RAM比较合适。如同PC机上的CMOS,其中存放的是路由器的配置文件。NVRAM的内容可以用“erasememory”或“writeerase”将配置参数删除到出厂设置状态,所以相对于路由器丢失了IOS,删除NOVRAM的后果不是很严重,恢复起来也容易一些。在路由器正常启动后,它会将NVRAM的内容拷贝到内存一份,我们对路由器的设置实际上就是修改内存中的参数。所以内存和NVRAM中的内容是可以不一样的,直到使用“writememory”、“copyrunning-configstartup-config”将内存设置保存到NVRAM中,或用“reload”、“copystartup-configrunning-config”、重启路由器等办法将NVRAM的内容重新调入内存,才能实现NVRAM与内存之间的同步。用“showconfiguration”命令可查看NVRAM中的设置,用“showrunning-config”、“writeterminal”命令则可以查看当前运行的设置(在内存中)。 ROM在Cisco路由器中的功能与计算机中的ROM相似,主要用于系统初始化等功能 ROM中实现的功能主要包含: POST的注册 引导顺序的微调(可以实现密码恢复等功能) Mini IOS的启动 ROM模式的启动 在IOS启动后可以通过show version命令查看ROM中的信息 Bootstarp是位于ROM微码中的程序,用于执行程序。负责找到每个IOS的位置然后加载该文件。默认情况下,所有的Cisco路由器都从flash中加载IOS软件。 POST也是存放于ROM中微码中的程序,用来检查硬件基本配置是否正常,然后决定哪些接口可用。 ROM Momitor:存储在ROM的微码中,作用是测试和排疑等。 Mini IOS:是一个简化的IOS RAM也就是咱们所说的内存,是可读可写的存储器,但它存储的内容在系统重启或关机后将被清除。和计算机中的RAM一样,Cisco路由器中的RAM也是运行期间暂时存放操作系统和数据的存储器,让路由器能迅速访问这些信息。RAM的存取速度优于前面所提到的3种内存的存取速度。) 当然这里应该还有一个必须的部件就是CPU,至于它的作用,就明白人不用细说! 另外还有一个比较重要的东西就是IOS Cisco IOS Software Features IOS是路由器和交换机的操作系统的简称,全名是Internetwork Operation System,也就是说IOS就相当于PC的操作系统。 只是交换机有默认设置,而路由器没有默认设置,所以不论你买什么型号的交换机都可以不用配置直接使用,但不论你什么型号怕路由器,那怕是家庭使用的宽带路由器也必须要经过设置才可以作用。 这个IOS分为两类,主要发布版本(MR)和前期研发发布版本(EDR)。 主要版本(MR)是IOS技术部门负责管理和发布的IOS版本,这些版本继承于之前的早期研发版本,具有更可靠的特性、平台支持、功能和技术。因此IOS MR具有更好的可靠性和性能,并县域,MR不在接受对新的特性和平台的支持,每个升级维护的版本的改变只是对已知软件错误的修正。 研发版本(ED)是Cisco对为了满足对新技术和新平台的技术而开发的IOS版本。也就是说每个更新的ED版本的发布除了修正已知的软件错误之外,都会不断带给客户更多的新特性。并且,每个ED版本发布1至2年后,就会晋级成为下一个IOS的主要版本。 Cisco IOS的命名规范 Cisco IOS二进制文件的命名由3部分组成,其中第一部分表示的是平台也就是适合的型号,第二部分是特性,第三部分是运行时内存和压缩格式。 如C7200-ajs40-mz C7200表示的是Cisco 7200系统路由器 Ajsa表示的是高级,j表示的是企业特性s表示的是附加特性 Mzm表示IOS在运行时所处的内存z表示的是zip压缩. 其中运行的位置包括以下几种: F运行在flash m运行在RAM R运行在ROM Limage will be relocatedat run time 压缩标识符: Zzip压缩 Xmzip压缩 W“Stac”压缩 那么,大家知道了路由器的组成部件以及IOS的作用,我们就可以来分析一下路由器的启动顺序,如图所示: 1. 在 ROM 中检查启动注册值(也叫做寄存器值)。这个值相当重要!后面介绍 2. 将 NVROM 中的 Startup-configuration 文件 copy 到内存里 3. 默认情况下将 flash 中的第一个 IOS 文件加载到内存中。 4. 如果没有在 flash 中找到 IOS 文件,则在网络中尝试寻找 TFTP Server. 5. 如果找不到 TFTP Server ,则使用 RXBOOT 模式,也就是加载 ROM 中的 Mini IOS. 6. 如果不能加载 Mini IOS ,则使用 ROMMON 启动。 到这里我相信大家都能看的明白,下面咱们开始进行这一节的一个重点,详细分析一下路由器的启动流程图:如果大家把这个图看明白了,那么路由器的启动就没有问题了 这个启动的过程还是有点小复杂的,好,我开始给大家做一个分析: 首先我们开始启动路由器,第一步到了 boot field=0 如果成立就启动 Rom monitor 模式,如果不成立也就是说不等于 0 的话,再判断 field=1 是否成立,如果成立就开始从 RXboot 模式启动,也就是从 mini IOS 方式启动。那如果不成立的话,则去检查 NVRAM 中的 start-up config 中有没有 boot system commands 命令,如果有,就按照这个命令去执行( do what they say )它说从哪儿启动就从哪儿启动,那如果没有这个命令,就检查 flash 中没有一个合法的 IOS 文件,如果有,就使用这个 IOS 从继续向下走,加载这个 IOS 。那如果 flash 中没有 IOS 怎么办呢?就执行 attempt to get ios from network ,也就是从网络上寻找 IOS ( TFTP 服务器),如果成功 , 就从网络上使用这个文件来加载 IOS ,那如果运气比较差,从网络上没有找到 IOS ,那么就查看寄存器中第 13 位的值是否 =1 ,如果成立,就会判断是否已经有 5 次失败了,如果没有则再从网络上查找此文件,也就是说找 TFTP 服务器,共寻找了五次如果都不成功最后才失败,那么这个时候就只能从 mini IOS 启动了,没有办法了!那如果这个 13 位如果不等于 1 ,等于 0 就比较危险了,就进入了一个死循环。所以说这个第 13 位一般都是 1 ! 位数 0123456789ABCDEF 值 00001 现在我们已经分析到了 load IOS, 然后再判断第 6 位是否等于 1 ,如果成立就直接进行 DIALOG 开始启动路由器,也就是说 NVRAM 中没有配置文件,那如果不等于 1 就说明以前有配置文件再判断这个文件是否合法,如果合法 然后就从 NVRAM 中取出此配置文件,启动成功,如果没有又进行 DIALOG 方式开始配置。至此启动全部结束! 那么这个第6 位设置为1 适合于路由器密码丢失的场合!因为密码都是存放在配置文件中,配置文件又是在NVROM 中的,所以跳过即合!但不要忘记,设置正确的密码后,保存到配置文件,然后再将此值改为1 。 下面咱们就来看一下 IOS 相关的操作,我们知道设备的 IOS 是存放在 FLASH 中的,如图所示: Flash 中存储着 IOS 文件,路由器启动的时候会自动在 flash 中寻找正确的 IOS 文件并加载到内存中运行,我们也可以通过 show flash 命令查看 flash 中的文件,如图所示: 我们从图中可以看出 IOS 文件名, flash 所用的空间,剩余空间以及总空间。 当然也可以从 NVRAM 中查看配置文件的信息,配置文件是存放在 NVRAM 中的,我们从上面的启动过程就已经看到了。启动的时候会查看 NVRAM 中有没有可用的配置文件,如果有就直接调入 RAM ,如果没有再启动 DIALOG ,如图所示: 大家可以看到我当前有正在 runing 的配置文件,但是 NVRAM 中是没有配置文件的,所以我们可以把我们现在 runing 的配置文件备份到 NVRAM 中。如图所示: 我在此将路由器名称设置为 dufei ,然后从备份中进行还原,成功后显示为 ITET ,当然除了 RAM 和 NVRAM 之间进行配置文件的复制之外还可以实现 RAM , NVRAM 和 TFTP 服务器之间进行配置文件的复制,如图所示: 如我们希望将当前的配置文件保存到 TFTP 服务器,可以作用命令 copy running-config tftp 我们也可以对 IOS 进行备份和还原,我们可以通过 TFTP 服务器来备份 IOS ,也就是将 IOS 备份到 TFTP 服务器上。如果大家刚才配置文件的备份和还原会了,那么 IOS 的备份也还原大家也就会了,因为语法一模一样! 当然也有需要注意的地方 1 设备和服务器的网络是通的,这是前提 2 一定保证双方的磁盘空间是足够的,否则会失败 3 创建文件,一定要注意是文件全名。 我们来看一下怎么将 IOS 进行备份,以供还原时使用,首先我们先显示一下 flash 中的信息,也就是使用 show flast 到现在为止,咱们已经很详细的把路由器的启动过程 IOS 以及配置文件的备份和还原介绍完了,下面咱们来看一下如何管理 Cisco 设备: 我们一般对 Cisco 设备进行管理有以下方式: 大家通过这个图可以看到可以通过 Console port 用于对新设备的配置 Aux port 用于远程拔呈对设备控制 Telnet (Virtual Terminal ) 用于对已经配置好的设备进行远程管理 TFTP 用于备份或升级 IOS 及配置文件 Web 或 NAS 可以利用一些网管软件对设备进行综合管理 下面我们逐个介绍: Hyper Terminal: 第一次配置路由器的时候必须使用 Console 接口进行配置。第一次使用交换机的时候如果不进行 VLAN 等操作,可以不进行配置。 使用方法如下:将控制线的一端插在路由器的 console 口上,另一头插在计算机的串中上,然后点开始 — 附件 --- 通讯 --- 超级终端 此处采用默认设置即可! Aux 当与远端路由器连接的链路失效,可以使用 Modem 通过 PSTN 网络拨号控制远程网络设备。 Vty 当与远端路由器连接的链路可用时,可以使用 TCP 协议的 Telnet 服务控制远程网络设备。 TFTP/FTP 将网络设备的配置文件保存在 TFTP 或者 FTP 服务器上,可以随时对网络设备的配置进行恢复。 SNMP 当网络环境比较复杂或者网络设备距离较远的时候,可以使用 SNMP 服务也就是咱们所说的网管软件进行管理。 因为在正常的工作中, telnet 方式使用的是比较多的,在下面将给出我们的第一个实验:当然这两个实验比较简单,咱们就从浅入深, Lab1 : Telnet 管理交换机 实验目的:通过 telnet 方式远程访问 cisco 交换机 实验设备:两台 cisco 系统的交换机,一条以太网交叉线 注意:在大型网络中, Telnet 的应用是非常大的,即方便我们对网络的排错和配置,又减少了人工在换线过程的消耗,大大的提高了工作效率。 图例: 具体配置: Switch1 : Switch>enable 从全局模式进入特权模式 Switch#configure terminal 进入配置模式 Switch(config)#hostname SWA 为设备起名 SWA(config)#interface vlan 1 SWA(config-if)#ipaddress 192.168.0.1 255.255.255.0 为交换机配置 IP SWA(config-if)#no shutdown SWA(config-if)#exit 退出配置模式 SWA(config)#username admin password admin 配置用户名口令 SWA(config)#line vty 0 4 SWA(config-line)#login local 启动本地验证 Switch2 : Switch>enable Switch#config terminal Switch(config)#hostname SWB SWB(config)#interface vlan 1 SWB(config-if)#no shutdown SWB(config-if)#ip address 192.168.0.2 255.255.255.0 SWB(config-if)#exit SWB(config)#username dufei password dufei SWB(config)#line vty 0 4 SWB(config-line)#login local 验证:配置完成后,可以在特权模式下用 show running-configuration 查看配置信息。此处略。 在检查配置没有问题后,在特权模式下可以使用 ping 检测两台交换的网络连通性。 至此,实验成功! Lab2: Telnet 管理路由器实验 实验目的:通过 Telnet 远程访问 Cisco 路由器 实验设备:两台 Cisco 系统路由器,一以太网交叉线 图例: Router0: Router>enable Router#configure terminal Router(config)#hostname RA RA(config)#interface fastEthernet 0/0 RA(config-if)#ip address 192.168.0.1 255.255.255.0 RA(config-if)#no shutdown RA(config-if)#exit RA(config)#usernameadmin password admin RA(config)#line vty 0 4 RA(config-line)#login local Router1: Router>enable Router#config terminal Router(config)#interface fastEthernet 0/0 Router(config-if)#ip address 192.168.0.2255.255.255.0 Router(config-if)#no shutdown Router(config-if)#exit Router(config)#exit 测试网络的连通性 而且大家在使用 Telnet 的时候会使用一个小技巧,就是 Ctrl+shift+6 : x 可以快速的回到本地设备上,如果希望再次连接到远程计算机,则可以使用的方法 可以使用命令 disconnect 命令关闭一个从本地发起的 telnet 会话, 可以使用 clear line 命令关闭一个从对端发起的 telet 会话 至此本节结束!累的我不轻。我得小睡一会,明天见。。。。。。 本文转自 dufei 51CTO博客,原文链接:http://blog.51cto.com/dufei/169311,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:如何避免ANR?

原文地址:http://android.xsoftlab.net/training/articles/perf-anr.html#anr 尽管你写代码可能通过了世界上所有的性能测试,但是它还是可能会让人感觉到卡顿。当应用卡的不成样子时,系统会给你弹一个”Application Not Responding”的对话框。 在Android中,系统会对那些长时间没有响应的应用采取一些措施:弹出一个对话框告诉用户APP已经停止了响应,如下图所示: 正出于这个原因,系统会在APP长时间没有响应的时候为用户提供一个退出APP的选项。所以使APP能够及时响应这一点是至关重要的,这样系统才不会向用户显示ANR对话框。 这节课我们会学习Android系统如何检测应用程序是否是未响应,以及应用程序如何保持响应能力的一些改进措施。 什么触发了ANR? 通常情况下,系统会在应用程序不再能够响应用户的输入时显示ANR对话框。比如,如果应用阻塞在了UI线程的IO操作上,那么系统就不能够处理用户的输入事件。或者应用花费了大量的时间在内存模型的构建上或者是在UI线程中计算了游戏的下一步动作。要记住: 即便是最高效的代码也需要花费时间来运行。 任何情况下都不要在UI线程中执行耗时操作,而是要将这些工作放在一个单独的线程中执行。这可以使UI线程保持流畅工作(UI线程负责驱动用户界面的事件循环)。 在Android中,应用程序的响应态由Activity Manager及Window Manager负责监控。系统会在侦测到以下状况时显示ANR对话框: 对输入事件在5秒内没有作出响应。 BroadcastReceiver在10秒内没有执行完毕。 如何避免ANR? Android应用程序默认运行在UI线程中。这意味着在UI线程中的任何耗时操作都会引发ANR问题,因为这会使应用程序给不到输入事件或者意图广播处理的机会。 因此,在UI线程中的每个方法都应当做尽可能少的工作,尤其是Activity的生命周期回调函数。像网络或数据库操作,或者大量的计算之类的耗时操作应当在工作线程中执行。 创建用于执行耗时操作的线程最便捷的方式莫过于使用AsyncTask了。只需要继承AsyncTask,然后重写doInBackground()就可以执行了。如果要向用户展示工作进度,你可以使用publishProgress()方法,它会回调onProgressUpdate()方法(该方法运行于UI线程)。 在onProgressUpdate()内我们可以更新进度条。 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { // Do the long-running work in here protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } // This is called each time you call publishProgress() protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } // This is called when doInBackground() is finished protected void onPostExecute(Long result) { showNotification("Downloaded " + result + " bytes"); } } 使用execute()方法启动工作线程: new DownloadFilesTask().execute(url1, url2, url3); 如果不采用这种方式,我们还有另一种实现方法:创建自己的Thread或HandlerThread。如果采用这种方法,那么应该设置该线程的优先级为”background”:通过Process.setThreadPriority()方法及参数THREAD_PRIORITY_BACKGROUND设置。 如果没有设置该优先级,那么该线程会使应用感到变慢,因为该线程的优先级默认与UI线程的优先级一致,它们会互相抢占CPU资源。 如果实现了自己的Thread或HandlerThread,那么要确保在等待其它工作线程完成之前UI线程不被阻塞—不要调用Thread.wait()或Thread.sleep()。如果需要等待其它线程的执行结果,可以为UI线程创建一个Handler。这样做可以使UI线程还可以对 输入事件保持响应能力。这样就可以避免5秒内无响应的ANR对话框出现。 BroadcastReceiver在执行时间上有特殊的限制,这意味着在其内部的工作一定是轻量级的:比如在后台做一些保存设置或者发送通知的工作。所以与UI线程中执行的方法一样,广播接收器内也应当杜绝耗时操作的出现。 TIP: 你可以使用StrictMode来发现UI线程中意外出现的耗时操作。 ANR相关优化 一般来说,100~200毫秒是用户所能感知到应用卡顿的极限。下面列出了一些可以避免应用程序ANR的一些点,同样也有助于防止出现卡顿的情况: 如果应用需要对用户输入做大量的后台工作,可以显示一个进度表示工作正在进行。 对于游戏类的复杂计算,应该将这些工作放在工作线程中执行。 如果应用在初始化阶段需要花费一些时间,可以考虑显示一个闪屏页面或者尽可能快的显示主界面:展示加载正在进行,并进行异步数据填充。在这些情况下都应当表明任务正在进行,以免让用户认为应用已经卡死。 使用Systrace或Traceview等性能工具检查APP的响应瓶颈。

优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:性能优化建议

原文地址:http://android.xsoftlab.net/training/articles/perf-tips.html 本篇文章主要介绍那些可以提升整体性能的微小优化点。它与那些能突然改观性能效果的优化手段并不属于同一类。选择正确的算法与数据结构必然是我们的第一总则,但是这不是我们这篇文章要介绍的。你应该将这篇文章所提及的知识点作为编码的日常习惯,这可以提升常规代码的执行效率。 下面是书写代码的基本准则: 绝不要做你不需要的工作。 如果可以不申请内存就不要申请,要合理复用已有的对象。 另一个较复杂的问题就是被优化过的APP肯定是要运行在各种类型的硬件平台上。不同版本的虚拟机运行在不同的处理器上肯定会有不同的运行速度。需要特别说明的是,在模拟器上测试很少会得知其它设备的性能。在不同设备上还有一个很大的不同点就是有没有JIT(JIT的意思是即时编译器):在JIT设备上运行的最优代码并不总在没有JIT设备上有效。 为了确保APP可以在各类设备上运行良好,要确保代码在各个版本的平台上都是高效的。 避免创建不必要的对象 创建对象绝不是没有成本的。虽然分代垃圾收集器可以使临时对象的分配成本变得很低,但是内存分配的成本总是远高于非内存分配的成本。 随着更多对象的生成,你可能就开始关注垃圾收集器了。虽然Android 2.3中出现的并发收集器可能会帮到你,但是不必要的工作总是应该避免的。 因此,要避免创建不需要的对象。下面的示例可能会帮到你: 如果你有个返回字符串的方法,该方法所返回的字符串总是被接在一个StringBuffer对象后面。那么就可以更改此方法的实现方式:让该字符串直接跟在StringBuffer的后面返回。这样就可以避免创建那些临时性的变量。 当从字符串中提取子串时,应该尝试返回原始数据的子串,而不是创建一个副本。子串将会创建一个新的String对象,但是它与char[]共用的是同一数据。采用这种方式的唯一不足就是:虽然使用了其中的一部分数据,但是剩余的数据还都保留在内存中。 一条更为先进的法则就是,将多维数组转换为平行数组使用: int数组的效率要比Integer数组的效率高的多。 如果你需要实现一个用于存储(Foo,Bar)对象的数组,要记得使用两个平行的Foo[],Bar[]数组,这要比单一的(Foo,Bar)数组效率好太多。 通常来说,要尽量避免创建那些生命周期很短的临时变量。更少的对象创建意味着更低频率的垃圾回收,这会直接反应到用户体验上。 首选静态 如果不需要访问对象的属性,那么就可以将方法设置为静态方法。这样调用将会增加15%-20%的速度。这还是一个好的习惯,因为这样可以告诉其它方法一个信号:它们更改不了对象的状态。 使用常量 请先考虑以下声明: static int intVal = 42; static String strVal = "Hello, world!"; 编译器会产生出一个类的实例化方法,名为< clinit>,它会在类首次被用到的时候执行。该方法会将值42存到intVal中,并将字符串常量表中的引用赋给strVal。当这些值被引用之后,其它属性才可以访问它们。 我们可以使用”final”关键字来改进一下: static final int intVal = 42; static final String strVal = "Hello, world!"; 这样的话,类就不需要再调用< clinit>方法,因为常量的初始化工作被移入了dex文件中。代码可以直接引用intVal为42的值,并且访问strVal也会直接得到字符串”string constant” ,这样可以省去了查找字符串的过程。 Note: 这样优化手段仅仅适用于基本数据类型以及字符串常量,不要作用其它类型。 避免内部的get\set方法 像C++这种本地语言通常都会使用get方法来访问属性。这对C++来说是一个非常好的习惯,并且C#、Java等面向对象语言也广泛使用这种方式,因为编译器通常会进行内联访问,并且如果你需要限制访问或者调试属性的话,只需要添加代码就可以。 不过,这在Android上并不是个好习惯。方法调用的开销是非常大的。虽然为了遵循面向对象语言提供get、set方法是合理的,但是在Android中最好是可以直接访问对象的字段。 在没有JIT的设备中,直接访问对象字段的速度要比通过get方法访问的速度快3倍。在含有JIT的设备中,这个效率会达到7倍之多。 注意:如果你使用了ProGuard,那么就有了一个两全其美的结果,因为ProGuard会直接为你进行内联访问。 使用增强for循环 增强for循环可用于实现了Iterable接口的集合或数组。在集合内部,迭代器需要实现接口方法:hasNext()以及next()。 有以下几种访问数组的方式: static class Foo { int mSplat; } Foo[] mArray = ... public void zero() { int sum = 0; for (int i = 0; i < mArray.length; ++i) { sum += mArray[i].mSplat; } } public void one() { int sum = 0; Foo[] localArray = mArray; int len = localArray.length; for (int i = 0; i < len; ++i) { sum += localArray[i].mSplat; } } public void two() { int sum = 0; for (Foo a : mArray) { sum += a.mSplat; } } zero()方法是最慢的,因为JIT不能够对每次访问数组长度的开销进行优化。 one()方法是稍快点的。它将一切元素放入了本地变量,这样避免了每一次的查询。只有数组的长度提供了明显的性能提升。 two()方法是最快的。它使用了增强for循环。 所以应当在默认情况下使用增强for循环。 Tip: 也可以查看Josh Bloch 的 Effective Java,第46条。 考虑使用包内访问 请先思考以下类定义: public class Foo { private class Inner { void stuff() { Foo.this.doStuff(Foo.this.mValue); } } private int mValue; public void run() { Inner in = new Inner(); mValue = 27; in.stuff(); } private void doStuff(int value) { System.out.println("Value is " + value); } } 上面的代码定义了一个内部类,它可以直接访问外部类的私有成员以及私有方法。这是正确的,这段代码将会打印出我们所期望的”Value is 27”。 这里的问题是:VM会认为Foo$Inner直接访问Foo对象的私有成员是非法的,因为Foo和Foo$Inner是两个不同的类,虽然Java语言允许内部类可以直接访问外部类的私有成员(PS:虚拟机与语言是两种互不干扰的存在)。为了弥补这种差异,编译器专门为此生成了一组方法: /*package*/ static int Foo.access$100(Foo foo) { return foo.mValue; } /*package*/ static void Foo.access$200(Foo foo, int value) { foo.doStuff(value); } 当内部类代码需要访问属性mValue或者调用doStuff()方法时会调用上面这些静态方法。上面的代码归结为你所访问的成员属性都是通过访问器方法访问的。早期我们说通过访问器访问要比直接访问慢很多,所以这是一段特定语言形成的隐性性能开销示例。 避免使用浮点型 一般来说,在Android设备上浮点型要比整型慢大概2倍的速度。 在速度方面,float与double并没有什么区别。在空间方面,double是float的两倍大。所以在桌面级设备上,假设空间不是问题,那么我们应当首选double,而不是float。 还有,在对待整型方面,某些处理器擅长乘法,不擅长除法。在这种情况下,整型的除法与取模运算都是在软件中进行的,如果你正在设计一个哈希表或者做其它大量的数学运算的话,这些东西应该考虑到。 使用本地方法要当心 使用本地代码开发的APP并不一定比Java语言编写的APP高效多少。首先,它会花费在Java-本地代码的转换过程中,并且JIT也不能优化到这些边界。如果你正在申请本地资源,那么对于这些资源的收集能明显的感觉到困难。除此之外,你还需要对每一种CPU架构进行单独编译。你可能甚至还需要为同一个CPU架构编译多个不同的版本:为G1的ARM处理器编译的代码不能运行在Nexus One的ARM处理上,为Nexus One的ARM处理器编译的代码也同样不能运行在G1的ARM处理器上。 本地代码在这种情况下适宜采用:当你有一个已经存在的本地代码库,你希望将它移植到Android上时,不要为了改善Java语言所编写的代码速度而去使用本地代码。 如果你需要使用本地代码,那么应该读一读JNI Tips. Tip: 相关信息也可以查看Josh Bloch 的 Effective Java,第54条。 性能误区 在没有JIT的设备中,通过具体类型的变量调用方法要比抽象接口的调用要高效,这是事实。举个例子,通过HashMap map调用方法要比Map map调用方法要高效的多,开销也少,虽然这两个实现都是HashMap。事实上速度并不会慢2倍这么多;真实的不同大概有6%的减缓。进一步讲,JIT会使两者的差别进一步缩小。 在没有JIT的设备上,通过缓存访问属性要比反复访问属性要快将近20%的速度。在JIT的设备中,属性访问的花销与本地访问的花销基本一致,所以这不是一项有多少价值的优化手段,除非你觉得这样做的话代码更易读(这对static,final,常量同样适用)。 经常估测 在开始优化之前,要确保你有个问题需要解决:要确保你可以精准测量现有的性能,否则将不能观察到优化所带来的提升。 基准点由Caliper的微型基准点框架创建。基准点很难正确获得,所以Caliper将这份很难处理的工作做了,甚至是在你没有在测量那些你想测量的地方的时候它也在工作。我们强烈的推荐你使用Caliper来创建自己的微型基准点。 你可能还发现Traceview非常有助于提升性能,不过你应该意识到Traceview工作的时候JIT并没有开启。这会错误的认为JIT会将损失掉的时间弥补回来。这尤其重要:根据Traceview所更改的结果会使实际代码运行的更快。 有关更多提升APP性能的工具及方法,请参见以下文档: Profiling with Traceview and dmtracedump Analyzing UI Performance with Systrace

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册