首页 文章 精选 留言 我的

精选列表

搜索[然之],共10000篇文章
优秀的个人博客,低调大师

SpringCloud组件之Eureka

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。 本文讲解Eureka的工作原理、相关配置、如何搭建Eureka服务 一、Eureka工作原理 Eureka包含两个组件:Eureka Server和Eureka ClientEureka Server提供服务发现能力,各个微服务启动时会向Eureka Server注册自己的信息(服务名、IP、端口等),Eureka Server便存储了这个信息.Eureka Client 是一个Java客户端,用于简化与Eureka的交互。每个微服务启动后, 会每

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

Docker之8 Dockerfile

什么是Dockerfile? Dockerfile是由多行命令语句组成的构建镜像的文件,一般命令分成四部分:基础镜像信息,元数据信息,镜像操作指令和容器启动时执行的指令。并且支持使用#作为注释使用。 Dockerfile指令: 1、FROM 格式:FROM <image>或 FROM <image>:<tag> 基础镜像来源,必须在第一行指令中指定,不指定标记则默认为latest。 2、LABEL 格式:LABEL <name>=<value> 指定添加元数据到镜像,可指定多个标签信息。 3、RUN 格式:RUN <command> 每条指令将在当前镜像基础上执行,并提交为新的镜像。 4、CMD 格式:CMD <command> 指定启动容器时执行的命令,每个Dockerfile只能有一条CMD指令,如果指定了多条CMD指令,则只会执行最后一条CMD指令。如果在启动镜像时指定了启动指令,则镜像预设的CMD指令不执行。一般用于执行容器时提供默认值。 5、EXPOSE 格式:EXPOSE <port> 指定镜像启动后暴露的端口,在容器启动时需要通过 -p 做端口映射 6、ENV 格式:ENV <key> <value> 指定环境变量,使用在构建阶段中的所有后续指令的环境。 7、ADD 格式:ADD <src> <dest> 该指令会在<src>(本地文件系统或远程网络位置) 进行复制新文件,并将它们添加到路径上图像的文件系统中<dest>。 8、COPY 格式:COPY <src> <dest> 复制本地主机的 <src> (为 Dockerfile 所在目录的相对路径) 到容器中的 <dest>。 9、ENTRYPOINT 格式:ENTRYPOINT <command> 配置容器启动后执行的命令,并且不可被docker run提供的参数覆盖。如果指定了多条ENTRYPOINT指令,则只会执行最后一条ENTRYPOINT指令。 10、VOLUME 格式:VOLUME <FileSystemMountPoint> 创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等 11、USER 格式:USER <user>:<group> | USER <uid>:<gid> 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。 12、WORKDIR 格式:WORKDIR <FileSystemPath> 为后续的 COPY、ADD、RUN、CMD、ENTRYPOINT 指令配置工作目录。(可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径, 则会基于之前命令指定的路径) 13、ARG 格式:ARG <varname>[=<value>] 该ARG指令定义了一个变量,用户可以docker build使用该--build-arg <varname>=<value> 标志在构建时将该变量传递给构建器。 14、ONBUILD 格式:ONBUILD [INSTRUCTION] 配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令,就好像它已经FROM在下游指令之后立即插入一样 Dockerfile。 15、STOPSIGNAL 格式:STOPSIGNAL <signal> 设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或SIGNAME格式的信号名,例如SIGKILL。 16、HEALTHCHECK 格式:HEALTHCHECK [OPTIONS] CMD command 测试容器以检查它是否仍在工作。即使服务器进程仍在运行,这也可以检测到陷入无限循环且无法处理新连接的Web服务器等情况。当容器指定了运行状况检查时,除了正常状态外,它还具有运行状况。这个状态最初是starting。每当健康检查通过时,它就会变成healthy(以前所处的状态)。经过一定数量的连续失败后,它就变成了unhealthy。 17、SHELL 格式:SHELL ["executable", "parameters"] 该SHELL指令允许覆盖用于shell命令形式的默认shell。Linux上的默认shell是["/bin/sh", "-c"],而在Windows上["cmd", "/S", "/C"]。该SHELL指令必须以JSON格式写入Dockerfile。 Dockerfile构建镜像 FROM centos:latest LABEL maintainers="yekangming" RUN echo "helloworld" CMD ["/bin/echo", "hellodocker"] docker build -t app:v1 .

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

kubernetes之Namespace详解

