首页 文章 精选 留言 我的

精选列表

搜索[快速],共10006篇文章
优秀的个人博客,低调大师

CentOS7,8上快速安装Gitea,搭建Git服务器

安装准备 1.安装Git环境 sh 复制代码 yum -y install git 2.下载Gitea运行程序 下载地址:https://dl.gitea.io/gitea/ 注:下载gitea-[版本号]-linux-amd64的运行程序 安装 1.将安装包上传至指定目录 如:/data0/gitea/gitea-linux-amd64 2.重命名安装包 sh 复制代码 mv /data0/gitea/gitea-linux-amd64 /data0/gitea/gitea 3.修改运行权限 sh 复制代码 chmod +x /data0/gitea/gitea 4.直接运行 sh 复制代码...

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

Docker快速安装Oracle11G,搭建oracle11g学习环境

安装说明 1.操作系统CentOS7_x64 2.安装的数据库为Oracle11G 3.已经安装了Docker环境 4.安装一些必要的软件 sh 复制代码 yum install unzip -y unzip:解压oracle安装文件 5.提前准备Oracle11G安装镜像 下载地址:https://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html 6.需要检查是否有swap分区,如果没有请设置 安装 1.镜像准备 将下载的Oracle安装包上传到指定目录并解压 如:/data0/oracle...

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

docker快速入门

1、docker简介 docker通过内核虚拟化技术(namespace及cgroups等)来提供容器的资源隔离与安全保障等,由于docker通过操作系统层的虚拟化实现隔离,所以docker容器在运行时,不需要类似虚拟机额外的操作系统开销,提供资源利用率 2、docker vs kvm 3、docker组件 镜像、容器、仓库 4、docker安装 [root@docker~]#tee/etc/yum.repos.d/docker.repo<<-'EOF' [dockerrepo] name=DockerRepository baseurl=https://yum.dockerproject.org/repo/main/centos/7/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg EOF [root@docker~]#yuminstalldocker-engine-y 5、docker基础操作 [root@docker~]#systemctlenabledocker.service Createdsymlinkfrom/etc/systemd/system/multi-user.target.wants/docker.serviceto/usr/lib/systemd/system/docker.service. [root@docker~]#systemctlstartdocker.service [root@docker~]# [root@docker~]#dockerpullcentos#拉取镜像 [root@docker~]#dockerpulldaocloud.io/library/nginx 有时候拉取速度很慢,采用国内源加速 root@docker~]#vim/usr/lib/systemd/system/docker.service增加下面这行 EnvironmentFile=/etc/sysconfig/docker 新建配置文件[root@docker~]#vim/etc/sysconfig/docker 在https://dashboard.daocloud.io/注册,然后点击加速器生成加速链接 OPTIONS=--registry-mirror=curl-sSLhttps://get.daocloud.io/daotools/set_mirror.sh|sh-s [root@docker~]#dockersearchnginx#搜索镜像 [root@docker~]#dockerp_w_picpaths REPOSITORYTAGIMAGEIDCREATEDSIZE centoslatest0584b3d2cf6d2weeksago196.5MB 导出镜像 [root@docker~]#dockersave-onginx.tardaocloud.io/library/nginx [root@docker~]#dockersave-ocnetos.tarcentos 导入镜像 [root@docker~]#dockerload--inputcnetos.tar或者[root@docker~]#dockerload<cnetos.tar 删除镜像 [root@docker~]#dockerrmi0584b3d2cf6d(镜像ID) [root@docker~]#dockerruncentos/bin/echo"Helloworld" Helloworld [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 5e381e68a385centos"/bin/echo'Hellowor"6secondsagoExited(0)5secondsagoclever_lamarr [root@docker~]#dockerrun--namemydocker-t-icentos/bin/bash [root@1a67f4c92b6e/]# [root@1a67f4c92b6e/]#ps-ef UIDPIDPPIDCSTIMETTYTIMECMD root10018:56?00:00:00/bin/bash root141018:56?00:00:00ps-ef [root@1a67f4c92b6e/]#exit exit [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 1a67f4c92b6ecentos"/bin/bash"12minutesagoExited(0)6secondsagomydocker 5e381e68a385centos"/bin/echo'Hellowor"16minutesagoExited(0)16minutesagoclever_lamarr [root@docker~]#dockerrun--namedocker-demo-dcentos/bin/bash-d代表放入后台执行 6c5a777467b9552714f9cd3322e677750e2b8b5b0bd2d81e79094ad560828a5e [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 6c5a777467b9centos"/bin/bash"11secondsagoExited(0)11secondsagodocker-demo 1a67f4c92b6ecentos"/bin/bash"17minutesagoExited(0)4minutesagomydocker 5e381e68a385centos"/bin/echo'Hellowor"21minutesagoExited(0)21minutesagoclever_lamarr [root@docker~]#dockerstopmydocker停止容器 [root@docker~]#dockerstart1a67f4c92b6e启动容器 [root@docker~]#dockerrun-d--namemynginxdaocloud.io/library/nginx 225a9b0459630c62dcf2199d6244b16a74ad9412471abf0be03755768df3ae63 [root@docker~]# [root@docker~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 225a9b045963daocloud.io/library/nginx"nginx-g'daemonoff"6secondsago Up5seconds80/tcp,443/tcpmynginx 进入容器脚步 [root@docker~]#catdocker_in.sh #!/bin/bash docker_in(){ NAME_ID=$1 PID=$(dockerinspect--format"{{.State.Pid}}"$NAME_ID) nsenter-t$PID-m-u-i-n-p } docker_in$1 6、docker网络 root@docker~]#dockerrun-d-P--namenginx-test1daocloud.io/library/nginx 9b1d36d40127fe2c84bbe7750802e435a817a15b4159b24fc49bfb1107a2cb74 [root@docker~]#dockerps-l CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 9b1d36d40127daocloud.io/library/nginx"nginx-g'daemonoff"2minutesagoUp2minutes0.0.0.0:32769->80/tcp,0.0.0.0:32768->443/tcpnginx-test1 [root@docker~]#netstat-lntup|grep32768 tcp600:::32768:::*LISTEN11213/docker-proxy [root@docker~]#curl-Ihttp://172.16.80.132:32769 HTTP/1.1200OK Server:nginx/1.11.5 Date:Thu,24Nov201605:58:47GMT Content-Type:text/html Content-Length:612 Last-Modified:Tue,11Oct201615:03:01GMT Connection:keep-alive ETag:"57fcff25-264" Accept-Ranges:bytes 转换前 [root@docker~]#iptables-L-n ChainINPUT(policyACCEPT) targetprotoptsourcedestination ACCEPTall--0.0.0.0/00.0.0.0/0stateRELATED,ESTABLISHED ACCEPTicmp--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTtcp--0.0.0.0/00.0.0.0/0stateNEWtcpdpt:22 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainFORWARD(policyACCEPT) targetprotoptsourcedestination DOCKER-ISOLATIONall--0.0.0.0/00.0.0.0/0 DOCKERall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0ctstateRELATED,ESTABLISHED ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainOUTPUT(policyACCEPT) targetprotoptsourcedestination ChainDOCKER(1references) targetprotoptsourcedestination ChainDOCKER-ISOLATION(1references) targetprotoptsourcedestination RETURNall--0.0.0.0/00.0.0.0/0 转换后 [root@docker~]#dockerrun-d-P--namenginx-test1daocloud.io/library/nginx 42783cf5053639383004f82b9e72fe0223c7c028d2754b2d0f74429824715f05 [root@docker~]#dockerps-l CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 42783cf50536daocloud.io/library/nginx"nginx-g'daemonoff"9secondsagoUp7seconds0.0.0.0:32769->80/tcp,0.0.0.0:32768->443/tcpnginx-test1 [root@docker~]#iptables-L-n ChainINPUT(policyACCEPT) targetprotoptsourcedestination ACCEPTall--0.0.0.0/00.0.0.0/0stateRELATED,ESTABLISHED ACCEPTicmp--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTtcp--0.0.0.0/00.0.0.0/0stateNEWtcpdpt:22 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainFORWARD(policyACCEPT) targetprotoptsourcedestination DOCKER-ISOLATIONall--0.0.0.0/00.0.0.0/0 DOCKERall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0ctstateRELATED,ESTABLISHED ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainOUTPUT(policyACCEPT) targetprotoptsourcedestination ChainDOCKER(1references) targetprotoptsourcedestination ACCEPTtcp--0.0.0.0/0172.17.0.2tcpdpt:443 ACCEPTtcp--0.0.0.0/0172.17.0.2tcpdpt:80 ChainDOCKER-ISOLATION(1references) targetprotoptsourcedestination RETURNall--0.0.0.0/00.0.0.0/0 [root@docker~]#shdocker_in.shnginx-test1 root@42783cf50536:/# root@42783cf50536:/# root@42783cf50536:/#ipaddr 1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefault link/loopback00:00:00:00:00:00brd00:00:00:00:00:00 inet127.0.0.1/8scopehostlo valid_lftforeverpreferred_lftforever inet6::1/128scopehost valid_lftforeverpreferred_lftforever 4:eth0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscnoqueuestateUPgroupdefault link/ether02:42:ac:11:00:02brdff:ff:ff:ff:ff:ff inet172.17.0.2/16scopeglobaleth0 valid_lftforeverpreferred_lftforever inet6fe80::42:acff:fe11:2/64scopelink valid_lftforeverpreferred_lftforever 7、docker数据存储 [root@docker~]#dockerrun-d--namenginx-volume-test1-v/datadaocloud.io/library/nginx 88b24d79a4f3b021325592ceac20e86291166d675b213d60db017548c4d9d960 [root@docker~]#shdocker_in.shnginx-volume-test1 root@88b24d79a4f3:/#cd/data/ root@88b24d79a4f3:/data#ls root@88b24d79a4f3:/data#touchhehe root@88b24d79a4f3:/data#ls-l total0 -rw-r--r--1rootroot0Nov2406:30hehe [root@docker~]#cd/var/lib/docker/ [root@dockerdocker]#ll total32 drwx------6rootroot4096Nov2414:28containers drwx------5rootroot4096Nov2402:05devicemapper drwx------3rootroot4096Nov2401:20p_w_picpath drwxr-x---3rootroot4096Nov2401:20network drwx------2rootroot4096Nov2401:20swarm drwx------2rootroot4096Nov2410:09tmp drwx------2rootroot4096Nov2401:20trust drwx------3rootroot4096Nov2414:28volumes [root@dockerdocker]#cdvolumes/ [root@dockervolumes]#ls 4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60metadata.db [root@dockervolumes]#cd4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60/ [root@docker4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60]#ls _data [root@docker4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60]#cd_data/容器内的文件实际在物理机上面的的保存目录 [root@docker_data]#ls hehe [root@docker~]#dockerrun-d--namenginx-volume-test2-v/data/mysql:/mysqldaocloud.io/library/nginx f7278ce9bd88c26a0c5aaefcb2b39f1f9df0066bc94edb7a530213815e166f5e #-v/data/mysql:/mysql表示把物理机的/data/mysql目录挂载到容器内的/mysql目录下面 [root@docker~]#dockerrun-d--namenginx-volumes-v/data/mysql:/mysqldaocloud.io/library/nginx 28c616e44352fc4eafeb2f87dbbb7b6eb9df447235afe027034efa96df1c5071 [root@docker~]# [root@docker~]#dockerrun-d--nameweb-node1--volumes-fromnginx-volumesdaocloud.io/library/nginx 0f022ce56e8b800cb1a4ac76bb8a326d42e198093146e8661ad3ac8925ad317d [root@docker~]# [root@docker~]#dockerrun-d--nameweb-node2--volumes-fromnginx-volumesdaocloud.io/library/nginx 03d5e88c15f6604eeee2b8af500b8f356ba69adc34710f3c19b813530f19dc3d

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

