首页 文章 精选 留言 我的

精选列表

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

SpringBoot2全家桶,快速入门学习开发网站教程

说明 本系列文章带大家玩转SpringBoot2。 但是学习是一个循序渐进的过程,所以该文章将分为几个小章节讲述。 并且在学习SpringBoot之前需要一定的基础知识 SpringMVC、Spring、MyBatis基础知识 Maven MySQL、Redis 本文章代码建立的环境基础 注:由于环境不同可能会导致代码运行效果不同,请同步环境 开发环境 名称 版本 JDK jdk-12.0.2 IDE Eclipse2019.09 Databases MySQL_v8.0.18 SpringBoot v2.2.2 章节 1.SpringBoot2初体验 2.SpringBoot2编写第一个Co...

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

Docker安装Oracle12C,快速搭建Oracle学习环境

安装说明 1.操作系统CentOS7_x64 2.安装的数据库为Oracle12C 3.已经安装了Docker环境 4.需要检查是否有swap分区,如果没有请设置 安装 1.Docker安装 镜像准备 sh 复制代码 docker pull sath89/oracle-12c 启动镜像 sh 复制代码 docker run -d --name oracle12c -p 8080:8080 -p 1521:1521 -v $PWD/data:/mnt -e TZ=Asia/Shanghai sath89/oracle-12c 注: oracle12c为Docker容器名称 8080:8080为内...

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

pipenv快速入门