Namespace Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace。 Namespace常用来隔离不同的用户,比如Kubernetes自带的服务一般运行在kube-system namespace中 何时使用多个Namespaces当团队或项目中具有许多用户时,可以考虑使用Namespace来区分,如果是少量用户集群,可以不需要考虑使用Namespace,如果需要它们提供特殊性质时,可以开始使用Namespace。 Namespace为名称提供了一个范围。资源的Names在Namespace中具有唯一性。 Namespace是一种将集群资源划分为多个用途(通过resource quota)的方法。 在未来的Kubernetes版本中,默认情况下,相同Namespace中的对象将具有相同的访问控制策略。 对于稍微不同的资源没必要使用多个Namespace来划分,例如同意软件的不同版本,可以使用labels(标签)来区分同一Namespace中的资源。 查询命名空间 [root@master ~]# kubectl get namespace NAME STATUS AGE c7n-system Active 30d default Active 46d eas Active 45d kafka Active 38d kube-public Active 46d kube-system Active 46d [root@master37 ~]# 注意:namespace包含两种状态”Active”和”Terminating”。在namespace删除过程中,namespace状态被设置成”Terminating”。 创建命名空间1.直接创建命名空间 kubectl create namespace mynamespace 2.通过文件创建命名空间cat [root@master37 ~]# cat mynamespace.yaml apiVersion: v1 kind: Namespace metadata: name: mynamespace [root@master37 ~]# 执行yaml文件生成mynamespace命名空间 [root@master37 ~]# kubectl apply -f mynamespace.yaml namespace/mynamespace created [root@master37 ~]# 注意:命名空间名称满足正则表达式a-z0-9?,最大长度为63位 删除命名空间 kubectl delete namespaces mynamespace 查看所有命名空间下pod [root@master37 ~]# kubectl get pod --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-86c58d9df4-d24nb 1/1 Running 1 46d kube-system coredns-86c58d9df4-pq6qt 1/1 Running 1 46d kube-system etcd-master37 1/1 Running 1 46d kube-system filebeat-7mq2l 1/1 Running 12 38d kube-system filebeat-cj6j9 1/1 Running 1 42d kube-system filebeat-q594h 1/1 Running 2 42d kube-system kube-apiserver-master37 1/1 Running 1 46d kube-system kube-controller-manager-master37 1/1 Running 8 46d kube-system kube-flannel-ds-amd64-8mwqh 1/1 Running 1 45d kube-system kube-flannel-ds-amd64-cnj5c 1/1 Running 1 38d kube-system kube-flannel-ds-amd64-gw6qv 1/1 Running 1 45d kube-system kube-flannel-ds-amd64-trjqr 1/1 Running 7 45d kube-system kube-proxy-65w67 1/1 Running 1 46d kube-system kube-proxy-f7f5s 1/1 Running 2 45d kube-system kube-proxy-jjb56 1/1 Running 1 45d kube-system kube-proxy-vvdq4 1/1 Running 1 38d kube-system kube-scheduler-master37 1/1 Running 8 46d kube-system kubernetes-dashboard-57df4db6b-4kvfn 1/1 Running 1 45d kube-system kubernetes-dashboard-57df4db6b-hxvlq 1/1 Running 2 45d kube-system nfs-client-provisioner-759cc8b85c-ndd5f 1/1 Running 0 30d kube-system prometheus-9d74f4d95-rn776 1/1 Running 0 5d1h kube-system tiller-deploy-5d4955d66-72rhz 1/1 Running 0 32d kube-system traefik-ingress-controller-4sxrh 1/1 Running 2 45d kube-system traefik-ingress-controller-qxx9x 1/1 Running 1 45d kube-system traefik-ingress-controller-w7z2c 1/1 Running 1 38d 删除一个namespace会自动删除所有属于该namespace的资源。default和kube-system命名空间不可删除。

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

Unity 2018.2之粒子

纹理Mipmap流 在Unity 2018.2中,我们根据需要向内存添加了纹理Mipmap流支持,启用此功能可以减少Unity应用的纹理内存要求。 1 如何运行 启用此系统后,Unity将仅在网格靠近已激活的摄像机时,加载更高分辨率的纹Mipmap。高分辨率Mipmap数据保存在内存中,整体的纹理内存会限制在用户定义的预算范围内。 如果在加载新的纹理Miplevel后,纹理内存超出预算,那么与摄像机距离最远网格上的较高分辨率Midmap会从内存中释放出来。 2 加速初次载入时间 由于首次加载的纹理数据减少,即仅加载较低分辨率Mipmap,初始场景的载入速度也会加速。初始加载速度的提升效果将根据平台有所不同。 3 更多的可控性 你可以完全控制Texture Mipmap Streaming系统,决定哪些Mipmap会加载到内存中。通常Unity会加载所有存储在硬盘上的Mipmap,但使用此系统,你可以直接控制要加载哪些Mipmap等级。 该系统还会占用一小部分的CPU时间,从而节省大量的GPU内存。 4 启用和管理过程十分简单 通过质量设置(Quality Setting)可以轻松启用该功能,你可以定义每个纹理是否应进行流式处理,你也可以查询指标,以识别纹理内存的使用情况,同时还能节省内存。 你还可以调整各种设置来控制系统,从而平衡内存节省和CPU消耗,并允许你优先处理一些纹理,例如:将角色纹理优先于环境纹理。 C#动画作业 AnimationPlayables现在允许用户编写自定义的C# Playables来直接与动画数据进行交互。 用户也可以编写多线程C#代码来控制PlayableGraph所使用的AnimationStream数据,它也允许将用户编写的IK解算器、程序化动画或甚至是自定义混音器集成到当前动画系统中。 粒子系统的改进 下面在Unity 2018.1中的粒子系统改进: 支持多达8个UV:这使你可以使用比以往更多的自定义数据。 MinMaxCurve和MinMaxGradient:现在可以在自定义脚本中和粒子系统外使用这二个类型,从而匹配粒子系统UI所使用的风格。 线性颜色空间:上传粒子系统数据到GPU前,粒子系统能适时将颜色转换为线性空间。 从精灵发射:我们给形状(Shape)模块加入了二个新模式,从而使它能够从精灵或SpriteRenderer组件发射对象,并将粒子发射效果与精灵视效完美匹配。 BakeMesh:我们新增了二个API来将粒子系统的几何体烘焙到网格中: BakeMesh会烘焙粒子几何体,BakeTrailsMesh会将轨迹模块(Trails module)烘焙到网格中。 仅显示选取的对象(即Solo Mode):这是一个用户非常需要的功能,我们使得这个功能更具探索性和易用性,并在场景视图的Overlay层加入了其它预览控件,例如:播放、重放和暂停等控件。 ETC纹理支持:当你在纹理集动画(Texture Sheet Animation)模块中使用精灵时,带有独立Alpha纹理的着色器现在可以在粒子上使用了。 更多unity2018的功能介绍请到paws3d学习中心查找。

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