JavaScript简单快速入门

“ 别害怕顾虑,想到就去做,这世界就是这样,当你把不敢去实现梦想的时候梦想就会离你越来越远,当你勇敢地去追梦的时候,全世界都会来帮你。”你好,我是梦阳辰!未来我陪你一起成长! 01.变量 定义:变量是存储信息的“容器”,是内存单元。 1.格式: var pi;//声明变量 var x =5;//赋值 2.注意:如果重新声明变量,该变量的值不会丢失。 var name = "MengYangChen"; var name; name的值依然是MengYangChen 3.动态类型 变量的类型,为赋值语句后面数据的类型。 var x;//如果没有赋值默认为undefined var x =3; var = "MengYangChen"; 4.变量的作用域: 再javaScript中,对象和函数同样也是变量。 4.1局部变量:变量在函数内声明,变量为局部作用域,只能在函数内部访问。 function myFunction(){ var age = 20; } 注意:如果在函数内没有声明(即没有使用var关键字),改变量为全局变量。 4.2全局变量 在函数体外定义,即为全局变量。全局变量具有全局作用域,网页中所有脚本和汉数据可以使用。 4.3JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。 原因:变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。 x = 5; // 变量 x 设置为 5 elem = document.getElementById("demo"); // 查找元素 elem.innerHTML = x; // 在元素中显示 x var x; // 声明 x 注意:JavaScript 只有声明的变量会提升,初始化的不会。 var x = 5; // 初始化 x elem = document.getElementById("demo"); // 查找元素 elem.innerHTML = x + " " + y; // 显示 x 和 y var y = 7; // 初始化 y 结果: x 为:5,y 为:undefined y 输出了 undefined,这是因为变量声明 (var y) 提升了,但是初始化(y = 7) 并不会提升,所以 y 变量是一个未定义的变量。 5.变量的生命周期 开始:声明时候的初始化。 结束: 局部变量在函数执行完毕销毁。 全局变量在页面关闭后销毁。 6.JavaScript 严格模式(use strict) “use strict” 指令在 JavaScript 1.8.5 (ECMAScript5) 中新增。 它不是一条语句,但是是一个字面量表达式,在 JavaScript 旧版本中会被忽略。 “use strict” 指令只允许出现在脚本或函数的开头。 严格模式下你不能使用未声明的变量。 "use strict"; x = 3.14; // 报错 (x 未定义) 不允许删除变量或对象。 "use strict"; var x = 3.14; delete x; 不允许删除函数。 "use strict"; function x(p1, p2) {}; delete x; // 报错 不允许变量重名。 "use strict"; function x(p1, p1) {}; // 报错 不允许使用8进制,转义字符等。 为什么使用严格模式? 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为. 严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。 另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。 02.数据类型 1.javaScript数据类型分为: 值类型(基本类型)/原始数据类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。 引用数据类型:对象(Object)、数组(Array)、函数(Function)。 2.String(字符串) 字符串可以使用单引号或双引号。 比较字符串是否相等用双等号。 2.1字符串对象 第一种:var s=“sag”;(小String,属于String类型) 第二种:var a2= new String(“ab”);(大String,属于Object类型) Sting是一个内置的类,可以直接使用。 3.Number(数字) javaScript只有一种数字类型,可以带小数点,也可以不带。很大的数据可以用科学计数法表示。 var x = 33; var x = 33.00; var y = 12e6; var y = 12e-6; 3.1注意:NaN,表示Not a Number不是一个数字,但是属于Number类型。 Infinity,表示无穷大。 0,-1,123,…小数,复数,无穷大都是属于number类型。 当除数为0时,结果为无穷大。 isNaN(数据):结果为true表示不是一个数字。 parseInt()函数:可以将字符串自动转换成数字。保留Int。 parseFloat()函数:将字符串转换成数字。 Math.Ceil()函数:向上取整。2.1会变为3。 4.Boolean数据类型 布尔(逻辑)只能有两个值:true 或 false。 注意:当某个地方一定是boolean类型时,会自动转换成boolean类型。例如if后面的括号。 NaN,0,"",null,undefined会自动转换成false。 5.Undefined 和 Null Undefined 这个值表示变量不含有值。 可以通过将变量的值设置为 null 来清空变量。 6.typeof动态的求出变量的数据类型 alert(typeof null);//Object alert(typeof NaN);//number alert(typeof undefined);//undefined 7.用”new“声明变量类型 var x = new Stirng; var y = new Number; var person = new Object; var flag = new Boolean; 8.JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。 03.输出语句 javaScript可以通过不同的方式输出数据: 1.使用window.alert()弹出警告框,window可以省略。 2.使用document.write()方法将内容写到HTML文档中。 3.使用innerHTML写入到HTML元素中。 4.使用console.log()写入到浏览器控制台,console可以省略。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>输出语句</title> </head> <body> <p id = "one" ></p> <script> var x = prompt("请输入一个数据:"); var y = 3.1; alert(x); document.write(x+y); var temp = document.getElementById("one"); temp.innerHTML=x+y; console.log(x+y); </script> </body> </html> 输入数据: 可以用prompt(”请输入你的姓名:“)在页面弹出一个输出框。数据为字符串类型。 04.数组 1.javaScript数组为一个无限大的容器,数组类型可以是不一致。 2.创建方式: var nums = new Array(); news[0] = 11; news[1] = "22"; //或者 var computerBrand = new ("ASUS","DELL"); 3.数组的遍历 3.1for循环遍历 3.2for/in循环遍历 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数组的遍历</title> </head> <body> <script> var arr = new Array(); arr[0]="MengYangChen"; arr[1]="20"; arr[2]="boy"; for(var i = 0;i<arr.length;i++){ document.write(arr[i]+"<br>"); } for(var i in arr){ document.write(arr[i]+"<br>"); } </script> </body> </html> 05.函数 JavaScript 函数语法 1.函数就是包裹在花括号中的代码块,前面使用了关键词 function: function functionname() { // 执行代码 } 或者 functionname=function{ //执行代码 } 2.具有参数的函数 function myFunction(var1,var2) { //代码 } 3.具有返回值的参数 function myFunction() { var x=5; return x; } document.getElementById("demo").innerHTML=myFunction(); function myFunction(a,b) { return a*b; } document.getElementById("demo").innerHTML=myFunction(4,3); 06.对象 1.avaScript 中的所有事物都是对象:字符串、数值、数组、函数…。 此外,JavaScript 允许自定义对象。 对象也是一个变量。对象可以包含多个值。 var computer ={brand:"ASUS",color:"silveryWhite",price:"13"}; 2.可以使用字面量来定义和创建 JavaScript 对象: var person ={ firstName : "YangChen", lastName :"Meng", age: 20, gender : "men" }; 键值对通常写法为 name : value (键与值以冒号分割)。 键值对在 JavaScript 对象通常称为 对象属性。 3.访问对象属性: person.lastName; person["lastName"]; 4.对象方法 4.1创建对象方法: methodName : function() { // 代码 } 案例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>对象</title> </head> <body> <span id = "demo"></span> <script> var person ={ firstName :"YangChen", lastName :"Meng", age: 20, gender : "men", fullName : function() { return this.firstName + " " + this.lastName; } }; document.getElementById("demo").innerHTML=person.fullName(); </script> </body> </html> 5.访问对象的方法 objectName.methodName(); 6.创建JavaScript对象 新建对象有两种不同的方法: 6.1使用 Object 定义并创建对象的实例。 在 JavaScript 中,几乎所有的对象都是 Object 类型的实例,它们都会从 Object.prototype 继承属性和方法。 Object 构造函数创建一个对象包装器。 Object 构造函数,会根据给定的参数创建对象,具体有以下情况: 如果给定值是 null 或 undefined,将会创建并返回一个空对象。 如果传进去的是一个基本类型的值,则会构造其包装类型的对象。 如果传进去的是引用类型的值,仍然会返回这个值,经他们复制的变量保有和源对象相同的引用地址。 当以非构造函数形式被调用时,Object 的行为等同于 new Object()。 <script> var person=new Object(); person.firstname="John"; person.lastname="Doe"; person.age=50; person.eyecolor="blue"; document.write(person.firstname + " is " + person.age + " years old."); </script> 6.2使用函数来定义对象,然后创建新的对象实例。(对象构造器) <script> function person(firstname,lastname,age,eyecolor){ this.firstname=firstname; this.lastname=lastname; this.age=age; this.eyecolor=eyecolor; this.changeName=changeName; function changeName(name) { this.lastname=name; } } myFather=new person("John","Doe",50,"blue"); document.write(myFather.firstname + " is " + myFather.age + " years old."); </script> ​ 有了对象构造器,就可以创建新的对象: var myFather=new person("John","Doe",50,"blue"); var myMother=new person("Sally","Rally",48,"green"); 07.事件 1.HTML 事件是发生在 HTML 元素上的事情。 2.在事件触发时 JavaScript 可以执行一些代码。 <button onclick="displayDate()">点这里</button> <script> function displayDate(){ document.getElementById("demo").innerHTML=Date(); } </script> <p id="demo"></p> 3.常见的HTML事件 下面是一些常见的HTML事件的列表: onchange HTML 元素改变,下拉列表选中改变,或文本框内容改变。 onclick 用户点击 HTML 元素 onmouseover 用户在一个HTML元素上移动鼠标 onmouseout 用户从一个HTML元素上移开鼠标 onkeydown 用户按下键盘按键 onload 浏览器已完成页面的加载 在js中,doucument.getElementById(‘ 标签的id’);发生一个交互事件时,js和html是分离的,获取标签对象。 08.DOM 1.文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 w3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。 DOM树 文档:一个页面就是一个文档,DOM中使用document表示。 元素:页面中的所有标签都是元素,DOM中使用element表示。 节点︰网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示。 2.获取元素 2.1根据ID获取 使用getElementById()方法可以获取带有ID的元素对象,找不到返回null。 console.dir()方法: 打印我们返回元素的对象,更好的查看里面的属性和方法。 2.2根据标签名获取 使用getElementsByTagName()方法,可以返回带有指定标签名的对象的集合。 得到的元素是动态的。 如果页面中只有一个元素,返回的还是一个伪数组。 如果没有该元素返回空的伪数组。 可以指定父元素,获取父元素内部所有指定标签名的子元素。 注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己。即先获取父元素,再根据父元素获取,子元素。 如: var ol = document.getElementsByTagName("ol"); console.log(ol[0].getElementsByTagName("li"); 根据类名获取元素 document.getElementsByClassName(“box”); 返回一个伪数组。 根据指定选择器返回第一个元素对象 document.querySelector(“选择器”); 根据指定选择器返回集合 document.querySelectorAll(“选择器”); var b = document.querySelectorAll(".two"); b[0].innerHTML="常"; b[1].innerHTML="有意思!"; 获取body和html标签 document.body; document.documentElement;//html 或则通过添加id,class…。 事件 JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。 简单理解︰触发—响应机制。 网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。 事件有三部分组成:(也称事件三要素) 事件源 <button id="btn">ff</button> var btn = document.getElementById("btn); 事件类型 如何触发,什么事件,比如鼠标点击(onclick)还是鼠标经过,还是键盘按下。 事件处理程序: 通过函数完成 执行事件的步骤。 1.获取事件源。 2.注册事件(绑定事件)。 btn.onclick=function(){ } 3.添加事件处理程序。 操作元素 JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性。 改变元素的内容 innerTest和innerHTML innerTest(非标准)不识别HTML的标签,而innerHTML识别。 可以获取里面的内容,innerTest会去除空格和换行,而innerHTML保留空格和换行。 常用元素的属性操作 先获取标签元素对象,然后通过对象.属性来修改属性。 分时显示不同图片,显示不同的问候语。 1.获取当前时间。 表单元素的属性操作 利用DOM可以操作如下表单元素的属性: type,value,checked,selected,disabled <body> <button>点击我</button> <input type="text" value="输入内容"> <script> //1.获取元素 var btn = document.querySelector("button"); var input = document.querySelector("input"); //注册事件 btn.onclick = function () { input.value = '他点击我了'; //btn.disabled=true;//禁用按钮 this.disabled = true;//指向当前对象,事件函数的调用者 } </script> </body> 点击按钮密码框切换为文本框,并可以查看密码明文 1.思路将密码框改为文本框 <body> <div class="box"> <label for="pwd"> <img src="#" alt="" id="eye"/> </label> <input type="password" name="" id="pwd"> </div> <script> var eye = document.getElementById('eye'); var pwd = document.getElementById('pwd'); //注册事件 var flag =0; eye.onclick = function () { if(flag = 0 ){ pwd.type= "text"; this.src="#1"; flag = 1; } else { pwd.type = 'password'; this.src="#"; flag = 0 ; } } </script> </body> 样式属性操作 我们可以通过js修改元素的大小,颜色,位置样式 1.element.style 行内样式操作 js修改style样式操作,产生的是行内样式,css权重比较高。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>样式属性</title> <style type="text/css"> div{ width: 200px; height: 200px; background-color: red; } </style> </head> <body> <div></div> <script> //1.获取元素 var div = document.querySelector('div'); //2.注册事件,处理程序 div.onclick = function () { this.style.backgroundColor="blue"; this.style.width = "300px"; } </script> </body> 2.element.className 类名样式操作 通过写好样式,然后通过获取元素,在响应事件后,将元素的类名赋我们事先绑定好的样式来改变元素的样式。 .change{ ...... } var test = document.querySelector('div'); test.onclick = function(){ this.className = 'change'; } 如果样式修改较多,可以采用这种方式。 原先的类名会被覆盖。 如果想要保留原先的类名,可以采用以下方式: this.className = 'first change'; 获取自定义属性值 1.element.属性 获取属性值 获取内置属性值(元素本身自带的属性) 2.element.getAttribute('属性‘); 可以获取自定义属性,程序员自定义的属性 3.设置属性值 element.属性 = '值'; element.setAttribute('属性','值');//主要用于自定义属性 4.移除属性 element.removeAttribute('属性'); H5的自定义属性 自定义属性的目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。 自定义属性获取是通过getAttribute('属性’)获取。 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。 <div getTime="20"><div> var di = document.querySelector('div'); 如何区分是自定义属性还是内置属性呢? H5规定自定义属性data-开头做为属性名并且赋值。 比如: <div data-index ="1"></div> 或者使用Js设置 element.setAttribute(‘data-index’,2); H5获取自定义属性的方法 1.element.getAttribute('data-indexd data-list-name=andy'); 2.H5新增element.dataset.index 或者element.dataset['index'] ie11才开始支持。 dataset是一个集合里面存放了所有以data开头的自定义属性。 如果自定义属性里面有多个-连接的单词,我们获取的时候才去驼峰命名法 ```java div.getAtrribute("data-list-name"); div.dataset.listName; 节点操作 为什么学节点操作? 获取元素通常使用两种方式: 1.利用DOM提供的方法获取元素 document.getElementById(); document.getElementByTagName(); document.querySelector(); 缺点:逻辑性不强,繁琐。 2.利用节点的层次关系获取元素(父子兄弟关系) 逻辑性强,但是兼容性差 一般节点至少拥有nodeType(节点类型),nodeName(节点名称)和nodeValue(节点值)这三个基本属性。 元素节点nodeType 为1 属性节点nodeType为2 文本节点nodeType 为3(文本节点包含文字、空格、换行等) 一般获取元素节点。 <div> <span></span> <div> 3.节点层级 利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。 父级节点 得到与元素最近的节点。找不到父节点则返回为null。 node.parentNode; 子节点 得到所有的子节点,包括元素节点,文本节点,等 parentNode.ChildNodes(标准) parentNode.ChildNodes返回包含指定节点的子节点的集合,改集合为即时更新的集合。 如果只想获得里面的元素节点,则需要专门处理,所以我们一般不提倡使用。 var ul =document. queryselector ( 'ul'); for(var i = 0; i < ul.childNodes.length; i++){ if (ul.childNodes[i].nodeType -- 1){ // ul.childNodes[i]是元素节点 console.log(ul.childNodes[i]); } 为了解决这个问题还有一种非标准的用法。 parentNode.children(非标准) parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(这个是我们重点掌握的)。 虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用。 第一个节点和最后一个节点 父节点.firstChild 父节点.lastChild 第一个子元素和最后一个元素节点 父节点.firstElementChild 父节点.LastElementChild 4.三种动态创建元素的区别 4.1document.write() document.write("<div>fa<div>"): 会导致页面重绘:document.write是直接将内容写入页面的内容流,但是文档流执行完毕,再使用该语句,则它会导致页面全部重绘。 4.2 element.innerHTML element.innerHTML="<a href="#">dfa</a>"; 4.3 document.createElement(); var a = document.createElement(); element.appendChild(a); innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘. innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂 . createElement(创建多个元素效率稍低一点点,但是结构更清晰 09.BOM 什么是BOM对象? Brower Object Model,指的是浏览器对象模型。 作用:操作浏览器窗口及窗口上的空间,实现用户和页面的动态交互。如返回,前进,刷新,地址栏,关闭窗口,缩放窗口等。 浏览器对象:指的是浏览器提供的一系列内置对象的统称。 BOM浏览器对象模型:各内置对象之间按照某种层次组织起来的模型的统称。 document(文档对象)﹔也称为DOM对象,是HTML页面当前窗体的内容,同时也是JavaScript重要组成部分之一。 history(历史对象)﹔主要用于记录浏览器的访问历史记录,也就是浏览网页的前进与后退功能。 location(地址栏对象)﹔用于获取当前浏览器中URL地址栏内的相关数据。navigator(浏览器对象)﹔用于获取浏览器的相关数据,例如浏览器的名称、版本等,也称为浏览器的嗅探器。 screen(屏幕对象):可获取与屏幕相关的数据,例如屏幕的分辨率等。 window对象 window对象是BOM中所有对象的核心,同时也是BOM中所有对象的父对象。定义在全局作用域中的变量、函数以及JavaScript中的内置函数都可以被window对象调用。 window对象的属性和方法: setTimeout()方法在执行一次后即停止了操作;setlnterval()方法一旦开始执行,在不加干涉的情况下,间歇调用将会一直执行到页面关闭为止。 若要在定时器启动后,取消该操作,可以将setTimeout()的返回值(定时器ID)传递给clearTimeout()方法;或将setlnterval()的返回值传递给clearIntexal()方法。 location对象 location对象提供的用于改变URL地址的方法,所有主流的浏览器都支持。 利用location.href可以跳转到指定的url地址中。 history对象 history对象可对用户在浏览器中访问过的URL历史记录进行操作。 出于安全方面的考虑,history对象不能直接获取用户浏览过的URL,但可以控制浏览器实现“后退”和“前进”的功能。 navigator对象 navigator对象提供了有关浏览器的信息,主流浏览器中存在的属性和方法如下: screen对象 screen对象用于返回当前渲染窗口中与屏幕相关的属性信息,如屏幕的宽度和高度等。 If your happiness depends on what somebody else does, I guess you do have a problem. 如果你的快乐与否取决于别人做了什么,我想,你真的有点问题。

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

