Spring Boot 之 使用jetty web容器
springboot 中默认的web容器是tomcat。 在maven 的pom 文件中加入如下依赖,便可使用tomcat 容器。
1 2 3 4 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> |
如果想使用 jetty 作为 web容器,需要2步操作: 1.排除默认的tomcat 容器
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> |
2.加入 jetty 的 starter 依赖
1 2 3 4 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> |
from:https://www.cnblogs.com/appleat/p/9100822.html
View DetailsWebflux快速入门
SpringWebflux是SpringFramework5.0添加的新功能,WebFlux本身追随当下最火的Reactive Programming而诞生的框架,那么本篇就来简述一下这个框架到底是做什么的 一、关于WebFlux 我们知道传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的,在Servlet3.1之后才有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上,因此它的运行环境的可选择行要比传统web框架多的多。 根据官方的说法,webflux主要在如下两方面体现出独有的优势: 1)非阻塞式 其实在servlet3.1提供了非阻塞的API,WebFlux提供了一种比其更完美的解决方案。使用非阻塞的方式可以利用较小的线程或硬件资源来处理并发进而提高其可伸缩性 2) 函数式编程端点 老生常谈的编程方式了,Spring5必须让你使用java8,那么函数式编程就是java8重要的特点之一,而WebFlux支持函数式编程来定义路由端点处理请求。 二、SpringMVC与SpringWebFlux 我们先来看官网的一张图: 它们都可以用注解式编程模型,都可以运行在tomcat,jetty,undertow等servlet容器当中。但是SpringMVC采用命令式编程方式,代码一句一句的执行,这样更有利于理解与调试,而WebFlux则是基于异步响应式编程,对于初次接触的码农们来说会不习惯。对于这两种框架官方给出的建议是: 1)如果原先使用用SpringMVC好好的话,则没必要迁移。因为命令式编程是编写、理解和调试代码的最简单方法。因为老项目的类库与代码都是基于阻塞式的。 2)如果你的团队打算使用非阻塞式web框架,WebFlux确实是一个可考虑的技术路线,而且它支持类似于SpringMvc的Annotation的方式实现编程模式,也可以在微服务架构中让WebMvc与WebFlux共用Controller,切换使用的成本相当小 3)在SpringMVC项目里如果需要调用远程服务的话,你不妨考虑一下使用WebClient,而且方法的返回值可以考虑使用Reactive Type类型的,当每个调用的延迟时间越长,或者调用之间的相互依赖程度越高,其好处就越大 我个人意见是:官网明确指出,SpringWebFlux并不是让你的程序运行的更快(相对于SpringMVC来说),而是在有限的资源下提高系统的伸缩性,因此当你对响应式编程非常熟练的情况下并将其应用于新的系统中,还是值得考虑的,否则还是老老实实的使用WebMVC吧 三、Reactive Spring Web 在这里定义了最基本的服务端接口:HttpHandler和WebHandler HttpHandler HttpHandler定义了最基本的处理Http请求行为,这个接口主要作用是处理Http请求并将结果做出响应,下面这个表格是说明了Server API的使用方式及何种方式进行响应式流支持的: Server name Server API used Reactive Streams support Netty Netty API Reactor Netty Undertow Undertow API spring-web: Undertow to Reactive Streams bridge Tomcat Servlet 3.1 non-blocking I/O; Tomcat API to read and write ByteBuffers vs byte[] spring-web: Servlet 3.1 non-blocking I/O to Reactive Streams bridge Jetty Servlet 3.1 non-blocking I/O; Jetty API to write ByteBuffers vs byte[] spring-web: Servlet 3.1 […]
View Detailssoul极简入门
目录: 1. 概述 2. 单机部署 3. 接入 Dubbo 应用 4. 接入 Spring Boot 应用 5. 接入 Spring Cloud 应用 6. rateLimiter 插件 7. hystrix 插件 666. 彩蛋 作者:芋道源码 原文地址 大家好,我是艿艿,一个永远 18 岁的技术宅 1. 概述 Soul 是基于 WebFlux 实现的响应式的 API 网关,具有异步、高性能、跨语言等特点。 作者:我希望能够有一样东西像灵魂一样,保护您的微服务。在参考了 Kong、Spring Cloud Gateway 等优秀的网关后,站在巨人的肩膀上,Soul 由此诞生! 作者是艿艿的大表弟,胖友信么?! 目前 Soul 功能列表如下: 支持各种语言,无缝集成到 Dubbo、Spring Cloud、Spring Boot 中。 Soul 是极其少支持 Dubbo 的 API 网关,通过 Dubbo 泛化调用 实现。 支持各种语言(http协议),支持 dubbo,springcloud协议。 插件化设计思想,插件热插拔,易扩展。 灵活的流量筛选,能满足各种流量控制。 内置丰富的插件支持,鉴权,限流,熔断,防火墙等等。 流量配置动态化,性能极高,网关消耗在 1~2ms。 支持集群部署,支持 A/B Test, 蓝绿发布。 整体架构如下图所示: 是不是看着就贼酷炫,实际一脸懵逼。不要慌~我们先来搭建 Soul 网关。 2. 单机部署 本小节,我们来单机部署一个 Soul 服务,适合测试环境。如下图所示: 2.1 MySQL 安装 相信大家都会,艿艿就不瞎哔哔了。嘿嘿~注意,目前最好安装 5.X 版本,艿艿一开始用 8.X 存在报错的情况。 安装完成后,创建 soul 数据库。 2.2 Soul Admin […]
View DetailsTCC和两阶段提交
经常在网络上看见有人介绍TCC时,都提一句,”TCC是两阶段提交的一种”。其理由是TCC将业务逻辑分成try、confirm/cancel在两个不同的阶段中执行。其实这个说法,是不正确的。可能是因为既不太了解两阶段提交机制、也不太了解TCC机制的缘故,于是将两阶段提交机制的prepare、commit两个事务提交阶段和TCC机制的try、confirm/cancel两个业务执行阶段互相混淆,才有了这种说法。 两阶段提交(Two Phase Commit,下文简称2PC),简单的说,是将事务的提交操作分成了prepare、commit两个阶段。其事务处理方式为: 1、 在全局事务决定提交时,a)逐个向RM发送prepare请求;b)若所有RM都返回OK,则逐个发送commit请求最终提交事务;否则,逐个发送rollback请求来回滚事务; 2、 在全局事务决定回滚时,直接逐个发送rollback请求即可,不必分阶段。 * 需要注意的是:2PC机制需要RM提供底层支持(一般是兼容XA),而TCC机制则不需要。 TCC(Try-Confirm-Cancel),则是将业务逻辑分成try、confirm/cancel两个阶段执行,具体介绍见TCC事务机制简介。其事务处理方式为: 1、 在全局事务决定提交时,调用与try业务逻辑相对应的confirm业务逻辑; 2、 在全局事务决定回滚时,调用与try业务逻辑相对应的cancel业务逻辑。 可见,TCC在事务处理方式上,是很简单的:要么调用confirm业务逻辑,要么调用cancel逻辑。这里为什么没有提到try业务逻辑呢?因为try逻辑与全局事务处理无关。 当讨论2PC时,我们只专注于事务处理阶段,因而只讨论prepare和commit,所以,可能很多人都忘了,使用2PC事务管理机制时也是有业务逻辑阶段的。正是因为业务逻辑的执行,发起了全局事务,这才有其后的事务处理阶段。实际上,使用2PC机制时————以提交为例————一个完整的事务生命周期是:begin -> 业务逻辑 -> prepare -> commit。 再看TCC,也不外乎如此。我们要发起全局事务,同样也必须通过执行一段业务逻辑来实现。该业务逻辑一来通过执行触发TCC全局事务的创建;二来也需要执行部分数据写操作;此外,还要通过执行来向TCC全局事务注册自己,以便后续TCC全局事务commit/rollback时回调其相应的confirm/cancel业务逻辑。所以,使用TCC机制时————以提交为例————一个完整的事务生命周期是:begin -> 业务逻辑(try业务) -> commit(comfirm业务)。 综上,我们可以从执行的阶段上将二者一一对应起来: 1、 2PC机制的业务阶段 等价于 TCC机制的try业务阶段; 2、 2PC机制的提交阶段(prepare & commit) 等价于 TCC机制的提交阶段(confirm); 3、 2PC机制的回滚阶段(rollback) 等价于 TCC机制的回滚阶段(cancel)。 因此,可以看出,虽然TCC机制中有两个阶段都存在业务逻辑的执行,但其中try业务阶段其实是与全局事务处理无关的。认清了这一点,当我们再比较TCC和2PC时,就会很容易地发现,TCC不是两阶段提交,而只是它对事务的提交/回滚是通过执行一段confirm/cancel业务逻辑来实现,仅此而已。 参考博客: 1. https://blog.csdn.net/Paranoia_ZK/article/details/79481976#commentsedit TCC和两阶段分布式事务处理的区别 2. https://blog.csdn.net/Saintyyu/article/details/100822735 X/Open DTP模型与XA协议之我见 3、https://blog.csdn.net/Saintyyu/article/details/101054542 分布式事务的七种实现方案汇总分析 from:https://blog.csdn.net/Saintyyu/article/details/100862449
View Details终于有人把“TCC分布式事务”实现原理讲明白了!
之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下。很多朋友看了还是不知道分布式事务到底怎么回事,在项目里到底如何使用。 所以这篇文章,就用大白话+手工绘图,并结合一个电商系统的案例实践,来给大家讲清楚到底什么是 TCC 分布式事务。 首先说一下,这里可能会牵扯到一些 Spring Cloud 的原理,如果有不太清楚的同学,可以参考之前的文章:《拜托,面试请不要再问我Spring Cloud底层原理!》。 业务场景介绍 咱们先来看看业务场景,假设你现在有一个电商系统,里面有一个支付订单的场景。 那对一个订单支付之后,我们需要做下面的步骤: 更改订单的状态为“已支付” 扣减商品库存 给会员增加积分 创建销售出库单通知仓库发货 这是一系列比较真实的步骤,无论大家有没有做过电商系统,应该都能理解。 进一步思考 好,业务场景有了,现在我们要更进一步,实现一个 TCC 分布式事务的效果。 什么意思呢?也就是说,[1] 订单服务-修改订单状态,[2] 库存服务-扣减库存,[3] 积分服务-增加积分,[4] 仓储服务-创建销售出库单。 上述这几个步骤,要么一起成功,要么一起失败,必须是一个整体性的事务。 举个例子,现在订单的状态都修改为“已支付”了,结果库存服务扣减库存失败。那个商品的库存原来是 100 件,现在卖掉了 2 件,本来应该是 98 件了。 结果呢?由于库存服务操作数据库异常,导致库存数量还是 100。这不是在坑人么,当然不能允许这种情况发生了! 但是如果你不用 TCC 分布式事务方案的话,就用个 Spring Cloud 开发这么一个微服务系统,很有可能会干出这种事儿来。 我们来看看下面的这个图,直观的表达了上述的过程: 所以说,我们有必要使用 TCC 分布式事务机制来保证各个服务形成一个整体性的事务。 上面那几个步骤,要么全部成功,如果任何一个服务的操作失败了,就全部一起回滚,撤销已经完成的操作。 比如说库存服务要是扣减库存失败了,那么订单服务就得撤销那个修改订单状态的操作,然后得停止执行增加积分和通知出库两个操作。 说了那么多,老规矩,给大家上一张图,大伙儿顺着图来直观的感受一下: 落地实现 TCC 分布式事务 那么现在到底要如何来实现一个 TCC 分布式事务,使得各个服务,要么一起成功?要么一起失败呢? 大家稍安勿躁,我们这就来一步一步的分析一下。咱们就以一个 Spring Cloud 开发系统作为背景来解释。 TCC 实现阶段一:Try 首先,订单服务那儿,它的代码大致来说应该是这样子的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{ <span class="hljs-comment">// 库存服务</span> <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> InventoryService inventoryService; <span class="hljs-comment">// 积分服务</span> <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> CreditService creditService; <span class="hljs-comment">// 仓储服务</span> <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> WmsService wmsService; <span class="hljs-comment">// 对这个订单完成支付</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">()</span></span>{ <span class="hljs-comment">//对本地的的订单数据库修改订单状态为"已支付"</span> orderDAO.updateStatus(OrderStatus.PAYED); <span class="hljs-comment">//调用库存服务扣减库存</span> inventoryService.reduceStock(); <span class="hljs-comment">//调用积分服务增加积分</span> creditService.addCredit(); <span class="hljs-comment">//调用仓储服务通知发货</span> wmsService.saleDelivery(); } } |
如果你之前看过 Spring Cloud 架构原理那篇文章,同时对 Spring Cloud 有一定的了解的话,应该是可以理解上面那段代码的。 其实就是订单服务完成本地数据库操作之后,通过 Spring Cloud 的 Feign 来调用其他的各个服务罢了。 但是光是凭借这段代码,是不足以实现 TCC 分布式事务的啊?!兄弟们,别着急,我们对这个订单服务修改点儿代码好不好。 首先,上面那个订单服务先把自己的状态修改为:OrderStatus.UPDATING。 这是啥意思呢?也就是说,在 pay() 那个方法里,你别直接把订单状态修改为已支付啊!你先把订单状态修改为 UPDATING,也就是修改中的意思。 这个状态是个没有任何含义的这么一个状态,代表有人正在修改这个状态罢了。 然后呢,库存服务直接提供的那个 reduceStock() 接口里,也别直接扣减库存啊,你可以是冻结掉库存。 […]
View DetailsVSCode插件开发全攻略(十)打包、发布、升级
更多文章请戳VSCode插件开发全攻略系列目录导航。 发布方式 插件开发完了,如何发布出去分享给他人呢?主要有3种方法: 方法一:直接把文件夹发给别人,让别人找到vscode的插件存放目录并放进去,然后重启vscode,一般不推荐; 方法二:打包成vsix插件,然后发送给别人安装,如果你的插件涉及机密不方便发布到应用市场,可以尝试采用这种方式; 方法三:注册开发者账号,发布到官网应用市场,这个发布和npm一样是不需要审核的。 本地打包 无论是本地打包还是发布到应用市场都需要借助vsce这个工具。 安装:
1 2 |
npm i vsce -g |
打包成vsix文件:
1 2 |
vsce package |
打包的时候如果没有设置repository会有提示,所以最好设置一下。 生成好的vsix文件不能直接拖入安装,只能从扩展的右上角选择Install from VSIX安装: 发布应用市场 Visual Studio Code的应用市场基于微软自己的Azure DevOps,插件的身份验证、托管和管理都是在这里。 要发布到应用市场首先得有应用市场的publisher账号; 而要有发布账号首先得有Azure DevOps组织; 而创建组织之前,首先得创建Azure账号; 创建Azure账号首先得有Microsoft账号; 是不是有点晕,梳理一下: 一个Microsoft账号可以创建多个Azure组织; 一个组织可以创建多个publisher账号; 同时一个组织可以创建多个PAT(Personal Access Token,个人访问令牌); 3.1. 注册账号 首先访问 https://login.live.com/ 登录你的Microsoft账号,没有的先注册一个: 然后访问: https://aka.ms/SignupAzureDevOps ,如果你从来没有使用过Azure,那么会看到如下提示: 点击继续,默认会创建一个以邮箱前缀为名的组织。 3.2. 创建令牌 默认进入组织的主页后,点击右上角的Security: 点击创建新的个人访问令牌,这里特别要注意Organization要选择all accessible organizations,Scopes要选择Full access,否则后面发布会失败。 创建令牌成功后你需要本地记下来,因为网站是不会帮你保存的。 3.3. 创建发布账号 获得个人访问令牌后,使用vsce以下命令创建新的发布者:
1 2 |
vsce create-publisher your-publisher-name |
your-publisher-name必须是字母数字下划线,这是全网唯一的账号,然后会依次要求输入昵称、邮箱、令牌: 创建成功后会默认登录这个账号,接下来你可以直接发布了,当然,如果你是在其它地方创建的,可以试用vsce login your-publisher-name来登录。 除了用命令之外,你还可以使用网页版创建发布账号:https://marketplace.visualstudio.com/manage 3.4. 发布 发布很简单:
1 2 |
vsce publish |
发布成功后大概需要过几分钟才能在应用市场搜到。过几分钟就可以访问网页版的插件主页:https://marketplace.visualstudio.com/items?itemName=sxei.vscode-plugin-demo vscode里面也能搜到了: 3.4.1. 发布注意事项 README.md文件默认会显示在插件主页; README.md中的资源必须全部是HTTPS的,如果是HTTP会发布失败; CHANGELOG.md会显示在变更选项卡; 如果代码是放在git仓库并且设置了repository字段,发布前必须先提交git,否则会提示Git working directory not clean; 另外,如前面所说,如果Organization没有选择all accessible organizations,或者Scopes没有选择Full access,发布的时候可能会报如下错误:
1 2 3 4 |
Error: Failed Request: Unauthorized(401) - https://marketplace.visualstudio.com/_apis/gallery Be sure to use a Personal Access Token <span class="hljs-built_in">which</span> has access to **all accessible accounts**. See https://code.visualstudio.com/docs/tools/vscecli<span class="hljs-comment">#_common-questions for more information.</span> |
3.4.2. 增量发布 版本号:major.minor.patch 如果想让发布之后版本号的patch自增,例如:1.0.2 -> 1.0.3,可以这样:
1 2 |
vsce publish patch |
执行这个命令后会自动修改package.json里面的版本号。同理,vsce publish minor也是可以的。 3.5. 取消发布
1 2 |
vsce unpublish (publisher name).(extension name) |
3.6. 更新 如果修改了插件代码想要重新发布,只需要修改版本号然后重新执行vsce publish即可。 插件升级 4.1. 发布到了应用市场 如果发布到了应用市场,那么一般来说会自动检测有没有新版本,有的话会自动无感知升级,但具体什么时候会去检测我还没有研究过,已经确定的是在扩展面板搜索插件名字会自动检测,重启vscode也会检测。 4.2. 如果是本地打包 如果是打包成vsix,那么只能自己实现升级检测功能呢,通过对比服务器上某个文件的版本号,具体我就不细讲了。 […]
View DetailsVSCode插件开发全攻略(一)概览
文章索引 VSCode插件开发全攻略(一)概览 VSCode插件开发全攻略(二)HelloWord VSCode插件开发全攻略(三)package.json详解 VSCode插件开发全攻略(四)命令、菜单、快捷键 VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示 VSCode插件开发全攻略(六)开发调试技巧 VSCode插件开发全攻略(七)WebView VSCode插件开发全攻略(八)代码片段、设置、自定义欢迎页 VSCode插件开发全攻略(九)常用API总结 VSCode插件开发全攻略(十)打包、发布、升级 本系列文章同步首发于多个平台,限于精力有限,后续如有更新和修改,仅更新我的个人博客上的内容,欢迎戳这里查看最新版:http://blog.haoji.me/vscode-plugin-overview.html 写在前面 一年前我写了一篇3万多字的Chrome插件(扩展)开发全攻略,反响还不错,帮助了很多新手快速上手,甚至包括大名鼎鼎的红芯浏览器(戳这里了解更多)。 最近因工作需要又接触到了vscode插件开发,所以趁势再写一篇有关vscode插件开发的文章,记录一些自己踩过的坑以及接触vscode插件开发这2个多月以来的心得体会,让大家少走一些弯路避免重复踩坑。 目前网上有关介绍vscode插件开发的文章也有挺多的,但都不够深入,基本上都是点到为止,篇幅不大,本系列文章争取多讲一些,涵盖面会更广,干货更多。 鉴于之前写过几篇内容较多的文章大家都反馈说阅读麻烦,一篇文章内容太多看起来太累,所以这次就拆分来写。 关于vscode插件 相信大家对vscode应该都不陌生,VSCode是微软出的一款轻量级代码编辑器,免费而且功能强大,以功能强大、提示友好、不错的性能和颜值俘获了大量开发者的青睐,对JavaScript和NodeJS的支持非常好,自带很多功能,例如代码格式化,代码智能提示补全、Emmet插件等。 再强大的IDE那也不可能面面俱到什么功能都塞进去,那样只会导致IDE本身太臃肿。功能嘛,按需索取,所以,vscode的很多强大功能都是基于插件实现的,IDE只提供一个最基本的框子和最基本功能,由插件来丰富和扩展它的功能。 vscode插件可以很轻松的在应用商店搜索并下载到,应用商店官网是:https://marketplace.visualstudio.com/vscode ,vscode推出时间本身并不长,但生态发展得非常好,应用商店已经有各种各样丰富的插件供大家使用了。 因为vscode本身都是用浏览器实现的,所以其插件不用说肯定也是基于HTML+JS等前端技术实现,从形式上看就是一个类似于npm包的vsix文件,只不过按照一些特殊规范来实现一些特殊功能,所以vscode插件开发难度不大,甚至可以说熟悉了相关API之后很容易。 有必要学习vscode插件开发吗 有!而且非常有必要!每个人都会多多少少有一些自己的特殊定制需求,当你不知道开发一个IDE插件其实也很容易、或者你没有意识到通过开发插件可以帮你提升多大效率时,你并不会下意识的将一些问题的解决方式往IDE插件开发上去想。至少我曾经就是这样的,提升开发效率大部分时候想到的都是写一些脚本工具、写一些浏览器插件、写一些客户端工具等,接触到IDE插件开发之后发现原来有些问题可以通过更高效的方式来解决,毕竟IDE才是我们程序员每天接触最多的东西。 但至于可以开发什么样的插件、实现什么样的功能、以什么样的形式呈现,这就要靠你从工作和生活中去发现、去找灵感并提炼了。 demo下载 本系列文章所有demo均在这个仓库里:https://github.com/sxei/vscode-plugin-demo ,可以直接下载运行。当然还有更简单的,这个demo已经发布到应用市场了,大家可以直接点击这里下载安装,或则您也可以直接在vscode里面搜索plugin-Demo就能搜到: vscode插件能做什么 既然前面讲到学习vscode插件开发很有必要,那插件到底能做什么呢?能实现什么功能?能从哪些方面动手脚?下面我们就来列举一些好让大家有个大概了解。 6.1. 不受限的本地磁盘访问 因为vscode是基于Electron开发的,可以使用nodejs随意读写本地文件、跨域请求、甚至创建一个本地server,这都是没有任何限制的,所以只要你想做,基本上没有不能实现的。 6.2. 自定义命令、快捷键、菜单 vscode插件很多功能都是基于一个个命令实现的,我们可以自定义一些命令,这个命令将出现在按下Ctrl+Shift+P后的命令列表里面,同时可以给命令配置快捷键、配置资源管理器菜单、编辑器菜单、标题菜单、下拉菜单、右上角图标等。 6.3. 自定义跳转、自动补全、悬浮提示 自定义跳转: 自动补全: 提示: 6.4. 自定义设置、自定义欢迎页 6.5. 自定义WebView 6.6. 自定义左侧功能面板 6.7. 自定义颜色、图标主题 6.8. 新增语言支持 给某一种原有没有的语言提供语言支持,语言支持包括很多方面,比如代码高亮、语法解析、折叠、跳转、补全等; 6.9. Markdown增强 你可以自定义markdown预览的样式、添加一些新语法、新功能的支持。 6.10. 其它 其它还有比如状态栏修改、通知提示、编辑器控制、git源代码控制、任务定义、Language Server、Debug Adapter等等。 收尾 本文作为开篇,不做太多详细介绍,只是为了让大家对vscode插件有一个大致了解,后面再分篇慢慢细讲。 参考资料 微软VSCode插件开发官方文档:https://code.visualstudio.com/docs/extensions/overview from:https://www.cnblogs.com/liuxianan/p/vscode-plugin-overview.html
View Detailsnginx http to https
if ($server_port !~ 443){ rewrite ^(/.*)$ https://$host$1 permanent; }
View DetailsJS判断是否是数组
1、通过instanceof判断 instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值。
1 2 3 4 |
let a = []; a instanceof Array; //true let b = {}; b instanceof Array; //false |
在上方代码中,instanceof运算符检测Array.prototype属性是否存在于变量a的原型链上,显然a是一个数组,拥有Array.prototype属性,所以为true。 需要注意的是,prototype属性是可以修改的,所以并不是最初判断为true就一定永远为真。 其次,当我们的脚本拥有多个全局环境,例如html中拥有多个iframe对象,instanceof的验证结果可能不会符合预期,例如:
1 2 3 4 5 6 7 8 |
//为body创建并添加一个iframe对象 var iframe = document.createElement('iframe'); document.body.appendChild(iframe); //取得iframe对象的构造数组方法 xArray = window.frames[0].Array; //通过构造函数获取一个实例 var arr = new xArray(1,2,3); arr instanceof Array;//false |
导致这种问题是因为iframe会产生新的全局环境,它也会拥有自己的Array.prototype属性,让不同环境下的属性相同很明显是不安全的做法,所以Array.prototype !== window.frames[0].Array.prototype,想要arr instanceof Array为true,你得保证arr是由原始Array构造函数创建时才可行。 2、通过constructor判断 我们知道,实例的构造函数属性constructor指向构造函数,那么通过constructor属性也可以判断是否为一个数组。
1 2 |
let a = [1,3,4]; a.constructor === Array;//true |
同样,这种判断也会存在多个全局环境的问题,导致的问题与instanceof相同。 3、通过Object.prototype.toString.call()判断 Object.prototype.toString().call()可以获取到对象的不同类型,多个全局环境也适用
1 2 3 4 5 6 7 8 9 |
// 检验是否是数组 let a = [1,2,3] Object.prototype.toString.call(a) === '[object Array]';//true //检验是否是函数 let b = function () {}; Object.prototype.toString.call(b) === '[object Function]';//true //检验是否是数字 let c = 1; Object.prototype.toString.call(c) === '[object Number]';//true |
4、通过Array.isArray()判断 简单好用,而且对于多全局环境,Array.isArray() 同样能准确判断,但有个问题,Array.isArray() 是在ES5中提出,也就是说在ES5之前可能会存在不支持此方法的情况。
1 2 |
let a = [1,2,3] Array.isArray(a);//true |
最终推荐方法
1 2 3 4 5 |
if (!Array.isArray) { Array.isArray = function(arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; } |
from:https://www.cnblogs.com/chenmeijiao/p/12060845.html
View DetailsUnsupported Modules Detected: Compilation is not supported for following modules: app, KeyboardView.
打开AS时出现了Unsupported Modules Detected: Compilation is not supported for following modules: app, KeyboardView. Unfortunately you can’t have non-Gradle Java modules and Android-Gradle modules in one project的错误,解决步骤如下: (1)关闭as (2)删除.idea目录 (3)删除app/build目录 (4)重新打开as from:https://blog.csdn.net/qq_40600379/article/details/106485687
View Details