Javascript基础之-Promise

Promise是什么呢?根据ecma-262的定义: Promise是一个被用于延时计算的最终结果的占位符 (A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation.) 这个怎么理解呢 比如说,我要去麦当劳买点吃的,下单以后人家会先给你一个订单号,等人家外卖做好了,会提示你,并用那个订单小票来换取你真正的食物,在这时候,那个订单小票就是你这顿饭的占位符。 回到Promise,它有三种状态,分别为完成,拒绝和待决议, 而待决议的状态代表它还没有被完成或者是拒绝,也就是说,如果它一直都是处于待决议的状态,意味着代码永远都不会继续往下执行 所以下面这段代码永远都执行不到finish new Promise((resolve, reject) => { console.log('waiting'); document.writeln('waiting'); }).then((msg) => { console.log('finish'); }); 也就是意味着,必须显示的执行resolve()或者是reject,程序才会继续往下执行。 那怎么解决这个问题呢,其实很简单,决议一下就好了嘛,哈哈~~ 或者给Promise设置一个超时时间,看下面的代码: function timeoutPromise(delay) { return new Promise( function(resolve,reject){ setTimeout( function(){ reject( "Timeout!" ); }, delay ); } ); } Promise.race([ new Promise(() => { console.log('waiting...'); }), timeoutPromise(3000) ]).catch((msg) => { console.log(msg); }) 这段代码呢,会先等待5秒,然后会打印出一个错误"Timeout",在这里,Promise.race()实际上就是竞态的,谁先决议,其余的就会被抛弃。所以咱们三秒钟后决议一个拒绝,剩下那个promise自动被抛弃了 说到错误处理了,思考下面的代码: new Promise((resolve, reject) => { foo.bar(); }).then((msg) => { console.log(msg); }, null).then((msg) => { console.log(msg); }, (err) => { console.log(err); }); 这段代码,很明显foo不是对象,所以会报ReferenceError,所以呢,会自动决议为reject,然后他紧接着的那个then没有拒绝处理回调,然后接着往下传递错误,直到有reject回调为止,假如一直都没有reject回调呢,他就会在全局抛出一个未捕获的异常。 那么如果在Promise决议多次呢,实际上只有第一次决议生效,也就是说,只能有一种决议生效,又成功又失败,或者成功多次,失败多次听着就不靠谱是吧,思考下面的代码 new Promise((resolve, reject) => { resolve(); reject(); console.log('exec finish'); }).then((msg) => { console.log('resolve'); }, (err) => { console.log('reject'); }); 运行结果是输出exec finish 和resolve,因为第一次决议为resolve, 所以reject决议就被抛弃了 大家想一下,决议后对应的then里面的回调函数是同步还是异步的呢,思考下面这个问题: console.log(0); let p = new Promise((resolve, reject) => { console.log(1); resolve(); console.log(2); }) console.log(3); p.then((msg) => { console.log(4); }); console.log(5); 他的结果是 1 2 3 5 4 答案很显然啦,是异步的!实际上当决议以后,就会把它放到一个异步队列里调用 那为什么要这么设计呢,会给我们带来什么好处呢,思考下面这个问题 function getResult() { console.log(a); } function opt() { if (isAsync) { setTimeout(() => { getResult(); }, 0); } else { getResult(); } } var a = 0; var isAsync = false; opt(); a++; isAsync = true; opt(); a++; 他的结果输出的是0 2,那为什么不是0, 1,实际上就是因为由于同步和异步的的不确定性导致的,也叫zalgo,所以呢,要想消除他们的不确定性,必须就让他里面的代码要么都是同步,要么都是异步,这也是then为什么是异步的原因了 关于then,还有一个问题,就是then的返回值是什么,来继续看问题 var p = Promise.resolve( 21 ); var p2 = p.then( function(v){ return v * 2; }); console.log(p2); 通过他的结果,你很容易就能看出来,then的返回值是一个Promise,那么,这个then回调是不是可以这么理解呢? function callback() { return Promise.resolve(42); } 如果是的话,那么咱们就研究一下Promise.resolve()的特性,然后then()同理就可以是吧 那么我们现在就研究一下Promise.resolve()的一些特性: 如果向Promise.resolve()传递一个非Promise,非thenable的立即值,就会立即得到这个值填充的Promise,这个有三个关键字,非Promise,非thenable和立即值 如果向Promise.resolve()传递一个真正的promise,那么就会返回这个Promise,又一个例子,很好理解 var p = Promise.resolve(42); var p2 = Promise.resolve(p); console.log(p === p2); // true 如果向Promise.resolve()传递一个非Promise的thenable值,那么就会展开这个值,并且在展开过程会持续到提取出一个具体的Promise最终值 大家应该会有一点疑惑,thenable是什么,这段话是什么意思 var obj = { then(resolve, reject) { resolve(42); } }; Promise.resolve(obj).then((msg) => { console.log(msg); //42 }); 好了,Promise.resolve()特性讲完了,then返回值同理 同理完了以后呢,就会出现一些比较有意思的用法 首先就是链式调用,比如说 var p = Promise.resolve( 21 ); var p2 = p.then( function(v){ console.log( v ); // 21 // 用值42填充p2 return v * 2; } ); // 连接p2 p2.then( function(v){ console.log( v ); // 42 } ); 很简单吧,就不赘述了。 还有一个比较有意思,就是Promise实现同步执行,也就是前一个then如果是异步的话,它必须操作完成后,才会执行后面的then,常见的写法是这样的 new Promise((resolve, reject) => { setTimeout(() => { console.log('exec in promise it'); resolve(); }, 1000); }).then(() => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('exec in then it'); resolve(); }, 1000); }); }); 这个先过一秒输出第一句话,再过一秒输出第二句话 这个的原理实际上刚刚Promise.resolve()的第二条,如果返回的是Promise,那么会直接返回这个Promise,在这里,直接返回return的这个Promise后,就会等待这个Promise决议,在一秒后决议完,就执行后面的then 最后一个有关then的知识点了: 一个Promise决议后,这个Promise上所有的通过then()注册的回调都会在下一个异步时间节点上依次被立即调用,这些回掉中任意一个都无法影响或者延误对其他回调的调用 var p = new Promise((resolve, reject) => { resolve(); }); p.then( function(){ p.then( function(){ console.log( "C" ); } ); console.log( "A" ); } ); p.then( function(){ console.log( "B" ); } ); // a b c 这个的重点实际上是这些决议回调都被加入到了一个队列中,输出的顺序正好实际上就代表了他们加入队列后的先后顺序 参考书籍《你不知道的Javascript中卷》本文转载自http://www.lht.ren/article/3/

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