学过Python的同学应该都了解pip这个工具,我们用pip绝大部分的第三方库都可以用pip来安装,用起来很方便。但是如果我们要把项目部署到服务器上面的话,就稍微有些麻烦了,因为还需要在服务器上用pip安装这些包,假如项目中用到很多包的话,一个个安装会很麻烦,而且没有通用性。Java上的maven、gradle,NodeJS的npm这些工具就不存在这个问题,它们有一个或多个的专门的依赖文件来管理这些包。pipenv就是这样一个类似的工具,可以帮助我们管理Python和第三方库的版本。 安装 安装pipenv很简单,用pip命令就可以安装。 pip install pipenv 将来需要更新pipenv的时候,运行: pip install --user --upgrade pipenv 首次运行 如果是第一次在项目中运行pipenv命令的话,会在项目中创建一个名为Pipfile的文件,文件内容类似下面这样。用过maven、gradle等工具的同学对此应该熟悉,相信不用我解释其中的含义。 [[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] requests-html = "*" [dev-packages] [requires] python_version = "3.7" 如果运行过install、update等命令的话,还会创建一个Pipfile.lock文件,类似npm中的lock文件。这两个文件就是pipenv用于管理第三方库的配置文件,如果同时使用版本控制软件的话,需要将它们也加入进去。 常用命令 安装 例如,我想在项目中安装requests这个包,运行: pipenv install requests 如果需要指定具体版本号,可以这样: pipenv install requests==2.13.0 如果是第一次运行pipenv的话,会先创建Pipfile文件,否则会修改Pipfile`文件。 该命令还有一个常用参数-d或--dev,用于安装仅供开发使用的包。 卸载 相应的还有命令来卸载第三方包,该命令还有两个参数--all和--all-dev用于卸载所有包和所有开发包。 pipenv uninstall requests 更新 查看所有需要更新的包: pipenv update --outdated 更新所有包: pipenv update 更新指定的包: pipenv update <包名> 从requirements.txt导入 如果项目中有requirements.txt文件,pipenv会在安装的时候自动导入。如果需要导入其他位置的requirements.txt,可以用下面的命令: pipenv install -r path/to/requirements.txt 指定Python版本 pipenv会创建虚拟Python环境,并在其中用pip安装所有包。如果要指定Python版本,可以用下面的命令,三种版本号都支持: pipenv --python 3 pipenv --python 3.6 pipenv --python 2.7.14 如果不指定版本号,pipenv会使用系统默认的Python版本。需要注意,这里指定的Python必须是系统已经安装的、可以在环境变量中搜索到的版本号,如果指定未安装的版本,会提示错误。 运行命令 用下面的命令可以启动一个在虚拟环境中的shell: pipenv shell 如果不想启动shell,而是直接在虚拟环境中执行命令,可以使用run: pipenv run python --version 高级用法 一开始我文档没看全,然后用pipenv的时候发现有一些问题,后来我发现官方文档还有一部分高级内容也很重要,所以再来补充一下。当然如果有需要的话还是得看原文。 导出requirements.txt 用下面的命令就可以将Pipfile和Pipfile.lock文件里面的包导出为requirements.txt文件。 pipenv lock -r 如果只想导出开发用的包,可以添加--dev参数: pipenv lock -r --dev 自动安装Python pipenv只能搜索系统中已经安装的Python版本,对于未安装的版本,会提示错误。但是如果你同时安装了pyenv的话,pipenv会自动发现pyenv,然后直接询问你是否要安装。这样一来,原来的工作流程是:用pyenv安装某个Python->用virtualenv或venv创建虚拟环境->用pip从requirements.txt中安装包->将来可能还要更新包。现在完全可以用pipenv一两条命令解决,真的是非常方便。 自动加载.env文件 .env文件可以设置一些环境变量,在程序开发的时候模拟环境变量。pipenv也可以自动加载.env文件。 $ cat .env HELLO=WORLD⏎ $ pipenv run python Loading .env environment variables… Python 2.7.13 (default, Jul 18 2017, 09:17:00) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.environ['HELLO'] 'WORLD' 环境变量支持 在Pipfile中也可以引用环境变量的值,格式为${MY_ENVAR}或$MY_ENVAR,在Windows系统中还支持%MY_ENVAR%。 [[source]] url = "https://${PYPI_USERNAME}:${PYPI_PASSWORD}@my_private_repo.example.com/simple" verify_ssl = true name = "pypi" [dev-packages] [packages] requests = {version="*", index="home"} maya = {version="*", index="pypi"} records = "*" 自定义虚拟环境路径 很多工具遵循Linux开发习惯,将东西全存在用户目录中,在Linux中可能没啥,但是在Windows下可能有人不喜欢把这些东西放在用户目录。当然pipenv也可以自定义,只需要设置或修改WORKON_HOME环境变量的值即可。 如果设置了PIPENV_VENV_IN_PROJECT环境变量,pipenv会把虚拟环境放在项目目录的.venv目录下。 配置pipenv pipenv还有一些配置,都是使用环境变量配置的,由于配置项比较多,这里就不介绍了,直接看官方文档好了。 从setup.py安装 pipenv也可以从setup.py安装: pipenv install -e . 那么为什么不全用pipenv来安装呢?官方文档这里为我们做出了解释:项目可以分为两种,程序和库,对于程序来说应该使用pipenv,而对于库来说则是在setup.py中安装。详细解释说实话我没太看懂,大意就是抽象依赖和具体依赖,还有一个责任分配的问题,原文在这里。

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

pyenv快速入门

在开发Python程序的时候,有时候可能需要在不同版本的Python上进行测试。pyenv就是这么一个管理多版本Python的工具。由于在Windows中我们可以同时安装多个版本的Python,所以这里是在Linux下介绍该工具。 安装 首先当然是安装pyenv了,最简单的办法就是利用官方Github仓库中的安装脚本了: $ curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash 安装脚本有可能会提示你手动把几行命令添加到shell的配置文件中。 如果你用的是zsh的话,别忘了替换命令中的bash。将来如果要删除的话,需要在.zshrc文件中删除。如果你用oh-my-zsh的话,不需要在.zshrc中添加那几行(加了也没用),而是在.zshrc中启用pyenv插件。 将来要进行更新的话: $ pyenv update 要卸载pyenv的话更加简单,直接删除目录即可: $ rm -fr ~/.pyenv 别忘了把.bashrc中的这几行也一并删掉: export PATH="~/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" 工作原理 Linux环境变量 当执行命令的时候,系统会在环境变量中从左到右依次寻找匹配的命令并执行。环境变量中是一组以冒号:分隔的路径。 环境变量 垫片(Shims) pyenv的工作原理其实很简单,将它自己管理的Python目录插到环境变量的最前面,这样一来系统在搜索Python的时候第一个找到的就是pyenv管理的Python环境。这个插到最前面的路径就叫做垫片(shims),当然这是在英文语境下,在中文环境下我老觉得怪怪的,反正理解意思就好。 选择Python版本 当执行pyenv命令的时候,它会按照以下顺序来决定要使用的Python版本: 使用PYENV_VERSION环境变量(如果存在). 你可以使用pyenv shell 命令来在当前shell环境中设置该环境变量. 当前目录中应用程序指定的.python-version文件(如果存在). 你可以用pyenv local 命令来修改当前目录的.python-version文件. 自底向上搜索各层上级目录,找到的第一个.python-version, 直到到达文件系统根目录. 全局的$(pyenv root)/version文件. 可以使用 pyenv global 命令来修改. 如果全局版本文件不存在, pyenv假设你使用系统安装的Python. (换句话说就是未安装pyenv时环境变量中找到的Python.) 常用命令 完整命令请参考官方文档。 安装 列出所有可安装的Python版本: pyenv install -l|--list 安装某个Python: pyenv install <version> 卸载 卸载某个Python,-f参数指定是否强制卸载,如果强制卸载的话不会弹出提示,而且如果版本不存在的话也不会显示错误信息: pyenv uninstall [-f|--force] <version> versions 列出所有已安装的Python,当前使用的Python会用星号标出: $ pyenv versions 2.5.6 2.6.8 * 2.7.6 (set by /home/yyuu/.pyenv/version) 3.3.3 jython-2.5.3 pypy-2.2.1 global 通过写~/.pyenv/version文件的方式设置全局Python: $ pyenv global 2.7.6 local 通过在当前目录写.python-version文件的方式设置当前目录下的Python: pyenv local 2.7.6 当不再需要本地Python的时候,用--set来清除: $ pyenv local --unset shell 指定当前shell使用的Python: $ pyenv shell pypy-2.2.1 当不再需要的时候,用--set来清除: $ pyenv shell --unset 最后展示一下pyenv install -l的输出,可以看到,pyenv可以方便的安装大部分版本的Python,省略号表示中间有一大堆: yitian@ubuntu:~ $ pyenv install -l Available versions: 2.1.3 ... 2.7.15 ... 3.6.6 3.7.0 3.7-dev 3.8-dev activepython-2.7.14 activepython-3.5.4 activepython-3.6.0 anaconda-1.4.0 ... anaconda3-5.2.0 ironpython-dev ironpython-2.7.4 ironpython-2.7.5 ironpython-2.7.6.3 ironpython-2.7.7 jython-dev jython-2.5.0 jython-2.5-dev jython-2.5.1 jython-2.5.2 jython-2.5.3 jython-2.5.4-rc1 jython-2.7.0 jython-2.7.1 micropython-dev micropython-1.9.3 micropython-1.9.4 miniconda-latest miniconda-2.2.2 ... miniconda3-4.3.30 pypy-c-jit-latest pypy-c-nojit-latest pypy-dev pypy-stm-2.3 pypy-stm-2.5.1 pypy-1.5-src pypy-1.5 ... pypy3.5-6.0.0 pyston-0.5.1 pyston-0.6.0 pyston-0.6.1 stackless-dev stackless-2.7-dev stackless-2.7.2 ... stackless-3.5.4 常见问题 用pyenv安装Python的时候可能会出现各种各样问题,例如缺少zlib、缺少ctypes模块等等。对此pyenv也有专门一个页面解决。对于我的Ubuntu 18.04虚拟机来说,安装以下一坨软件可以解决问题: sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \ libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ xz-utils tk-dev libffi-dev liblzma-dev libedit-dev 其他系统请查看pyenv的页面,如果有其它问题请自行搜索Stack Overflow。

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

JetCache快速入门

创建缓存实例 通过@CreateCache注解创建一个缓存实例,默认超时时间是100秒 @CreateCache(expire = 100) private Cache<Long, UserDO> userCache; 用起来就像map一样 UserDO user = userCache.get(123L); userCache.put(123L, user); userCache.remove(123L); 创建一个两级(内存+远程)的缓存,内存中的元素个数限制在50个。 @CreateCache(name = "UserService.userCache", expire = 100, cacheType = CacheType.BOTH, localLimit = 50) private Cache<Long, UserDO> userCache; name属性不是必须的,但是起个名字是个好习惯,展示统计数据的使用,会使用这个名字。如果同一个area两个@CreateCache的name配置一样,它们生成的Cache将指向同一个实例。 创建方法缓存 使用@Cached方法可以为一个方法添加上缓存。JetCache通过Spring AOP生成代理,来支持缓存功能。注解可以加在接口方法上也可以加在类方法上,但需要保证是个Spring bean。 public interface UserService { @Cached(name="UserService.getUserById", expire = 3600) User getUserById(long userId); } 基本配置(使用Spring Boot) 如果使用Spring Boot,可以按如下的方式配置。 POM <dependency> <groupId>com.alicp.jetcache</groupId> <artifactId>jetcache-starter-redis</artifactId> <version>2.4.4</version> </dependency> 配置一个spring boot风格的application.yml文件,把他放到资源目录中 jetcache: statIntervalMinutes: 15 areaInCacheName: false local: default: type: linkedhashmap keyConvertor: fastjson remote: default: type: redis keyConvertor: fastjson valueEncoder: java valueDecoder: java poolConfig: minIdle: 5 maxIdle: 20 maxTotal: 50 host: 127.0.0.1 port: 6379 然后创建一个App类放在业务包的根下,EnableMethodCache,EnableCreateCacheAnnotation这两个注解分别激活Cached和CreateCache注解,其他和标准的Spring Boot程序是一样的。这个类可以直接main方法运行。 package com.company.mypackage; import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; import com.alicp.jetcache.anno.config.EnableMethodCache; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableMethodCache(basePackages = "com.company.mypackage") @EnableCreateCacheAnnotation public class MySpringBootApp { public static void main(String[] args) { SpringApplication.run(MySpringBootApp.class); } } 未使用SpringBoot的配置方式 如果没有使用spring boot,可以按下面的方式配置(这里使用jedis客户端连接redis为例)。 <dependency> <groupId>com.alicp.jetcache</groupId> <artifactId>jetcache-anno</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>com.alicp.jetcache</groupId> <artifactId>jetcache-redis</artifactId> <version>2.4.4</version> </dependency> 配置了这个JetCacheConfig类以后,可以使用@CreateCache和@Cached注解。 package com.company.mypackage; import java.util.HashMap; import java.util.Map; import com.alicp.jetcache.anno.CacheConsts; import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; import com.alicp.jetcache.anno.config.EnableMethodCache; import com.alicp.jetcache.anno.support.GlobalCacheConfig; import com.alicp.jetcache.anno.support.SpringConfigProvider; import com.alicp.jetcache.embedded.EmbeddedCacheBuilder; import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder; import com.alicp.jetcache.redis.RedisCacheBuilder; import com.alicp.jetcache.support.FastjsonKeyConvertor; import com.alicp.jetcache.support.JavaValueDecoder; import com.alicp.jetcache.support.JavaValueEncoder; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.util.Pool; @Configuration @EnableMethodCache(basePackages = "com.company.mypackage") @EnableCreateCacheAnnotation public class JetCacheConfig { @Bean public Pool<Jedis> pool(){ GenericObjectPoolConfig pc = new GenericObjectPoolConfig(); pc.setMinIdle(2); pc.setMaxIdle(10); pc.setMaxTotal(10); return new JedisPool(pc, "localhost", 6379); } @Bean public SpringConfigProvider springConfigProvider() { return new SpringConfigProvider(); } @Bean public GlobalCacheConfig config(SpringConfigProvider configProvider, Pool<Jedis> pool){ Map localBuilders = new HashMap(); EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder .createLinkedHashMapCacheBuilder() .keyConvertor(FastjsonKeyConvertor.INSTANCE); localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder); Map remoteBuilders = new HashMap(); RedisCacheBuilder remoteCacheBuilder = RedisCacheBuilder.createRedisCacheBuilder() .keyConvertor(FastjsonKeyConvertor.INSTANCE) .valueEncoder(JavaValueEncoder.INSTANCE) .valueDecoder(JavaValueDecoder.INSTANCE) .jedisPool(pool); remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder); GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig(); globalCacheConfig.setConfigProvider(configProvider); globalCacheConfig.setLocalCacheBuilders(localBuilders); globalCacheConfig.setRemoteCacheBuilders(remoteBuilders); globalCacheConfig.setStatIntervalMinutes(15); globalCacheConfig.setAreaInCacheName(false); return globalCacheConfig; } } 进一步阅读 CreateCache的详细使用说明可以看这里 使用@CacheCache创建的Cache接口实例,它的API使用可以看这里 关于方法缓存(@Cached, @CacheUpdate, @CacheInvalidate)的详细使用看这里 详细的配置说明看这里。

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

AMFPHP快速入门

AMFPHP是PHP的远程调用(RPC, Remote Procedure Call)工具。它可以使PHP与下述技术无缝通信: (1) Flash 和 Flex Remoting (2) JavaScript JSON 和 Ajax JSON (3) XML 和XML-RPC 什么是RPC 远端程序调用(RPC, Remote Procedure Call) 是一种客户端与服务器端交换数据方式。我们可以调用本地对象带对各种参数方法设置回调并接受调用结果。我们不用关心发送和接收数据的实现细节。实现细节通常是抽象的,就像我们在调用本地方法一样。 AMFPHP的工作原理 客户端(Flash / Flex)与服务器端(PHP) 使用相同的方式描述方法调用和复杂数据。客户端序列化请求并将它发送到网关AMFPHP。AMFPHP再执行: (1) 反序列化请求 (2) 找到相应的远程服务类 (3) 实例化类 (4) 执行安全检查 (5)(使用指定参数)调用服务器端方法 (6) 序列化返回的数据 AMFPHP可以正确地序列化、反序列化复杂类型数据。除了对象和数组,它还支持 resources 数据连接资源,这就意味着我们可以通过调用远程方法简单返回mysql_query,amfphp 会处理这一切。如果平台支持 (目前来说,Flash Remoting 和Flex Remoting),AMFPHP还可以处理循环引用和自定义数据它也支持简单的远程调试。还有AMFPHP附带一个浏览器,它可以在创建客户端代码前测试远程服务。AMFPHP 1.0.1还添加了模板,可以自动生成客户端代码。AMFPHP 1.9 beta更是新增了对AMF3的支持。 简单示例 下面我们通过一个简单的登录示例来对AMFPHP有一个初步的认识,将分别从客户端和服务器端两个部分进行介绍。 一,Flex客户端: 复制代码 代码 import mx.controls.Alert; import mx.rpc.remoting.mxml.RemoteObject; import mx.rpc.events.*; public var login_remoteObj:RemoteObject = null; public function initLoginRemoteObject():void {//初始化RemoteObject this.login_remoteObj = new RemoteObject(); this.login_remoteObj.source = "Login"; this.login_remoteObj.destination = "amfphp"; this.login_remoteObj.showBusyCursor = true; this.login_remoteObj.endpoint = "http://localhost/MyTest/amfphp/gateway.php"; this.login_remoteObj.doLogin.addEventListener("result", loginHandler); this.login_remoteObj.doLogin.addEventListener("fault", faultHandler); } public function doLogin():void {//登陆操作,向服务器提交数据 var name:String = this.txtName.text; var pwd:String = this.txtPassword.text; var data:Array = new Array(); data.push(name); data.push(pwd); this.login_remoteObj.getOperation("doLogin").send(data); } public function loginHandler(event: ResultEvent):void {//处理服务器返回的结果 var result:Array = event.result as Array; var flag:String = result[0]; if (flag == "0") { Alert.show("登陆失败: " + result[1]); } else if (flag == "1") { Alert.show("登陆成功: " + result[1]); } else if (flag == "-1") { Alert.show("异常: " + result[1]); } } public function faultHandler(event: FaultEvent):void {//出错处理 Alert.show("sorry,出错了!!!"); } } 复制代码 二,PHP服务器端 1,将amfphp文件夹置于MyTest项目的根目录下,打开浏览器输入下述地址验证amfphp是否安装成功 http://localhost/MyTest/amfphp/gateway.php amfphp就是通过这个gateway来定位我们的服务类,并将请求转发给这些服务类进行处理的。 2,Login.php文件,包含了处理登陆请求的Login类,此文件置于BusinessLogic目录下 复制代码 代码 <?php class Login { public function doLogin($data) { $result = array(); try { $name = array_shift($data); $pwd = array_shift($data); if ($name == "phinecos" && $pwd == "123") { $result[] = "1"; $result[] = "you are valid user!"; } else { $result[] = "0"; $result[] = "login failed"; } } catch (Exception $ex) { $result[] = "-1"; $result[] = $ex->getMessage(); } return $result; } } ?> 复制代码 3,将globals.php中的服务路径项修改如下,为amfphp指明服务类所在的目录 $servicesPath = "../BusinessLogic/"; 本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2010/05/10/1731595.html,如需转载请自行联系原作者

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

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. 如果你的快乐与否取决于别人做了什么,我想,你真的有点问题。

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

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)

资源下载

更多资源
优质分享App

优质分享App

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

Apache Tomcat

Apache Tomcat

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

JDK

JDK

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。

Sublime Text

Sublime Text

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