1.8新特性-1函数式接口

主要内容 自定义函数式接口 函数式编程 常用函数式接口 1.函数式接口 概念 函数式接口在Java中是指:有且仅有一个抽象方法的接口。 函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。 备注:“**语法糖**”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部 类的“语法糖”,但是二者在原理上是不同的。 格式 只要确保接口中有且仅有一个抽象方法即可: 修饰符 interface 接口名称 { public abstract 返回值类型 方法名称(可选参数信息); // 其他非抽象方法内容 } 由于接口当中抽象方法的 public abstract 是可以省略的,所以定义一个函数式接口很简单: public interface MyFunctionalInterface { void myMethod(); } @FunctionalInterface 与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注 解可用于一个接口的定义上: @FunctionalInterface public interface MyFunctionalInterface { void myMethod(); } @Override检查方法是否为重写的方法,是:编译成功,否:编译失败 一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注 意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。 2.函数式编程 在兼顾面向对象特性的基础上,Java语言通过Lambda表达式与方法引用等,为开发者打开了函数式编程的大门。 下面我们做一个初探。 Lambda的延迟执行 有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda表达式是延迟执行的,这正好可以 作为解决方案,提升性能。 public class Demo01Logger { private static void log(int level, String msg) { if (level == 1) { System. »

1.8新特性-2Lambda表达式

第三章 Lambda表达式 1.1 函数式编程思想概述 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。 面向对象的思想: 做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情. 函数式编程思想: 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程 1.2 冗余的Runnable代码 传统写法 当需要启动一个线程去完成任务时,通常会通过 java.lang.Runnable 接口来定义任务内容,并使用 java.lang.Thread 类来启动该线程。代码如下: public class Demo01Runnable { public static void main(String[] args) { // 匿名内部类 Runnable task = new Runnable() { @Override public void run() { // 覆盖重写抽象方法 System.out.println("多线程任务执行!"); } }; new Thread(task).start(); // 启动线程 } } 本着“一切皆对象”的思想,这种做法是无可厚非的:首先创建一个 Runnable 接口的匿名内部类对象来指定任务内容,再将其交给一个线程来启动。 代码分析 对于 Runnable 的匿名内部类用法,可以分析出几点内容: Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心; 为了指定 run 的方法体,不得不需要 Runnable 接口的实现类; »

1.8新特性-3Stream流

Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定“流”就一定是“IO流”呢?在Java 8中,得益于Lambda所带 来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端。 引言 传统集合的多步遍历代码 几乎所有的集合(如 Collection 接口或 Map 接口等)都支持直接或间接的遍历操作。而当我们需要对集合中的元 素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。例如: import java.util.ArrayList; import java.util.List; public class Demo01ForEach { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("张无忌"); list.add("周芷若"); list.add("赵敏"); list.add("张强"); list.add("张三丰"); for (String name : list) { System.out.println(name); } } } 这是一段非常简单的集合遍历操作:对集合中的每一个字符串都进行打印输出操作。 循环遍历的弊端 Java 8的Lambda让我们可以更加专注于做什么(What),而不是怎么做(How),这点此前已经结合内部类进行 了对比说明。现在,我们仔细体会一下上例代码,可以发现: for循环的语法就是“怎么做” for循环的循环体才是“做什么” 为什么使用循环?因为要进行遍历。但循环是遍历的唯一方式吗?遍历是指每一个元素逐一进行处理,而并不是从 第一个到最后一个顺次处理的循环。前者是目的,后者是方式。 试想一下,如果希望对集合中的元素进行筛选过滤: 将集合A根据条件一过滤为子集B; 然后再根据条件二过滤为子集C。 那怎么办?在Java 8之前的做法可能为: »

ES6新特性

ES6新特性 1.1 什么是ES6 编程语言JavaScript是ECMAScript的实现和扩展 。ECMAScript是由ECMA(一个类似W3C的标准组织)参与进行标准化的语法规范。ECMAScript定义了: 语言语法 – 语法解析规则、关键字、语句、声明、运算符等。 类型 – 布尔型、数字、字符串、对象等。 原型和继承 内建对象和函数的标准库 – JSON、Math、数组方法、对象自省方法等。 ECMAScript标准不定义HTML或CSS的相关功能,也不定义类似DOM(文档对象模型)的Web API,这些都在独立的标准中进行定义。ECMAScript涵盖了各种环境中JS的使用场景,无论是浏览器环境还是类似node.js的非浏览器环境。 ECMAScript标准的历史版本分别是1、2、3、5。 那么为什么没有第4版?其实,在过去确实曾计划发布提出巨量新特性的第4版,但最终却因想法太过激进而惨遭废除(这一版标准中曾经有一个极其复杂的支持泛型和类型推断的内建静态类型系统)。 ES4饱受争议,当标准委员会最终停止开发ES4时,其成员同意发布一个相对谦和的ES5版本,随后继续制定一些更具实质性的新特性。这一明确的协商协议最终命名为“Harmony”,因此,ES5规范中包含这样两句话 ECMAScript是一门充满活力的语言,并在不断进化中。 未来版本的规范中将持续进行重要的技术改进 2009年发布的改进版本ES5,引入了Object.create()、Object.defineProperty()、getters和setters、严格模式以及JSON对象。 ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,2015年6月正式发布。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。 1.2 Node.js中使用ES6 ES6+ 太棒了,但是很多高级功能node是不支持的,就需要使用babel转换成ES5 (1)babel转换配置,项目根目录添加.babelrc 文件 { "presets" : ['es2015'] } (2)安装es6转换模块 cnpm install babel-preset-es2015 --save-dev (3)全局安装命令行工具 cnpm install babel-cli -g (4)使用 babel-node js文件名 1.3 语法新特性 1.3.1 变量声明let 我们都是知道在ES6以前,var关键字声明变量。无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部)。这就是函数变量提升例如 function aa() { if(bool) { var test = 'hello man' } else { console. »

Author image HuangRui on #qd, #es6,

FastDFS入门安装与nginx整合

分布式文件系统fastDFS研究 什么是分布式文件系统 技术应用场景 一个网站拥有大量的视频和图片资源,并且免费提供用户去下载,文件太多如何高效存储?用户访问量大,如何提升访问速度? 分布式文件系统可以解决上述问题. 分布式文件系统解决了海量文件存储及传输访问的瓶颈问题,对海量视频的管理、对海量图片的管理等。 什么是文件系统 总结:文件系统是负责管理和存储文件的系统软件,它是操作系统和硬件驱动之间的桥梁,操作系统通过文件系统 提供的接口去存取文件,用户通过操作系统访问磁盘上的文件。如下图: 常见的文件系统:FAT16/FAT32、NTFS、HFS、UFS、APFS、XFS、Ext4等 。 什么是分布式文件系统 为什么会有分布文件系统呢? 分布式文件系统是面对互联网的需求而产生,互联网时代对海量数据如何存储?靠简单的增加硬盘的个数已经满足 不了我们的要求,因为硬盘传输速度有限但是数据在急剧增长,另外我们还要要做好数据备份、数据安全等。 采用分布式文件系统可以将多个地点的文件系统通过网络连接起来,组成一个文件系统网络,结点之间通过网络进 行通信,一台文件系统的存储和传输能力有限,我们让文件在多台计算机上存储,通过多台计算共同传输。如下 图: 好处: 1、一台计算机的文件系统处理能力扩充到多台计算机同时处理。 2、一台计算机挂了还有另外副本计算机提供数据。 3、每台计算机可以放在不同的地域,这样用户就可以就近访问,提高访问速度。 主流的分布式文件系统 1、NFS 2、GFS 1)GFS采用主从结构,一个GFS集群由一个master和大量的chunkserver组成。 2)master存储了数据文件的元数据,一个文件被分成了若干块存储在多个chunkserver中。 3)用户从master中获取数据元信息,从chunkserver存储数据。 3、HDFS 1)HDFS采用主从结构,一个HDFS集群由一个名称结点和若干数据结点组成。 名称结点存储数据的元信息,一个完整的数据文件分成若干块存储在数据结点。 2)客户端从名称结点获取数据的元信息及数据分块的信息,得到信息客户端即可从数据块来存取数据。 分布式文件服务提供商 什么是fastDFS fastDSF介绍 FastDFS是用c语言编写的一款开源的分布式文件系统,它是由淘宝资深架构师余庆编写并开源。FastDFS专为互联 网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很 容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。 为什么要使用fastDFS呢? 上边介绍的NFS、GFS都是通用的分布式文件系统,通用的分布式文件系统的优点的是开发体验好,但是系统复杂 性高、性能一般,而专用的分布式文件系统虽然开发体验性差,但是系统复杂性低并且性能高。fastDFS非常适合 存储图片等那些小文件,fastDFS不对文件进行分块,所以它就没有分块合并的开销,fastDFS网络通信采用 socket,通信速度很快。 fastDSF工作原理 fastDSF架构 FastDFS架构包括 Tracker server和Storageserver。客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载。 1)Tracker Tracker Server作用是负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server提 供文件上传服务。可以将tracker称为追踪服务器或调度服务器。 FastDFS集群中的Tracker server可以有多台,Tracker server之间是相互平等关系同时提供服务,Tracker server 不存在单点故障。客户端请求Tracker server采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。 2)Storage Storage Server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage server没有实现自己 的文件系统而是使用操作系统的文件系统来管理文件。可以将storage称为存储服务器。 3)Storage状态收集 »