java之常量折叠

为什么会写着篇博客,因为昨天看了关于final关键字的解析。但是有个问题始终没有得到解决,于是请教了我qq上之前添加的知乎大神。他给我回复的第一条消息:常量折叠。身为渣渣猿的我立马查询了这个概念。这是第一次知道这个概念。知乎大神还给我讲了好多。让我终于明白了这个常量折叠的概念 实例解析 昨天,让我迷惑的代码是下面这段代码 public static void main(String[] args) { String a = "hello2"; final String b = "hello"; String d = "hello"; String c = b + 2; String e = d + 2; System.out.println((a == c)); System.out.println((a == e)); } 这段的执行结果是 true false 我就是不明白为什么第一个返回true呢? 留着这个疑问,我们先了解下常量折叠的概念。来更好的理解上面的代码 常量折叠 常量折叠的概念 常量折叠是一种编译器优化技术。 常量折叠主要指的是编译期常量加减乘除的运算过程会被折叠 对于 String s1 = "1" + "2"; 编译器会给你优化成 String s1 = "12"; 在生成的字节码中,根本看不到 "1" "2" 这两个东西。 我们通过idea进行验证下 1、源码文件 public static void main(String[] args) { String s1 = "1"+"2"; } 2、运行后,idea有个out文件夹,找到上面文件的class文件 public static void main(String[] args) { String s1 = "12"; } 确实如上面所说,编译器会给你进行优化 常量折叠发生的条件 必须是编译期常量之间进行运算才会进行常量折叠。 编译期常量就是“编译的时候就可以确定其值的常量”, 首先:字面量是编译期常量。(数字字面量,字符串字面量等) 其次:编译期常量进行简单运算的结果也是编译期常量,如1+2,"a"+"b"。 最后:被编译器常量赋值的 final 的基本类型和字符串变量也是编译期常量。 举个栗子 1.第一个栗子 public static void main(String[] args) { String s1="a"+"bc"; String s2="ab"+"c"; System.out.println(s1 == s2); } 相信大家都知道了,输出为true并且只创建了一个 "abc" 字符串对象,且位于字符串常量池中。 2、第二个栗子 public static void main(String[] args) { String a = "a"; String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); } 这个结果呢?false s1 是字符串字面量相加,但是 s2 却是两个非 final 的变量相加,所以不会进行常量折叠。 而是根据 String 类特有的 + 运算符重载,变成类似这样的代码 (jdk1.8) String s2 = new StringBuilder(a).append(b).toString(); 这里toString()会生成新的String变量,显然用 == 运算符比较是会返回 false。 3、第三个栗子 public static void main(String[] args) { final String a = "a"; final String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); } 这里的结果就是true 因为 被编译器常量赋值的 final 的基本类型和字符串变量也是编译期常量 4、第四个栗子 public static void main(String[] args) { String x ="a"; final String a = x; final String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2); } 这里的结果是false 这里需要注意的是:final的变量,不是被编译期常量初始化的也不是编译器常量 这里的a 就不是编译器常量 5、第五个栗子 public static void main(String[] args) { String x ="a"; final String a = x; final String bc = "bc"; String s1 = "a" + "bc"; String s2 = a + bc; System.out.println(s1 == s2.intern()); } 这里的结果是true 其实,这里大家要明白intern这个方法的意思就会明白了 // 一个字符串池,最初是空的,是由类字符串私有维护的。 1、A pool of strings, initially empty, is maintained privately by the class String. // 如果常量池中已经有了这个字符串,那么直接返回常量池中它的引用,如果没有,那就将它的引用保存一份到字符串常量池,然后直接返回这个引用。 2、When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. 3、It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. 总结 现在看完,是不是对上面打印的结果为什么是true 知道了呢?所以。只要牢记常量折叠主要指的是编译期常量加减乘除的运算过程会被折叠 后续补充 上面一开始写的是 而是根据 String 类特有的 + 运算符重载,变成类似这样的代码 String s2 = new StringBuffer(a).append(b).toString(); 这里更正下,就是现在我用jdk1.8 通过反编译后先在已经不是StringBuffer 而是StringBuilder。这里需要更正下。我也查询了下。StringBuilder 是jdk1.5之后才有的。

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