Docker进阶-快速扩容

1、命令方式 在创建好的Swarm集群中运行nginx服务,并使用--replicas参数指定启动的副本数。 docker service create --replicas 3 -p 80:80 --name nginx nginx:latest 或者 docker service create -p 80:80 --name nginx nginx:latest docker service scale nginx=3 docker service ls #查看副本情况 2、portainer方式 可以使用portainer的方式在web界面上创建服务并指定副本数,同时可以随时动态增减副本数。

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

快速了解云计算

云是将服务器虚拟化,形成虚拟资源池,相比于以前的物理机更加节省资源成本,便于管理。云是计算、存储、网路资源池化的概念。我们每天使用的搜索引擎、邮箱、网盘,就是很标准的云,而这大多都是免费的。云是对互联网的升级,意味着互联网并不仅仅是存储数据,而是为你提供某种服务。云计算、云存储、云服务、云平台等就是利用云通过一堆机器经过网络组合到一起的不同形式,是云下面的子概念。总的来说就是,云服务=云平台,云服务=云计算+云存储!云计算随着互联网的发展,云服务和应用也变得越来越复杂,需要支持更多的用户、需要更强的计算能力、需要更加稳定安全等等。用传统的方法比如配备更加完备的IT运维部门将会耗费大量的精力和财力,而且对于大公司来说需求仍会难以满足,对于那些中小规模的企业,甚至个人创业者来说,创造软件产品的运维成本就更加难以承受了。而“云计算”出现以后就可以完美的解决这个问题。将应用部署到云端后,就不必再关注那些令人头疼的硬件和软件问题,它们会由云服务提供商的专业团队去解决。使用的是共享的硬件,只要按照你的需求买了这个云服务就可以使用了关于软件的更新,资源的按需扩展都能自动完成。云计算具有大规模分布式、虚拟化、高可用性和扩展性、按需服务更加经济及安全五大特点。云服务和云平台云计算将我们传统的IT工作转为以网络为依托的云平台运行,而云服务则是在这个云平台上发布出来的供用户使用的产品服务。云平台比较通俗的可以理解为云计算服务商有N多服务器和存储设备,用信息技术将其整合为一种提供存储服务的平台,这个平台以租赁的方式对外提供服务。云服务常规上是指通过网络以按需、易扩展的方式获得所需服务。简单来说,云服务可以将企业所需的软硬件、资料都放到网络上,在任何时间、地点,使用不同的IT设备互相连接,实现数据存取、运算等目的。云服务的两种主要形式:公有云 & 私有云公有云(Public Cloud):SaaS、PaaS和IaaS公有云是最基础的服务,成本较低,是指多个客户可共享一个服务提供商的系统资源,他们毋须架设任何设备及配备管理人员,便可享有专业的IT服务,这对于中小企来说,无疑是一个降低成本的好方法。私有云(Private Cloud):虽然公有云成本低,但是大企业(如金融、保险行业)为了兼顾行业、客户私隐,不可能将重要数据存放到公共网络上,故倾向于架设私有云端网络。私有云的运作形式,与公共云类似。然而,架设私有云却是一项重大投资,企业需自行设计数据中心、网络、存储设备,并且拥有专业的顾问团队。企业管理层必须充分考虑使用私有云的必要性,以及是否拥有足够资源来确保私有云正常运作。**云存储**云存储官方定义是一个以数据存储和管理为核心的云计算系统。即是指通过集群应用、网格技术或分布式文机房集中监控系统件系统等功能,将网络中大量各种不同类型的存储设备通过应用软件集合起来协同工作,共同对外提供数据存储和业务访问功能的一个系统。云存储设备横向扩展的方式让存储系统具有了无限扩展的能力,能够实现控制器与硬盘的同时扩展,即性能与容量可以同时实现线性扩展,云存储一般可以分为私有云存储、公有云存储。通过云存储模式,私有网络的资源和数据得到链接,并且这些资源和数据放到了公有云服务提供商共享公共网络上。这些数据一方面创造着无限价值,但是另一方面一旦发生某云计算平台泄漏了用户的数据隐私,或是数据在云端存储的过程中由于设备故障而导致大量丢失,亦或是数据在传输过程中被其他用户任意篡改,这种后果所造成的后果是难以估量的。因此,在云时代,关于这些方面的问题也是非常值得注意的。

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