Promise在异步调用时的使用场景

下面基于,前端要调用接口删除图片的环境背景下,说明为了实现删除成功图片消失,删除失败图片不会消失的实现过程` 用到ES6中的promise语法 promise异步调用** 在handleRemove方法调用删除图片的api方法,删除成功时return true,删除失败时return false; //删除图片 handleRemove(file, fileList) { console.log(file) // alert('删除') // return true; //删除图片 courseApi.deleteCoursePic('1').then((res) => { if(res.success){ this.$message.success('删除成功'); return true; }else{ this.$message.error(res.message); return false; } }); }, 在上边代码中将提交的课程id故意写错,按照我们预期应该是删除失败,而测试结果却是图片在页面上删除成功。 问题原因: 通过查询deleteCoursePic方法的底层代码,deleteCoursePic最终返回一个promise对象。 Promise是ES6提供的用于异步处理的对象,因为axios提交是异步提交,这里使用promise作为返回值。 Promise的使用方法如下: Promise对象在处理过程中有三种状态: pending:进行中 resolved:操作成功 rejected: 操作失败 Promise的构建方法如下: const promise = new Promise(function(resolve,reject){ //...TODO... if(操作成功){ resolve(value); }else{ reject(error); } }) 上边的构造方法function(resolve,reject)执行流程如下: 1)方法执行一些业务逻辑。 2)如果操作成功将Promise的状态由pending变为resolved,并将操作结果传出去 3)如果操作失败会将promise的状态由pending变为rejected,并将失败结果传出去。 上边说的操作成功将操作结果传给谁了呢?操作失败将失败结果传给谁了呢? 通过promise的then、catch来指定 promise.then(function (result) { console.log('操作成功:' + result); }); promise. »

RabbitMQ入门 及win安装mq

RabbitMQ 入门 介绍 RabbitMQ MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开 发中应用非常广泛。RabbitMQ官方地址:http://www.rabbitmq.com/ 开发中消息队列通常有如下应用场景: 1、任务异步处理。 将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。 2、应用程序解耦合 MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。 市场上还有哪些消息队列? ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。 为什么使用RabbitMQ呢? 1、使得简单,功能强大。 2、基于AMQP协议。 3、社区活跃,文档完善。 4、高并发性能好,这主要得益于Erlang语言。 5、Spring Boot默认已集成RabbitMQ 其它相关知识 AMQP是什么 ? 总结:AMQP是一套公开的消息队列协议,最早在2003年被提出,它旨在从协议层定义消息通信数据的标准格式, 为的就是解决MQ市场上协议不统一的问题。RabbitMQ就是遵循AMQP标准协议开发的MQ服务。 官方:http://www.amqp.org/ JMS是什么 ? 总结: JMS是java提供的一套消息服务API标准,其目的是为所有的java应用程序提供统一的消息通信的标准,类似java的 jdbc,只要遵循jms标准的应用程序之间都可以进行消息通信。它和AMQP有什么 不同,jms是java语言专属的消 息服务标准,它是在api层定义标准,并且只能用于java应用;而AMQP是在协议层定义的标准,是跨语言的 。 入门知识 RabbitMQ的工作原理 下图是RabbitMQ的基本结构: 组成部分说明如下: Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。 Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。 Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。 Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。 Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。 消息发布接收流程: —–发送消息—– 1、生产者和Broker建立TCP连接。 2、生产者和Broker建立通道。 3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。 4、Exchange将消息转发到指定的Queue(队列) —-接收消息—– 1、消费者和Broker建立TCP连接 2、消费者和Broker建立通道 3、消费者监听指定的Queue(队列) 4、当有消息到达Queue时Broker默认将消息推送给消费者。 5、消费者接收到消息。 下载安装 下载安装 RabbitMQ由Erlang语言开发,Erlang语言用于并发及分布式系统的开发,在电信领域应用广泛,OTP(Open »

cms-SSI服务端包含

SSI服务端包含技术 本节分析首页的管理方案。 1、页面内容多如何管理? 将页面拆分成一个一个的小页面,通过cms去管理这些小页面,当要更改部分页面内容时只需要更改具体某个小页 面即可。 2、页面拆出来怎么样通过web服务浏览呢? 使用web服务(例如nginx)的SSI技术,将多个子页面合并渲染输出。 3、SSI是什么? ssi包含类似于jsp页面中的incluce指令,ssi是在web服务端将include指定 的页面包含在网页中,渲染html网页响 应给客户端 。nginx、apache等多数web容器都支持SSI指令。 ssi指令如下: <!‐‐#include virtual="/../....html"‐‐> 4、将首页拆分成 index.html:首页主体内容 include/header.html:头部区域 include/index_banner.html:轮播图 include/index_category.html:左侧列表导航 include/footer.html:页尾 5、在nginx虚拟主机中开通SSI server{ listen 80; server_name www.xuecheng.com; ssi on; ssi_silent_errors on; ...... ssi的配置参数如下: ssi on: 开启ssi支持 ssi_silent_errors on:默认为offff,设置为on则在处理SSI文件出错时不 输出错误信息 ssi_types:默认为 ssi_types text/html,如果需要支持shtml(服务器执行脚本,类似于jsp)则需 要设置为ssi_types text/shtml 6、测试 去掉某个#include查看页面效果。 类似JSP中的include,把原来的页面拆分为多个小模块,目的就是更方便CMS管理这些小页面,修改起来更方便 »

Author image HuangRui on #xm,

cms-Swagger接口测试

Swagger Swagger介绍 OpenAPI规范(OpenAPI Specifification 简称OAS)是Linux基金会的一个项目,试图通过定义一种用来描述API格 式或API定义的语言,来规范RESTful服务开发过程,目前版本是V3.0,并且已经发布并开源在github上。 (https://github.com/OAI/OpenAPI-Specifification) Swagger是全球最大的OpenAPI规范(OAS)API开发工具框架,支持从设计和文档到测试和部署的整个API生命周 期的开发。 (https://swagger.io/) Spring Boot 可以集成Swagger,生成Swagger接口,Spring Boot是Java领域的神器,它是Spring项目下快速构建 项目的框架。 可以在代码中加上注解注释,生成一份接口文档,并且可以在线测试接口 Swagger常用注解 在Java类中添加Swagger的注解即可生成Swagger接口,常用Swagger注解如下: @Api:修饰整个类,描述Controller的作用 @ApiOperation:描述一个类的一个方法,或者说一个接口 @ApiParam:单个参数描述 @ApiModel:用对象来接收参数 @ApiModelProperty:用对象接收参数时,描述对 象的一个字段 @ApiResponse:HTTP响应其中1个描述 @ApiResponses:HTTP响应整体描述 @ApiIgnore:使用 该注解忽略这个API @ApiError :发生错误返回的信息 @ApiImplicitParam:一个请求参数 @ApiImplicitParams:多个请求参数 @ApiImplicitParam属性: Swagger接口定义 修改接口工程中页面查询接口,添加Swagger注解。 @Api(value="cms页面管理接口",description = "cms页面管理接口,提供页面的增、删、改、查") public interface CmsPageControllerApi { @ApiOperation("分页查询页面列表") @ApiImplicitParams({ @ApiImplicitParam(name="page",value = "页 码",required=true,paramType="path",dataType="int"), @ApiImplicitParam(name="size",value = "每页记录 数",required=true,paramType="path",dataType="int") }) public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ; } 在QueryPageRequest类中使用注解 ApiModelProperty 对属性注释: @Data public class QueryPageRequest extends RequestData { //站点id @ApiModelProperty("站点id") private String siteId; //页面ID @ApiModelProperty("页面ID") private String pageId; //页面名称 @ApiModelProperty("页面名称") private String pageName; //页面别名 @ApiModelProperty("页面别名") private String pageAliase; //模版id @ApiModelProperty("模版id") private String templateId; } Swagger接口测试 Swagger接口生成工作原理: 1、系统启动,扫描到api工程中的Swagger2Confifiguration类 2、在此类中指定了包路径com. »

Author image HuangRui on #xm,

cms-前端cms管理项目搭建

创建目录结构 base:存放基础组件 base/api:基础api接口 base/component:基础组件,被各各模块都使用的组件 base/router:总的路由配置,加载各模块的路由配置文件 common:工具类 mock:存放前端单元测试方法 module:存放各业务模块的页面和api方法。 下级目录以模块名命名, 下边以cms举例: ​ cms/api:cms模块的api接口 ​ cms/component:cms模块的组件 cms/page: cms模块的页面 cms/router:cms模块的路由配置 statics:存放第三方组件的静态资源 vuex:存放vuex文件,本项目不使用 static:与src的平级目录,此目录存放静态资源 启动** 导包之后 启动文件: 1、进入 webpacktest02目录,执行npm run dev 2、使用webstorm,右键package.json文件,选择“Show npm Scripts” 打开窗口: 双击 dev。 注意:dev就是在package.json中配置的webpack dev server命令。 发现启动成功自动打开浏览器。 修改src中的任意文件内容,自动加载并刷新浏览器。 »

Author image HuangRui on #xm,