MongoDB 工具之mongostat

摘要: MongoDB提供了一些列的工具,包括mongostat, mongotop等性能监控工具,导入导出工具,同步工具,gridfile管理工具 等等。 背景 MongoDB提供了一些列的工具,这些工具我们通过mongodb官方进行下载。 mongodump mongoexport mongofiles mongoimport mongooplog mongoperf mongorestore mongostat mongotop 下载地址 如果我们通过rpm方式进行安装,那么我们需要单独安装mongo tools(mongodb-org-tools-3.2.9-1.el6.x86_64.rpm)。 mongostat作用 mongostat是最常用的工具之一,主要用来查看内存使用情况,网络吞吐情况。还可以查看实时的增删改查pqs。 安装 我们直接通过rpm方式即可安装成功 rpm-ivhmongodb-org-tools-3.2.9-1.el6.x86_64.rpm mongostat实战 直接执行mongostat脚本 mongostat help 除了常用的监控参数之外,mongostat提供了很多参数,我们可以通过mongostat --help来查看这些参数。 mongostat 参数详解 mongostat参数分为5种。 普通参数 查看版本 --version 查看help --help 例如:mongostat --version 连接参数 hostname --host或者-h (我们需要在hosts配置之后才能使用hostname来进行通信访问) 端口 --port 例如:mongostat --host=mongo243 --port=27017 ssl参数 指定证书等相关信息,这个不常用。 鉴权参数 鉴权参数主要是用来指定用户名密码, 用户名 -u或--username=xxxx 密码 -p或 --password=xxxx stat参数 结果以json展示 --json 不展示头信息 --noheaders 展示多少行就自动退出 --rowcount= 此外还有 --http, --discover, --all,这几个不是特别常用,这里不多做解释。 例如:mongostat --json, 输出结果 {"mongo243":{"ar|aw":"0|0","command":"3|0","conn":"3","delete":"*0","flushes":"0","getmore":"0","host":"mongo243","insert":"*0","netIn":"405b","netOut":"19.6k","qr|qw":"0|0","query":"*0","repl":"SEC","res":"80.0M","set":"productSet","time":"22:21:39","update":"*0","vsize":"767M"}}

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