guava快速入门(二)

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 guava类似Apache Commons工具集 Collection 不可变集合 不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节); 不可变对象因为有固定不变,可以作为常量来安全使用。 JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但: 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景; 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的; 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。 创建不可变集合方法: copyOf方法,如ImmutableSet.copyOf(set); of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2); Builder工具 import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class ImmutableDemo { public static void main(String[] args) { ImmutableSet<String> set = ImmutableSet.of("a", "b", "c", "d"); ImmutableSet<String> set1 = ImmutableSet.copyOf(set); ImmutableSet<String> set2 = ImmutableSet.<String> builder().addAll(set).add("e").build(); ImmutableList<String> list = set.asList(); System.out.println("set:"+set); System.out.println("set1:"+set1); System.out.println("set2:"+set2); //set.add("f");//java.lang.UnsupportedOperationException } } 返回: set:[a, b, c, d] set1:[a, b, c, d] set2:[a, b, c, d, e] 新型集合类 Multiset Multiset可统计一个词在文档中出现了多少次 import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.Multiset; public class MultiSetDemo { public static void main(String[] args) { Multiset<String> set = LinkedHashMultiset.create(); set.add("a"); set.add("a"); set.add("lucas"); set.add("lucas"); set.setCount("a", 5); // 添加或删除指定元素使其在集合中的数量是count System.out.println(set); System.out.println(set.count("a")); // 给定元素在Multiset中的计数 System.out.println(set.size()); // 所有元素计数的总和,包括重复元素 System.out.println(set.elementSet().size()); // 所有元素计数的总和,不包括重复元素 set.clear(); // 清空集合 System.out.println(set); } } 返回: [a x 5, lucas x 2] 5 7 2 [] Multimap Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。 import java.util.Collection; import java.util.Map; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; public class MultiMapDemo { public static void main(String[] args) { Multimap<String, Integer> map = HashMultimap.create(); // Multimap是把键映射到任意多个值的一般方式 map.put("a", 1); // key相同时不会覆盖原value map.put("a", 2); map.put("a", 3); map.put("b", 1); map.put("b", 2); System.out.println(map); // {a=[1, 2, 3]} System.out.println(map.get("a")); // 返回的是集合 System.out.println(map.size()); // 返回所有”键-单个值映射”的个数,而非不同键的个数 System.out.println(map.keySet().size()); // 返回不同key的个数 Map<String, Collection<Integer>> mapView = map.asMap(); System.out.println(mapView); } } 返回: {a=[1, 2, 3], b=[1, 2]} [1, 2, 3] 5 2 {a=[1, 2, 3], b=[1, 2]} BiMap BiMap import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; public class BitMapDemo { public static void main(String[] args) { BiMap<String, String> biMap = HashBiMap.create(); biMap.put("sina", "sina.com"); biMap.put("qq", "qq.com"); biMap.put("sina", "sina.cn"); // 会覆盖原来的value /* * 在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException异常 * 如果对特定值,你想要强制替换它的键,请使用 BiMap.forcePut(key, value) */ // 抛出异常java.lang.IllegalArgumentException: value already present: qq.com //biMap.put("tecent", "qq.com"); biMap.forcePut("tecent", "qq.com"); // 强制替换key System.out.println(biMap); System.out.println(biMap.inverse()); // 翻转value-key System.out.println(biMap.inverse().get("sina.cn")); // 通过value找key System.out.println(biMap.inverse().inverse() == biMap); // true } } 返回: {sina=sina.cn, tecent=qq.com} {sina.cn=sina, qq.com=tecent} sina true Table Table它有两个支持所有类型的键:”行”和”列”。 import java.util.Set; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; public class TableDemo { public static void main(String[] args) { // 记录学生在某门课上的成绩 Table<String, String, Integer> table = HashBasedTable.create(); table.put("jack", "java", 100); table.put("jack", "c", 90); table.put("mike", "java", 93); table.put("mike", "c", 100); Set<Table.Cell<String, String, Integer>> cells = table.cellSet(); for (Table.Cell<String, String, Integer> cell : cells) { System.out.println(cell.getRowKey() + " " + cell.getColumnKey() + " " + cell.getValue()); } System.out.println("----------------------"); System.out.println(table.row("jack")); System.out.println(table); System.out.println(table.rowKeySet()); System.out.println(table.columnKeySet()); System.out.println(table.values()); } } 返回: mike java 93 mike c 100 jack java 100 jack c 90 ---------------------- {java=100, c=90} {mike={java=93, c=100}, jack={java=100, c=90}} [mike, jack] [java, c] [93, 100, 100, 90] Collections2 filter():只保留集合中满足特定要求的元素 import java.util.Collection; import java.util.List; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; public class FilterDemo { public static void main(String[] args) { List<String> list = Lists.newArrayList("moon", "dad", "refer", "son"); Collection<String> palindromeList = Collections2.filter(list, input -> { return new StringBuilder(input).reverse().toString().equals(input); // 找回文串 }); System.out.println(palindromeList);//palindromeList 回文,也叫做镜文,正写倒写一样,如mam } } 返回: [dad, refer] transform():类型转换 import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Set; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Sets; public class TransformDemo { public static void main(String[] args) { Set<Long> times = Sets.newHashSet(); times.add(91299990701L); times.add(9320001010L); times.add(9920170621L); Collection<String> timeStrCol = Collections2.transform(times, new Function<Long, String>() { @Override public String apply( Long input) { return new SimpleDateFormat("yyyy-MM-dd").format(input); } }); System.out.println(timeStrCol); } } 返回: [1970-04-19, 1970-04-26, 1972-11-23] 多个Function组合 import java.util.Collection; import java.util.List; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; public class TransformDemo2 { public static void main(String[] args) { List<String> list = Lists.newArrayList("abcde", "good", "happiness"); // 确保容器中的字符串长度不超过5 Function<String, String> f1 = new Function<String, String>() { @Override public String apply( String input) { return input.length() > 5 ? input.substring(0, 5) : input; } }; // 转成大写 Function<String, String> f2 = new Function<String, String>() { @Override public String apply( String input) { return input.toUpperCase(); } }; Function<String, String> function = Functions.compose(f1, f2); Collection<String> results = Collections2.transform(list, function); System.out.println(results); } } 返回: [ABCDE, GOOD, HAPPI] 集合操作:交集、差集、并集 import java.util.Set; import com.google.common.collect.Sets; public class CollectionsDemo { public static void main(String[] args) { Set<Integer> set1 = Sets.newHashSet(1, 2, 3, 4, 5); Set<Integer> set2 = Sets.newHashSet(3, 4, 5, 6); Sets.SetView<Integer> inter = Sets.intersection(set1, set2); // 交集 System.out.println(inter); Sets.SetView<Integer> diff = Sets.difference(set1, set2); // 差集,在A中不在B中 System.out.println(diff); Sets.SetView<Integer> union = Sets.union(set1, set2); // 并集 System.out.println(union); } } 返回: [3, 4, 5] [1, 2] [1, 2, 3, 4, 5, 6]

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

guava快速入门(三)

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 guava类似Apache Commons工具集 Cache 缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。 Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。 Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。 通常来说,Guava Cache适用于: 你愿意消耗一些内存空间来提升速度。 你预料到某些键会被查询一次以上。 缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。 如果这不符合你的需求,请尝试Memcached这类工具) Guava Cache有两种创建方式: cacheLoader callable callback LoadingCache是附带CacheLoader构建而成的缓存实现 import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; public class LoadingCacheDemo { public static void main(String[] args) { LoadingCache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) // 最大缓存数目 .expireAfterAccess(2, TimeUnit.SECONDS) // 缓存1秒后过期 .build(new CacheLoader<String, String>() { @Override public String load(String key) throws Exception { return key; } }); cache.put("j", "java"); cache.put("c", "cpp"); cache.put("s", "scala"); cache.put("g", "go"); try { System.out.println(cache.get("j")); TimeUnit.SECONDS.sleep(1); System.out.println(cache.get("s")); // 1秒后 输出scala TimeUnit.SECONDS.sleep(2); System.out.println(cache.get("s")); // 2秒后 输出s } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } } } 返回: java scala s 回调: import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; public class CallbackDemo { public static void main(String[] args) { Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) .expireAfterAccess(1, TimeUnit.SECONDS) .build(); try { String result = cache.get("java", () -> "hello java"); System.out.println(result); } catch (ExecutionException e) { e.printStackTrace(); } } } refresh机制:- LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。- CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value- CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache 并发 ListenableFuture 传统JDK中的Future通过异步的方式计算返回结果:在多线程运算中可能或者可能在没有结束返回结果,Future是运行中的多线程的一个引用句柄,确保在服务执行返回一个Result。 ListenableFuture可以允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Future是不支持的。 import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; public class ListenableFutureDemo { public static void main(String[] args) { // 将ExecutorService装饰成ListeningExecutorService ListeningExecutorService service = MoreExecutors. listeningDecorator(Executors.newCachedThreadPool()); // 通过异步的方式计算返回结果 ListenableFuture<String> future = service.submit(() -> { System.out.println("call execute.."); return "task success!"; }); // 有两种方法可以执行此Future并执行Future完成之后的回调函数 future.addListener(() -> { // 该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行 try { System.out.println("result: " + future.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }, service); Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess( String result) { System.out.println("callback result: " + result); } @Override public void onFailure(Throwable t) { System.out.println(t.getMessage()); } }, service); } } 返回: call execute.. result: task success! callback result: task success! IO import java.io.File; import java.io.IOException; import java.util.List; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.io.Files; public class FileDemo { public static void main(String[] args) { File file = new File(System.getProperty("user.dir")); System.out.println(file.getName()); System.out.println(file.getPath()); } // 写文件 private void writeFile(String content, File file) throws IOException { if (!file.exists()) { file.createNewFile(); } Files.write(content.getBytes(Charsets.UTF_8), file); } // 读文件 private List<String> readFile(File file) throws IOException { if (!file.exists()) { return ImmutableList.of(); // 避免返回null } return Files.readLines(file, Charsets.UTF_8); } // 文件复制 private void copyFile(File from, File to) throws IOException { if (!from.exists()) { return; } if (!to.exists()) { to.createNewFile(); } Files.copy(from, to); } } 返回: collection-others D:\GITHUB\java\code\test01\collection-others 参考:Google Guava官方教程(中文版)guava-importnew

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

[jvm]jvm快速入门

本篇以jdk1.7为例 jvm内存结构 堆内存 方法区 jvm栈 程序计数器 本地方法栈如图: 使用processon作图 所以,这里可以看到jvm内存三大主要结构 方法区 堆区 栈区 常用jvm控制参数 -Xms 设置堆的最小空间大小。 -Xmx 设置堆的最大空间大小。 -XX:NewSize 设置新生代最小空间大小。 -XX:MaxNewSize 设置新生代最大空间大小。 -XX:PermSize 设置永久代最小空间大小。 -XX:MaxPermSize 设置永久代最大空间大小。 -Xss 设置每个线程的堆栈大小。 一张图来了解如何通过参数来控制各区域的内存大小 简单介绍每个区域的作用 Java堆(Heap)对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。 根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。 方法区(Method Area)方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。 Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。 根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 程序计数器(Program Counter Register) 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 JVM栈(JVM Stacks)与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。 其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。 本地方法栈(Native Method Stacks) 本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 参考自《深入理解Java虚拟机:JVM高级特性与最佳实践 作者:周志明》 JVM (Java Virtual Machine)

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

docker快速部署gitlab

docker安装gitlabhttps://docs.gitlab.com/omnibus/docker/使用文档:https://docs.gitlab.com.cn/ce/gitlab-basics/README.htmlgit使用:http://blog.jobbole.com/25775/ 拉取镜像:docker pull gitlab/gitlab-ce 运行gitlab sudo docker run --detach \ --hostname 10.39.10.223 \ --publish 443:443 --publish 80:80 --publish 2222:22 \ --name gitlab \ --restart always \ --volume /data0/gitlab/config:/etc/gitlab \ --volume /data0/gitlab/logs:/var/log/gitlab \ --volume /data0/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest 运行成功后,即可通过80访问页面,2222为ssh端口。 配置gitlab服务器的访问地址修改gitlab的配置文件vi /data0/gitlab/config/gitlab.rb 配置http协议所使用的访问地址,此处为主机ip地址: external_url 'http://10.39.10.223' 修改gitlab.rb配置文件之后,重启容器。或者在容器里执行gitlab-ctl reconfigure命令 http://10.39.3.23 Command line instructions Git global setup git config --global user.name "dataqa"git config --global user.email "249016681@qq.com" Create a new repository git clone git@10.39.10.223:dataqa/te.gitcd tetouch README.mdgit add README.mdgit commit -m "add README"git push -u origin master Existing folder cd existing_foldergit initgit remote add origin git@10.39.3.23:dataqa/te.gitgit add .git commit -m "Initial commit"git push -u origin master Existing Git repository cd existing_repogit remote add origin git@10.39.3.23:dataqa/te.gitgit push -u origin --allgit push -u origin --tags

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

Python快速入门_1

注释 # 用#号字符开头注释单行 """ 三个引号可以注释多行 三个引号可以注释多行 三个引号可以注释多行 """ 原始数据类型和运算符 (1)整型 #整数 3 #=>3 (2)算术运算 #加法 1+1 #=>2 #减法 8-1 #=>7 #乘法 10*2 #=>20 #除法 !!!结果自动转换成浮点数 35/5 #=>7.0 5/3 #=>1.6666666666666667 #整数除法 !!!结果向下取整 5//3 #=>1 5.0//3.0 #=>1.0 -5//3 #=>-2 5//(-3) #=>-2 -5.0//3.0 #=>-2.0 #浮点数的运算结果也是浮点数 3*2.0 #=>6.0 #取模 7%3 #=>1 #x的y次方 2**4 #=>16 #用括号决定优先级 (1+3)*2 #=>8 (2)布尔运算与比较运算 #布尔值 True #=>True False #=>False #用not取非 not True #=>False not False #=>True #逻辑运算符,注意and和or都是小写 True and False #=>False True or False #=>True #整数也可以当做布尔值 0== False #=>True 2==True #=>False 1==True #=>True #用==判断相等 1==1 #=>True 2==1 #=>False #用!=判断不等 1!=1 #=>False 1!=2 #=>True #比较大小 1<10 #=>True 2<=2 #=>True 2>=2 #=>True (4)字符串运算 #字符串用单引号双引号都可以 '这个是字符串' "这个也是字符串" #用加号连接字符串 'Hello '+'World' #=>'Hello World' #字符串可以被当做字符列表 'This is a string'[0] #=>'T' #用format来格式化字符串 "{} can be {}".format("string",'interpolated') #=>'string can be interpolated' #可以重复参数以节省时间 "{0} be nimble,{0} be quick,{0} jump over the {1}".format("jack","candle stick") #=>'jack be nimble,jack be quick,jack jump over the candle stick' #如果不想数参数可以用关键词 "{name} wants to eat {food}".format(name='Bob',food='lasagna') #=>'Bob wants to eat lasagna' #如果你的python3程序也要运行在Python2.5以下环境运行,也可以用老式的格式化语法 "%s can be %s the %s way"%('strings','interpolater','old') #=>'strings can be interpolater the old way' (2)None #None是一个对象 None #当与None进行比较时不要用==,要用is,is是用来比较两个变量是否指向同一个对象 'etc' is None #=>False None is None #=>True #None,0,空字符串,空列表,空字典都算是False,其他都是True bool(None) #=>False bool(0) #=>False bool("") #=>False bool({}) #=>False bool([]) #=>False

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

Visual Basic快速入门

Basic语言的全名是Beginner's All-purpose Symbolic Instruction Code(初学者通用的符号指令代码),是几十年前流行过的一门语言。我高中时候一门数学选修课中使用的也是Basic语言。我还记得当时我为了使用Basic语言,还从网上下了一个简陋的QBasic工具。当时第一次接触编程的我对编程语言充满了兴趣。当然在现在,Basic语言已经基本没什么用了。现在还在使用的Basic语言大概就是微软的Visual Basic了。今天就来介绍一下Visual Basic语言。需要注意的是,VB语言运行在微软的CLR上,所以如果你对C#比较熟悉的话,学习VB就很简单了。 HelloWorld 照例,第一个项目自然应该是HelloWorld。打开Visuall Studio,创建一个VB项目,然后就会出现如下图所示的代码。 HelloWorld 来解释一下HelloWorld的代码。首先第一行是导入类库,和C#、java的import语句是一个道理。然后下面定义了一个Program模块,其中定义了Main函数,在函数中输出Hello World。在VB中,不使用大括号作为块分隔符,而是使用End语句来结束块作用域。 Imports System Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 基本数据类型 由于VB和C#都是运行在CLR上的语言,所以其实它们的基本类型是一样的,都有有/无符号的各种长度整数、单精度双精度浮点数、布尔类型、字符和字符串等类型。下面的代码仅列出几个常用的。 Public Class DataType Sub DataType() Dim b As Byte Dim i As Integer Dim s As Single Dim d As Double Dim c As Char Dim str As String Dim bool As Boolean b = 100 i = 1000 s = 1.5 d = 3.1415926 c = "c"c str = "abc" bool = True End Sub End Class 变量和常量 VB的变量定义也和C系语言不同,使用的是Dim 变量名 As 变量类型的语法进行定义。变量必须先定义才能使用。如果想同时定义多个变量,可以这么写。 Dim i, j As Integer 如果想在定义变量的同时初始化,可以这样。 Dim bool As Boolean = True 如果要定义常量,可以变量类似,只不过使用Const关键字。 Const cs As Integer = 1000 运算符 先来看看算术运算符。 运算符 用途 例子 ^ 幂运算符 3 ^ 2 = 9 + 加法 - 减法 * 乘法 / 小数除法 3 / 2 = 1.5 \ 整除 3 \ 2 = 1 MOD 取模 6 MOD 4 = 2 然后是比较运算符。这里需要注意的就是VB的相等和不等和其他语言的可能不太一样。 运算符 用途 = 相等 <> 不等 < 小于 > 大于 <= 不大于 >= 不小于 然后是逻辑运算符。 运算符 用途 And 与运算符,不短路求值 Or 或运算符,不短路求值 Not 非运算符 Xor 异或运算符 AndAlso 与运算符,短路求值 OrElse 或运算符,短路求值 IsTrue 是否为真 IsFalse 是否为假 条件语句 If语句 先来看看VB中的If语句,其基本结构是If 条件 Then 执行体 Else 执行体 End If。 Dim num As Integer = 5 If num\2 = 0 Then Console.WriteLine($"{num} is even") Else Console.WriteLine($"{num} is odd") End If 如果需要多重If语句,可以添加ElseIf语句块。 If num = 1 Then Console.WriteLine($"{num} is 1") ElseIf num = 2 Console.WriteLine($"{num} is 2") Else Console.WriteLine($"{num} is other") End If Select语句 Select语句相当于其他语言中的switch语句,如果没有匹配项,会执行Case Else语句块。 Dim c As Char = "c"c Select c Case "a"c Console.WriteLine("a") Case "b"c, "c"c Console.WriteLine("b or c") Case Else Console.WriteLine("others") End Select 循环语句 Do语句循环 Do语句循环有两种结构,第一种是循环条件在前。先来看看Do-While语句,当满足循环条件的时候会继续循环,不满足条件时跳出循环。这里顺便提一下,VB中没有块注释,只有单行注释,以单引号开头,直到句末。 'Do While语句 Dim i = 0 Do While i < 5 If i = 3 Then Exit Do End If Console.Write(i) i += 1 Loop 再来看看Do-Until语句,和Do-While相反,在不满足条件的时候会执行循环,满足条件时跳出循环。 'Do Until语句 i = 0 Do Until i > 5 If i < 3 Then i += 2 Continue Do End If Console.Write(i) i += 1 Loop Do循环的第二种形式就是先执行循环体,然后进行判断,同样有While和Until两种。 i = 0 Do Console.Write(i) i += 1 Loop While i < 5 Console.WriteLine While循环 还有就是传统的While循环。 'While循环 i = 0 While i < 5 Console.Write(i) i += 1 End While For循环 下面是For循环的例子,在For循环中可以使用Step指定步长。 For counter As Integer = 1 To 9 Step 1 Console.Write(counter) Next Foreach循环 Foreach循环用于迭代一个列表中的每一项。 Dim array() as Integer = {1, 2, 3, 4, 5, 6, 7} For Each item As Integer In array Console.Write(item) Next With语句 With语句其实不算循环语句,不过我看的这个VB教程把With语句放到这里说,那我也放到这里好了。With语句在有些语言中也有,主要用途是节省代码数量。比方说有下面这个Person类。 Public Class Person Public Property Name As String Public Property Age As Integer End Class 假如有一个person对象多次出现的话,就可以使用With语句,在With语句中,点访问符默认指向的就是With语句指定的对象。 Dim person As Person = New Person With person .Name = "yitian" .Age = 25 Console.WriteLine($"Person(Name:{.Name}, Age:{.Age})") End With 跳转语句 Exit语句 Exit语句用于结束某个代码块,它的形式如下。想用Exit退出哪个代码块,就写哪个代码块的类型。 Exit { Do | For | Function | Property | Select | Sub | Try | While } Continue语句 Continue语句用于结束当前循环,直接进行下一次循环。它的形式如下,后面跟要继续的代码块类型。 Continue { Do | For | While } Goto语句 最后就是Goto语句,它会直接跳转到指定的标签处。 'Goto语句 GoTo Ending Console.WriteLine("Print something") Ending: Console.WriteLine("This is end.") 数组 先来看看数组定义。VB中的数组比较特殊,定义一个Dim a1(3),其实是下标0-4长度为四的一维数组,这一点要非常注意。 '下标0-9的十个元素的数组 Dim array1(9) As Integer '11X11的二维数组 Dim array2(2, 2) As Integer '定义并初始化数组 Dim array3() = {1, 2, 3, 4, 5} '锯齿数组,也就是数组的数组 Dim array4 As Integer()() = New Integer(1)() {} array4(0) = New Integer() {1, 2} array4(1) = New Integer() {3, 4} 访问数组元素需要使用圆括号,而不是一般语言的方括号。 '初始化一维数组 For i As Integer = 0 To 9 array1(i) = i Next '初始化二维数组 For i = 0 To 2 For j = 0 To 2 array2(i, j) = (i + 1)*(j + 1) Next Next 最后就是遍历数组了,可以使用For循环迭代下标,或者用Foreach循环直接遍历元素。 '显示数组 For Each e In array1 Console.Write(e) Next Console.WriteLine For i As Integer = 0 To 2 For j = 0 To 2 Console.Write(array2(i, j)) Next Console.WriteLine Next For Each e In array3 Console.Write(e) Next Console.WriteLine For i As Integer = 0 To 1 For j = 0 To 1 Console.Write(array4(i)(j)) Next Console.WriteLine Next 函数 Sub函数 回头来看看前面的HelloWorld,其中就有一个Main函数,它是一个Sub函数,也就是没有返回值的函数。 Imports System Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 函数可以按值传参,也可以按引用传参,默认情况下是按值传参。 Function GetParam(ByVal a As Integer, ByRef b As Integer) a = 10 b = 10 Console.WriteLine("Param changed") End Function Function函数 Function函数就是有返回值的函数。在函数中,如果要返回值,可以有两种办法,第一种是使用Return语句,第二种是在函数体中向函数名赋值。 '函数返回值可以用Return语句 Function Return1() As Integer Return 1 End Function '也可以向函数名赋值 Function Return2() As Integer Return2 = 2 End Function 可变参数列表 可变参数列表使用ParamArray声明。 Function PrintIntegers(ParamArray integers As Integer()) For Each i In integers Console.Write(i) Next Console.WriteLine End Function 面向对象编程 类 VB的类和C#的类非常相似,同样有字段、属性等概念。构造函数使用New声明,不需要返回值。析构函数使用Finalize声明,也不需要返回值。 Class Contact ' 字段 Private _name As String Private _tel As String '构造函数 Public Sub New(name As String, tel As String) _name = name _tel = tel End Sub '析构函数 Protected Overrides Sub Finalize() End Sub '属性 Public Property Tel As String Get Return _tel End Get Set _tel = value End Set End Property Public Property Name As String Get Return _name End Get Set(value As String) _name = value End Set End Property '重写方法 Public Overrides Function ToString() As String Return $"Contact(Name:{Name}, Tel:{Tel})" End Function End Class 抽象类和接口 如果一个类的方法含有MustOverride修饰符,那么这个方法就是一个抽象方法。含有抽象方法的类就是抽象类,需要使用MustInherit关键字修饰。 MustInherit Class Shape MustOverride Function GetArea() As Double End Class Interface Color Function GetColor() As String End Interface 继承 继承基类和实现接口的声明必须写在类实现的前面。如果一个方法重写了基类的版本,那么这个方法应该使用Overrides关键字修饰。如果不希望类被其他类继承,可以使用NotInheritable修饰,类似于Java的final关键字或者C#的sealed关键字。如果子类需要调用基类的方法,可以使用MyBase关键字代表基类。 Class Circle Inherits Shape Protected radius As Double Public Sub New(r As Double) radius = r End Sub Public Overrides Function GetArea() As Double Return Math.PI*radius*radius End Function End Class NotInheritable Class RedCircle Inherits Circle Implements Color Public Sub New(r As Double) MyBase.New(r) End Sub Public Function Color_GetColor() As String Implements Color.GetColor Return "Red" End Function End Class 静态成员 静态成员和静态函数使用Shared关键字声明,对于每个类来说Shared成员只会存在一个。 Class MyMath Public Shared PI As Double = 3.1415926 Public Shared Function GetPI As Double Return PI End Function End Class 模块 Module类似于Class,不同之处在于Module不需要实例化,其中的函数可以直接调用,就像静态函数一样。 Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 异常处理 VB的异常处理和C#的一样,都有Try、Catch、Finally部分。 Public Module ExceptionHandling Sub HandleException() Try Throw New ArithmeticException("除数不能为零") Catch ex As ArithmeticException Console.WriteLine($"捕获了数学计算异常:{ex.Message}") Catch ex As Exception Console.WriteLine($"捕获了异常:{ex.Message}") Finally Console.WriteLine("终结代码") End Try End Sub End Module 以上就是VB语言的一些介绍了,希望对大家能有所帮助。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Apache Tomcat

Apache Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Eclipse

Eclipse

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。