JavaScript之Promise对象

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。 Promise 对象是一个代理对象(代理一个值),被代理的值在 Promise 对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的 Promise 对象。 Promise 对象有以下两个特点: 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功) 和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和 从 pending 变为 rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 基本用法 new Promise( function(resolve, reject) {...} /* executor */ ); Promise 对象的初始化接收一个执行函数 executor,executor 是带有 resolve 和 reject 两个参数的函数 。 Promise 构造函数执行时会立即调用 executor 函数, resolve 和 reject 两个函数作为参数传递给 executor(executor 函数在 Promise 构造函数返回新建对象前被调用)。 resolve 和 reject 函数被调用时,分别将 promise 的状态改为 fulfilled(完成) 或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用 resolve 函数来将 promise 状态改成 fulfilled,或者在发生错误时将它的状态改为 rejected。 如果在 executor 函数中抛出一个错误,那么该 promise 状态为 rejected。executor函数的返回值被忽略。 先看个示例:(注:后文的示例均使用 setTimeout 模拟异步操作) // 从 pending 变为 fulfilled var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); resolve('promise fulfilled!'); }, 500); }).then(function(data) { console.log(data); }); // Hi, // promise fulfilled! // 从 pending 变为 rejected var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); reject('promise rejected!'); }, 500); }).then(null, function(error) { console.log(error); //欢迎加入全栈开发交流圈一起学习交流:864305860 }); //面向1-3年前端人员 // Hi, //帮助突破技术瓶颈,提升思维能力 // promise rejected! 从 pending 变为 fulfilled 这段代码,当执行 new Promise() 时,传入的执行函数就立即执行了,此时其内部有一个异步操作(过 500ms 之后执行),等过了 500ms 之后先执行 console.log('Hi,'); 输出 Hi,,此时 promise 的状态为 pending(进行中),而执行 resolve('Promise!'); 则修改 promise 的状态为 fulfilled(完成),然后我们调用 then() 接收 promise 在 fulfilled 状态下传递的值,此时输出 'Promise!'。 同理,从 pending 变为 rejected 这段代码基本差不多,不同的是异步操作调用了 reject 方法,then 方法使用第二个参数接收 rejected 状态下传递的值。 Promise.prototype.then() then 的作用是为 Promise 实例添加状态改变时的回调函数。 then 方法的第一个参数是 resolved 状态的回调函数,第二个参数(可选)是 rejected 状态的回调函数。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }, function(error) { console.log(error); }); // 如果调用 resolve 方法,输出如下: // Hi, // promise fulfilled! // 如果调用 reject 方法,输出如下: // Hi, // promise rejected! then 方法返回的是一个新的 Promise 实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。采用链式的 then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个 Promise 对象(即有异步操作),这时后一个回调函数,就会等待该 Promise 对象的状态发生变化,才会被调用。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); resolve(); }, 500); }).then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }); }) }).then(function(data) { console.log(data); //欢迎加入全栈开发交流圈一起学习交流:864305860 }, function(error) { //面向1-3年前端人员 console.log(error); //帮助突破技术瓶颈,提升思维能力 }); // 如果第一个 then 调用 resolve 方法,第二个 then 调用第一个回调函数,最终输出如下: // Hi, // promise fulfilled! // 如果第一个 then 调用 reject 方法,第二个 then 调用第一个回调函数,最终输出如下: // Hi, // promise rejected! Promise.prototype.catch() catch 方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。 所以下面代码: var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }, function(error) { console.log(error); }); 等价于: var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }).catch(function(error) { console.log(error); }); 如果没有使用 catch 方法或者 then 第二个参数指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应,这跟传统的 try/catch 代码块是不同。 catch 方法返回的还是一个 Promise 对象,因此后面还可以接着调用 then 方法。 catch 方法与 .then(null, rejection) 的不同: 如果异步操作抛出错误,状态就会变为 rejected,就会调用 catch 方法指定的回调函数,处理这个错误。 then 方法指定的回调函数,如果运行中抛出错误,也会被 catch 方法捕获。 catch 方法的写法更接近同步的写法(try/catch)。 因此,建议总是使用 catch 方法,而不使用 then 方法的第二个参数。 Promise.prototype.finally() finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }).catch(function(error) { console.log(error); }).finally(function() { console.log('I am finally!'); }); 上面代码中,不管 promise 最后的状态,在执行完 then 或 catch 指定的回调函数以后,都会执行 finally 方法指定的回调函数。 Promise.all() Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。 var p = Promise.all([p1, p2]); 上面代码中,Promise.all 方法接受一个数组作为参数,p1、p2 都是 Promise 实例,如果不是,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。) p的状态由p1、p2决定,分成两种情况。 只有 p1、p2 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2 的返回值组成一个数组,传递给 p 的回调函数。 只要 p1、p2 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。 示例: 试想一个页面聊天系统,我们需要从两个不同的 URL 分别获得用户的个人信息和好友列表,这两个任务是可以并行执行的,用Promise.all()实现。 // 并行执行异步任务 var p1 = new Promise(function (resolve, reject) { setTimeout(function() { // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('P1'); } else { reject('error'); } }, 500); }); var p2 = new Promise(function (resolve, reject) { setTimeout(resolve, 600, 'P2'); }); // 同时执行p1和p2,并在它们都完成后执行then: Promise.all([p1, p2]).then(function (results) { console.log(results); // 输出:['P1', 'P2'] }).catch(function(error) { console.log(error); // 如果p1执行失败,则输出:error }); 注意,如果作为参数的 Promise 实例,自己定义了 catch 方法,那么它一旦被 rejected,并不会触发 Promise.all() 的 catch 方法。 Promise.race() Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。 var p = Promise.race([p1, p2]); 上面代码中,只要 p1、p2 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。 Promise.race 方法的参数与 Promise.all 方法一样,如果不是 Promise 实例,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。 示例: 有些时候,多个异步任务是为了容错。比如,同时向两个 URL 读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现。 // 多任务容错 var p1 = new Promise(function (resolve, reject) { setTimeout(resolve, 500, 'P1'); }); var p2 = new Promise(function (resolve, reject) { setTimeout(resolve, 400, 'P2'); }); Promise.race([p1, p2]).then(function (result) { console.log(result); // 'P2' }); Promise.resolve() 有时需要将现有对象转为 Promise 对象,Promise.resolve 方法就起到这个作用。 Promise.resolve方法的参数分成四种情况: (1)参数是一个 Promise 实例 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。 (2)参数是一个 thenable 对象 thenable 对象指的是具有 then 方法的对象,比如下面这个对象。 var thenable = { then: function (resolve, reject) { resolve(42); } }; Promise.resolve 方法会将这个对象转为 Promise 对象,然后就立即执行 thenable 对象的 then 方法。 var thenable = { then: function (resolve, reject) { resolve(42); } }; var p1 = Promise.resolve(thenable); p1.then(function (value) { console.log(value); // 42 }); 上面代码中,thenable 对象的 then 方法执行后,对象 p1 的状态就变为 resolved,从而立即执行最后那个 then 方法指定的回调函数,输出 42。 (3)参数不是具有 then 方法的对象,或根本就不是对象 如果参数是一个原始值,或者是一个不具有 then 方法的对象,则 Promise.resolve 方法返回一个新的 Promise 对象,状态为 resolved。 var p = Promise.resolve('Hello'); p.then(function (s) { console.log(s) }); // 'Hello' var p1 = Promise.resolve(true); p1.then(function (b) { console.log(b) }); // true var p2 = Promise.resolve(1); p1.then(function (n) { console.log(n) }); // 1 (4)不带有任何参数 Promise.resolve 方法允许调用时不带参数,直接返回一个 resolved 状态的 Promise 对象。 所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用 Promise.resolve 方法。 Promise.reject() Promise.reject 方法也会返回一个新的 Promise 实例,该实例的状态为 rejected。 注意,Promise.reject 方法的参数,会原封不动地作为 reject 的参数,变成后续方法的参数。这一点与 Promise.resolve 方法不一致。 var thenable = { then(resolve, reject) { reject('出错了'); } }; Promise.reject(thenable) .catch(e = > { console.log(e === thenable) }) // true 上面代码中,Promise.reject 方法的参数是一个 thenable 对象,执行以后,后面 catch 方法的参数不是 reject 抛出的 出错了 这个字符串,而是 thenable 对象。 加载图片 我们可以将图片的加载写成一个 Promise,一旦加载完成,Promise 的状态就发生变化。 function (path) { return new Promise(function (resolve, reject) { const image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); }; 封装ajax 我们可以将 ajax 请求写成一个 Promise,根据请求的不同状态改变 Promise 的状态。 function ajax(method, url, data) { var request = new XMLHttpRequest(); return new Promise(function (resolve, reject) { request.onreadystatechange = function () { if (request.readyState === 4) { if (request.status === 200) { resolve(request.responseText); } else { reject(request.status); } //欢迎加入全栈开发交流圈一起学习交流:864305860 } //面向1-3年前端人员 }; //帮助突破技术瓶颈,提升思维能力 request.open(method, url); request.send(data); }); } 总结 优点: 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(回调地狱)。 在异步执行的流程中,可以把执行代码和处理结果的代码清晰地分离开来。 缺点: 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。 当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

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

IoT之智能照明

版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。 https://blog.csdn.net/wireless_com/article/details/84001331 大多数照明控制系统仍然基于遗留的连接模型,这些模型是该领域专有的。 与物联网技术的深入整合是下一个主要的颠覆性转变,这将导致真正的智能照明与建筑连接管理的基础设施无缝结合。 物联网处理和连接能够提高可持续性和可维护性,并在我们与我们生活或工作的空间的互动中增强了个性化的用户体验,从而提高了舒适性和幸福感。 在过去的三年里,一个由欧洲主要公司组成的财团致力于定义和实施一套智能固态照明开放架构(简称 OpenAIS)。 部分由欧盟在地Horizon 2020计划中资助的 OpenAIS 项目,已经展示了物联网技术如何能够更加深入地整合在一起,并且在不久的将来,作为智能连接建筑的一部分,物联网技术如何能够更加深入地整合在一起。 该架构可交付的成果描述了使用基于 IP 数据包的数字网络通信进行照明控制以及收集传感器数据。 这便利了照明设备的安装和维护。 同样的网络基础设施可以重新用作其他应用程序领域的全建筑骨干,或与通用的信息技术和建筑管理系统进行无缝集成。 OpenAIS架构及其在全尺寸真实办公楼试验示范中的实例化也展示了开放的协作生态系统如何使社区能够提供智能照明解决方案,这些解决方案在一起运作良好,并且易于安装、使用和维护。 网络架构 OpenAIS的连接性架构是基于一个共同的 IPv6有线和无线混合的网络结构。 系统技术的建议是为有线段和无线Thread使用以太网/PoE。然而,OpenAIS 网络也可以支持任何其他IPv6传输。 IPv6数据包可以通过廉价且通用的交换或路由设备相互连接,而这些设备不需要照明应用程序域知识。 可以以统一的方式安装和管理主干和边缘网络,利用信息技术网络领域的专门知识或现有的基础设施。 此外,这个通用网络可用于各种其他的机器对机器信令或数据收集。 保证多个供应商的互操作性是 OpenAIS 网络系统定义的一个基本要求。 对于无线领域,互操作性的要求促使使用线程协议作为物联网的主要 IPv6网络技术的建议。 总之,OpenAIS 架构描述了一个具有以下特性的网络系统: 以 IPv6为基础的通信作为传输层,支持跨越有线或无线网络段IPv6组播 所有应用层通信都使用 IETF 定义的标准化 CoAP 协议,用于受限的嵌入式设备 数据通信的安全性和隐私性是通过运输层和应用层的调试、配置和加密的组合来实现的 照明域的通信模式 扩展一般的 IP 网络,以便在多个异质网路部分大规模地覆盖照明控制,这带来了挑战,当解决了这些问题,就产生了一些最有价值的 OpenAIS 架构定义: 扩展一般的IP网络,以便在多个异质网络部分大规模地覆盖照明控制,这带来了挑战,当解决了这些问题,就产生了一些最有价值的 OpenAIS 架构定义: 定义为低延迟、高同步群通信模式和协议。 这假定了一个多对多的拓扑,使用了多播 IPv6地址。 对于照明控制,群组通信处于中心位置,并被推荐用于增加高节点计数系统的可伸缩性,而不是更传统的客户端-服务器或设备对云的单播模式。 描述了一个分布式控制操作模型,该模型不依赖于一个基本通信的中央管理服务器。 这种控制模型可以建立在冗余的基础上,即使与这些中央基础设施的连接丢失或无法使用,也可以优雅地降级以实现基本功能。 这样的基本功能可能很简单,但是必要的光开关是实时的。 提供了一个灵活的应用层 API,优化底层网络—— OpenAIS 项目定义并提供了一个高智能、多功能和面向未来连接照明设备功能的对象模型。 图一 IoT的照明域架构 OPENAIS 实践 在2018年上半年,位于荷兰爱因霍温市中心的工业遗产大楼 De Witte Dame 的 GGD 办公室安装了 OpenAIS 系统。 图二荷兰爱因霍温 这一实践包括: 400 + 照明节点灯具,由数字 IP 网络连接,使用以太网/PoE/UPoW 为无线骨干和有线连接 先进的照明控制策略,包括当地占用和每个灯具的光敏传感器,粒度感应和控制策略(局部调光) ,以及通过智能手机办公应用程序进行个人控制 收集了有关区域占用情况的汇总数据,并提供给设施管理人员,以便他们能够评估空间利用效率 对于这一实验而言,一些 OpenAIS 联盟成员提供了Thread技术构件,对已部署的组件实施了Thread Group的认证程序。使用Thread作为本地 的IPv6协议,每个节点都有自己的 IPv6地址,也允许连接无线网络的光点与通过通用Thread 边缘路由器连接的基于以太网的有线网络之间的自然互联。 此外,Thread 允许在所有有线和无线设备上重用相同的非差异应用程序固件模块。 OpenAIS 联盟的项目合作伙伴分别是Signify(以前的飞利浦照明公司) ,Zumtobel Lighting,Tridonic,Johnson Controls,Dynniq,NXP,ARM,埃因霍温理工大学和 TNO-ESI。 对 OpenAIS 最终架构的详细描述和试验性演示验证结果可在联盟网站上查阅。

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

开源项目之kisso

kisso开源项目:https://gitee.com/baomidou/kisso 一、简介 kisso = cookie sso 基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞 士军刀。 应用场景如下: 1.支持单点登录 2、支持登录Cookie缓存 3、支持防止 xss攻击, SQL注入,脚本注入 4、支持 Base64 / MD5 / AES / PBE / RSA 算法 5、支持浏览器客户端校验 6、支持Cookie参数配置及扩展 7、支持跨域登录,模拟登录 8、支持在线人数统计 9、支持生成动态图片验证码 10、支持 app 移动端 api 服务验证,采用微信公众平台 api 验证机制认证 11、支持踢出指定登录用户 二、kisso 是什么原理与 cas 区别 1.kisso原理说明 kisso 采用的是加密会话 cookie 机制实现单点登录 SSO 服务,具备“无状态”、“分散验证” 等特性。 a.session 存放在服务器端,cookie 存放在客户端,存在 2 种状态: 第一种:持久 cookie 具 有时效性,以文件的形式存放在客户机硬盘中, 时间一到生命周期结束自动被删除; 第二种:临时 cookie 又叫会话 cookie 放在浏览器内存中,浏览器关闭生命周期结束自动失效。 b.单纯不做任何改变而言 session 更安全,如果 cookie 采取各种安全保护措施,此时的 cookie 一样安全。 c.cookie 轻松实现分布式服务部署,单点登录跨域访问等问题,换成 session 需要处理 session 复制及各种问题实现困难。 2.kisso与cas的区别 a.cas 是单点登录系统,它给你制定好了规则按照它的要求做就可以,配置(复杂)好一切即可实 现单点登录; b.kisso 是一个中间件,提供 cookie 搭建 java web sso 的组件式解决方案。你不管使用任何架构都可以使用它,就像一个 U 盘需要使用就插入、不用就拔掉。 c.cas 集中验证,所有请求都由 cas 集中验证,缺点cas服务压力巨大。kisso 分散验证,由各个系 统验证 cookie 合法性,缺点秘钥要保护好。 3.maven依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>kisso</artifactId> <version>3.6.10</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk14</artifactId> <version>1.50</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.46</version> </dependency> 注意:(1)如果想自己实现 Token 解析,实现 com.baomidou.kisso.common.parser.SSOParser 类 (解析接口类),修改配置文件 sso.properties 属性 sso.parser.class 此时 kisso 会调用您定义的解析类,不需要再依赖 fastjson 库。(2)自己实现 Token 加密,实现 com.baomidou.kisso.common.encrypt.SSOEncrypt 类(加密解密接口类),修改配置文件 sso.properties 属性 sso.encrypt.class 不在需要依赖 bcprov 库 三、sso.properties如何配置 配置如下,其他均可以采用默认配置 sso.secretkey=56jp2s5q83ZTE74ri6sso.cookie.domain=.baomidou.comsso.login.url=http://demo.baomidou.com:8080/Blog/views/login.html 四、配置 1.web.xml配置 kissoConfigLocationclasspath:properties/sso.propertiescom.baomidou.kisso.web.KissoConfigListener 2.spring-mvc.xml配置 *,对某个模块下的请求拦截使用:/myPath/ --> 两种方式任选一种即可 五、项目模块 六、跨域原理 七、Web访问流程图 八、移动端API访问流程图

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

Java 集合 之 List

http://www.verejava.com/?id=17159894213940 /** * 注意: 1. ArrayList 是按照添加的顺序,有序先进先出的. 2. ArrayList 可以添加重复元素 3. ArrayList 也可以添加 空值 null 4. ArrayList 内部是以对象数组 实现的 */ import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List list = new ArrayList(); // boolean add(Object o) list.add(1); list.add(1); list.add(null); list.add(2.5); list.add(true); list.add("王强"); list.add('A'); list.add(new Cat("波斯猫")); // // Object get(int index) Object wangqiang = list.get(3); System.out.println(wangqiang); // int size() System.out.println(list.size()); // // boolean contains(Object o) System.out.println(list.contains("王强")); // boolean isEmpty() System.out.println(list.isEmpty()); // // set(int index, Object element) list.set(4, 'B'); System.out.println(list.get(4)); // //遍历集合打印所以元素 for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); System.out.print(obj + ","); } // boolean remove(int index) list.remove(4); System.out.println(""); for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); System.out.print(obj + ","); } // void clear() list.clear(); System.out.println(""); System.out.println(list.size()); System.out.println(list.isEmpty()); for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); System.out.print(obj + ","); } } } public class Cat { private String name; public Cat(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString() { return name; } } http://www.verejava.com/?id=17159894213940

资源下载

更多资源
Nacos

Nacos

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册