All posts by 龙生
面向切面编程
AOP 概述 面向切面编程(aspect-oriented programming),是一种将横切关注点与业务逻辑分离的编程方式。每个横切关注点都集中在一个地方,而不是分散在多处代码中。这样使我们的服务模块更加简洁,因为它们只包含了主要关注点的代码,而次要的功能或者说辅助的功能被转移到切面中了。 aop-1.png 上图表示划分为三个服务模块的应用,每个模块提供相应的服务,而且这些模块都需要类似的辅助功能,例如日志、安全、事务等等。我们并不想在各个模块中写重复的日志、安全、事务的代码,那么就可以使用选用切面这个方案,来解决这个问题。 AOP 术语 aop-2.png advice – 通知 切面的具体行为,即要切入执行的代码 pointcut – 切点 通知被应用的具体位置 join point – 连接点 程序运行时,能够应用通知的所有点 aspect – 切面 什么时候在什么地方做什么事情,是切点和通知的结合 target – 目标对象 被切入功能的目标对象 introduction – 引入 将新的方法或属性引入到现有的类中 weaving – 织入 把切面应用到目标对象并创建新的代理对象的过程 代理模式 代理模式是使用代理对象完成用户请求,屏蔽用户对真实对象访问的一种设计模式。现实生活中,代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,他只和代理人通信。而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人。 AOP 就是使用代理模式实现的,其中的代理类就相当于AOP中的切面。 aop-3.png 静态代理 之所以称为静态代理,是因为在程序运行前,代理类就已经存在了。 举个例子 一般艺人都需要助理,来帮他跑腿,演出前谈价格,演出后收钱,只有表演的时候艺人才亲自出马。 定义一个艺人接口
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package org.nocoder.proxy.staticproxy; /** * 艺人接口 * @author jason * @date 2019/2/14. */ public interface Artist { /** * 表演 */ void perform(); } |
定义艺人实现类刘德华
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package org.nocoder.proxy.staticproxy; /** * 艺人刘德华 * * @author jason * @date 2019/2/14. */ public class LiuDehua implements Artist { private LiuDehua() { } public static LiuDehua getInstance() { return new LiuDehua(); } public void perform() { System.out.println("刘德华出场演唱笨小孩..."); } } |
编写代理类
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 |
package org.nocoder.proxy.staticproxy; /** * 艺人助理(代理类) * * @author jason * @date 2019/2/14. */ public class ArtistProxy implements Artist { private LiuDehua liuDehua; private ArtistProxy() { } public ArtistProxy(LiuDehua liuDehua) { this.liuDehua = liuDehua; } public void perform() { System.out.println("助理出面谈价格,签合同..."); liuDehua.perform(); System.out.println("助理出面收钱..."); } } |
运行main方法,将艺人实例传入代理类的构造方法,然后调用代理类的perform()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package org.nocoder.proxy.staticproxy; /** * @author jason * @date 2019/2/14. */ public class StaticProxyDemo { public static void main(String[] args) { LiuDehua liuDehua = LiuDehua.getInstance(); ArtistProxy proxy = new ArtistProxy(liuDehua); proxy.perform(); } } |
运行结果
1 2 3 4 5 |
助理出面谈价格,签合同... 刘德华出场演唱笨小孩... 助理出面收钱... Process finished with exit code 0 |
静态代理的缺点 假设主题接口中的方法很多,为每一个接口写一个代理方法也很麻烦。如果接口有变动,则真实主题和代理类都要修改,不利于系统维护; 动态代理 动态代理是在程序运行时,利用Java反射机制动态的生成代理类的代理模式。 Jdk动态代理 JDK的动态代理依靠接口实现 如果类并没有实现接口,则不能使用Jdk的动态代理 定义图书服务接口
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package org.nocoder.proxy.jdkproxy; /** * 图书服务接口 * @author jason * @date 2019/2/14. */ public interface BookService { /** * 新增图书接口 */ void addBook(); } |
编写图书服务实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package org.nocoder.proxy.jdkproxy; /** * 图书服务实现类 * @author jason * @date 2019/2/14. */ public class BookServiceImpl implements BookService { @Override public void addBook() { System.out.println("新增图书"); } } |
编写InvocationHandler实现类
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 |
package org.nocoder.proxy.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * JDK 动态代理 * @author jason * @date 2019/2/14. */ public class BookServiceInvocationHandler implements InvocationHandler { private Object target; public BookServiceInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("事务开始"); Object result = method.invoke(target, args); System.out.println("事务结束"); return result; } } |
运行测试程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package org.nocoder.proxy.jdkproxy; import java.lang.reflect.Proxy; /** * JDK动态代理演示 * * @author jason * @date 2019/2/14. */ public class JdkProxyDemo { public static void main(String[] args) { BookServiceInvocationHandler invocationHandler = new BookServiceInvocationHandler(new BookServiceImpl()); // JDK 动态代理只支持接口 BookService bookServiceProxy = (BookService) Proxy.newProxyInstance( BookServiceImpl.class.getClassLoader(), BookServiceImpl.class.getInterfaces(), invocationHandler); bookServiceProxy.addBook(); } } |
运行结果
1 2 3 4 5 |
事务开始 新增图书 事务结束 Process finished with exit code 0 |
CGLIB动态代理 JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这时就要使用cglib动态代理了。使用cglib需要依赖cglib的jar,使用maven为例
1 2 3 4 5 |
<dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.2.4</version> </dependency> |
定义图书服务类
1 2 3 4 5 6 7 8 9 10 11 |
package org.nocoder.proxy.cglibproxy; /** * @author jason * @date 2019/2/14. */ public class BookService { public void addBook() { System.out.println("新增图书"); } } |
编写MethodInterceptor实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package org.nocoder.proxy.cglibproxy; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author jason * @date 2019/2/14. */ public class BookServiceMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("事务开始"); methodProxy.invokeSuper(o, objects); System.out.println("事务结束"); return null; } } |
运行测试程序 […]
View DetailsDubbo和Spring Cloud微服务架构比较
Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司;只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主。 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果。它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 虽然微服务架构没有公认的技术标准和规范或者草案,但业界已经有一些很有影响力的开源微服务架构框架提供了微服务的关键思路,例如 Dubbo 和 Spring Cloud。 各大互联网公司也有自研的微服务框架,但其模式都与这二者相差不大。 微服务主要的优势 降低复杂度 将原来耦合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累。 每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界;每个服务开发者只专注服务本身,通过使用缓存、DAL 等各种技术手段来提升系统的性能,而对于消费方来说完全透明。 可独立部署 由于微服务具备独立的运行进程,所以每个微服务可以独立部署。当业务迭代时只需要发布相关服务的迭代即可,降低了测试的工作量同时也降低了服务发布的风险。 容错 在微服务架构下,当某一组件发生故障时,故障会被隔离在单个服务中。比如通过限流、熔断等方式降低错误导致的危害,保障核心业务正常运行。 扩展 单块架构应用也可以实现横向扩展,就是将整个应用完整的复制到不同的节点。 当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。 本文主要围绕微服务的技术选型、通讯协议、服务依赖模式、开始模式、运行模式等几方面来综合比较 Dubbo 和 Spring Cloud 这 2 种开发框架。 架构师可以根据公司的技术实力并结合项目的特点来选择某个合适的微服务架构平台,以此稳妥地实施项目的微服务化改造或开发进程。 核心部件 微服务的核心要素在于服务的发现、注册、路由、熔断、降级、分布式配置,基于上述几种必要条件对 Dubbo 和 Spring Cloud 做出对比。 总体架构 Dubbo 核心部件(如下图): Provider:暴露服务的提供方,可以通过 jar 或者容器的方式启动服务。 Consumer:调用远程服务的服务消费方。 Registry:服务注册中心和发现中心。 Monitor:统计服务和调用次数,调用时间监控中心。(Dubbo 的控制台页面中可以显示,目前只有一个简单版本。) Container:服务运行的容器。 Dubbo 总体架构 Spring Cloud总体架构(如下图): Service Provider: 暴露服务的提供方。 Service Consumer:调用远程服务的服务消费方。 EureKa Server: 服务注册中心和服务发现中心。 Spring Cloud 总体架构 点评:从整体架构上来看,二者模式接近,都需要服务提供方,注册中心,服务消费方。 微服务架构核心要素 Dubbo 只是实现了服务治理,而 Spring Cloud 子项目分别覆盖了微服务架构下的众多部件,服务治理只是其中的一个方面。 Dubbo 提供了各种 Filter,对于上述中“无”的要素,可以通过扩展 Filter 来完善。例如: 分布式配置:可以使用淘宝的 diamond、百度的 disconf 来实现分布式配置管理。 服务跟踪:可以使用京东开源的 Hydra,或者扩展 Filter 用 Zippin 来做服务跟踪。 批量任务:可以使用当当开源的 Elastic-Job、tbschedule。 点评:从核心要素来看,Spring […]
View Details在ASP.NET Core中使用百度在线编辑器UEditor
0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个。不过服务端只有ASP.NET版的,如果是为了能尽快使用,只要把ASP.NET版的服务端作为应用部署在IIS上就可以立即使用了。不过我的需求并不急,所以把ASP.NET移植到了ASP.NET Core上。整个过程很简单,只是重新引用了一些包,修改了几处代码,另外就是把Controller中比较长的一个switch语句块重构为了字典,根据url中的action参数从字典中找出并调用相应的Action处理,这样的好处就是如果要扩展action支持的操作无需修改源代码,只要扩展字典就可以,对扩展开放,对修改关闭。最后把服务端功能打成了nuget包UEditorNetCore,方便使用。这篇博客主要就介绍下如何使用UEditorNetCore快速实现UEditor服务端,也可以直接使用源代码中的示例,希望对有这方面需求的园友有所帮助。 0x01 总体设计 当接收到action后,UEditorService会从UEditorActionCollection中找到这个action对应的方法并调用,同时传入HttpContext参数。这些方法调用基层的服务XxxxHandler完成功能,并把返回内容通过HttpContext.Response.WriteAsync()方法写入。如果要扩展对action的支持,可以扩展UEditorActionCollection,具体方法后面有介绍。 0x02 如何使用UEditorNetCore 1.安装UEditorNetCore
1 |
Install-Package UEditorNetCore |
2.在Startup.cs的ConfigureServices方法中添加UEditorNetCore服务
1 2 3 4 5 6 7 |
public void ConfigureServices(IServiceCollection services) { //第一个参数为配置文件路径,默认为项目目录下config.json //第二个参数为是否缓存配置文件,默认false services.AddUEditorService() services.AddMvc(); } |
3.添加Controller用于处理来自UEditor的请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[Route("api/[controller]")] //配置路由 public class UEditorController : Controller { private UEditorService ue; public UEditorController(UEditorService ue) { this.ue = ue; } public void Do() { ue.DoAction(HttpContext); } } |
4.修改前端配置文件ueditor.config.js serverUrl需要参照第3步Controller中配置的路由,按照上面步骤3中的配置,需要以下配置:
1 |
serverUrl:"/api/UEditor" |
这样配置后当前端要获取服务端UEditor配置时就会访问/api/UEditor?action=config。 5.修改服务端配置config.json 上传类的操作需要配置相应的PathFormat和Prefix。示例部署在web根目录,因此Prefix都设置为"/"。使用时要根据具体情况配置。 例如示例中图片上传的配置如下:
1 2 |
"imageUrlPrefix": "/", /* 图片访问路径前缀 */ "imagePathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", |
关于PathFormat的详细配置可参照官方文档。 6.添加javascript引用
1 2 3 |
<script type="text/javascript" charset="utf-8" src="~/lib/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="~/lib/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="~/lib/ueditor/lang/zh-cn/zh-cn.js"></script> |
0x03 扩展action UEditor前端和后端交互主要通过在url中给出不同的action参数实现的,例如/api/UEditor?action=config会从服务端获取UEditor配置信息。UEditorNetCore目前支持的有8种action: config 获取服务端配置信息 uploadimage 上传图片 uploadscrawl 上传涂鸦 uploadvideo 上传视频 uploadfile 上传文件 listimage 多图片上传 listfile 多文件上传 catchimage 抓取图片 如果以上action无法满足需求,可以方便的增加、覆盖、移除action。 增加action
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public void ConfigureServices(IServiceCollection services) { services.AddUEditorService() .Add("test", context => { context.Response.WriteAsync("from test action"); }) .Add("test2", context => { context.Response.WriteAsync("from test2 action"); }); services.AddMvc(); } |
以上代码增加了名字为test和test2两个action,作为示例仅仅返回了字符串。当访问/api/UEditor?action=test时会返回"from test action"。在扩展action时可以使用Config获取服务端配置,也可以使用已有的Handlers,具体可以参考源代码。 覆盖现有action 上面的Add方法除了添加新action外还可以覆盖现有action。当现有的action可能不符合你的要求,可以Add一个同名的action覆盖现有的。 移除action 如果要移除某个action,可以使用Remove方法。
1 2 3 4 5 6 |
public void ConfigureServices(IServiceCollection services) { services.AddUEditorService() .Remove("uploadvideo"); services.AddMvc(); } |
以上代码中的Remove("uploadvideo")方法移除了名为uploadvideo的action。 0x04 相关资源 UEditorNetCore代码和示例:https://github.com/durow/UEditorNetCore UEditor代码:https://github.com/fex-team/ueditor UEditor官网:http://ueditor.baidu.com/website/index.html from:https://www.cnblogs.com/durow/p/6116393.html
View Detailsjs中的Math.random()
random() 方法可返回介于 0 ~ 1 之间的一个随机数。 这里有几种用法: 1.从数组中随机获取成员 var items = [12,a,9,p,8]; var randomItem = items[Math.floor(Math.random() * items.length)]; 2.生成从0到指定值的数字数组 var numbersArray = [] , max = 100; for( var i=1; numbersArray.push(i++) < max;); // numbers = [1,2,3 … 100] 3.生成随机的字母数字字符串 function radomcharnum(len){ var str = ""; for(;str.length<len;str+=Math.random().toString(36).substr(2)); return str.substr(0,len); } 3.得到指定范围的整数(需要Math.floor()或者parseInt()或者Math.ceil()) var randomNum = Math.random()*5; console.log(parseInt(randomNum));//1 console.log(Math.floor(randomNum));//0 Math.floor(Math.random()*(max-min+1)+min);//max为期待的最大的数,min为最小的数 使用parseInt也是可以的。 from:https://www.cnblogs.com/Catherine001/p/7265597.html
View DetailsVMMap v3.26
Download VMMap (626 KB) Run now from Sysinternals Live. Introduction VMMap is a process virtual and physical memory analysis utility. It shows a breakdown of a process’s committed virtual memory types as well as the amount of physical memory (working set) assigned by the operating system to those types. Besides graphical representations of memory usage, VMMap also shows summary information and a detailed process memory map. Powerful filtering and refresh capabilities allow you to identify the sources of process memory usage and the memory cost of application features. Besides flexible views […]
View DetailsDubbo与DubboX区别
前世今生: Dubbo源于阿里的淘宝网开源的分布式的服务架构,致力于提供高性能和透明化的RPC远程服务调用方案,是SOA服务化治理方案的核心框架。淘宝网将其开源之后,得到了很多的拓展和支持(比较出名的有:当当网的扩展版本dubbox,京东的扩展版本jd-hydra等) Dubbox(即Dubbo eXtensions)是当当网Fork基于dubbo2.x的升级版本,兼容原有的dubbox。其中升级了zookeeper和spring版本,并且支持restfull风格的远程调用。。 版本: Dubbo目前已停止更新; Dubbox目前还在更新。 说明:dubbox和dubbo 2.x是兼容的, 没有改变dubbo的任何已有的功能和配置方式(除了升级了Spring之类的版本)。 据说淘宝网dubbo与一个非开源的框架HSF有争执,导致dubbo的团队已经解散了,但是其扩展的版本dubbox却得到不断的发展(升级更新); <!——--升级详情——--|——————-- dubbox-2.8.0:该版本已经在生产环境中使用,主要支持REST风格远程调用、支持Kryo和FST序列化、升级了Spring和Zookeeper客户端、调整了demo应用等等 dubbox-2.8.1:主要支持基于嵌入式tomcat的http-remoting,优化了REST客户端性能,在REST中支持限制服务端接纳的最大HTTP连接数等等 dubbox-2.8.2: 支持REST中的HTTP logging,包括HTTP header的字段和HTTP body中的消息体,方便调试、日志纪录等等 提供辅助类便于REST的中文处理 改变使用@Reference annotation配置时的异常处理方式,即当用annotation配置时,过去dubbo在启动期间不抛出依赖服务找不到的异常,而是在具体调用时抛出NPE,这与用XML配置时的行为不一致。 较大的充实了Dubbo REST的文档 dubbox-2.8.3: 在REST中支持dubbo统一的方式用bean validation annotation作参数校验(沈理) 在RpcContext上支持获取底层协议的Request/Response(沈理) 支持采用Spring的Java Config方式配置dubbo(马金凯) 在Dubbo协议中支持基于Jackson的json序列化(Dylan) 在Spring AOP代理过的对象上支持dubbo annotation配置(Dylan) 修正Dubbo管理界面中没有consumer时出现空指针异常(马金凯) 修正@Reference annotation中protocol设置不起作用的bug(沈理) 修正@Reference annotation放在setter方法上即会出错的bug(Dylan) 详见:https://github.com/dangdangdotcom/dubbox/releases ———/> 嵌入: dubbo:嵌入式Jetty dubbox:基于嵌入式tomcat实现dubbo的 HTTP remoting体系(即dubbo-remoting-http) 对Servlet API的支持: dubbo:2.5 dubbox:升级到3.1 序列化: dubbo: dubbox:基于Dubbo默认的RPC协议添加新的JSON序列化实现; 支持基于Kryo和FST的Java高效序列化实现; Zookeeper注册中心: dubbo:Dubbo提供了Zookeeper注册中心,在整个Dubbo的设计里面充分考虑到了各类用户的需求,一些底层的通讯或者是信息存储都提供有大量的不同的存储方案; dubbox:升级ZooKeeper客户端到最新版本; 使用场景: dubbo:使用Dubbo的RPC调用方式,服务间仍然会存在API强依赖; dubbox:相对于Dubbo支持了REST风格的原创调用(HTTP +JSON/XML); ——————————————————- ——简言之(dubbox基于dubbo的升级): ——————- 支持REST风格远程调用(HTTP + JSON/XML); 支持基于Kryo和FST的Java高效序列化实现; 支持基于Jackson的JSON序列化; 支持基于嵌入式Tomcat的HTTP remoting体系; 升级Spring至3.x; 升级ZooKeeper客户端; 支持完全基于Java代码的Dubbo配置; ————————————————- 附录: Dubbo: 官网首页:http://dubbo.io/ , 官方用户指南: http://dubbo.io/User+Guide-zh.htm可以当做SOA架构的学习资料 Dubbox: dubbox入门:http://www.cnblogs.com/yjmyzz/p/dubbox-demo.html dubbox架构: http://www.cnblogs.com/Javame/p/3632473.html 当当网dubbox学习参考文档:http://dangdangdotcom.github.io/dubbox/ 分布式服务框架 dubbo/dubbox 入门示例:http://www.cnblogs.com/wanghang/p/6298957.html ———————- […]
View DetailsGUI
图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。 与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。然而这界面若要通过在显示屏的特定位置,以”各种美观而不单调的视觉消息“提示用户”状态的改变“,势必得比简单的消息呈现花上更多的计算能力。 图形用户界面是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其它一些日常任务。与通过键盘输入文本或字符命令来完成例行任务的字符界面相比,图形用户界面有许多优点。图形用户界面由窗口、下拉菜单、对话框及其相应的控制机制构成,在各种新式应用程序中都是标准化的,即相同的操作总是以同样的方式来完成,在图形用户界面,用户看到和操作的都是图形对象,应用的是计算机图形学的技术。 GUI 即人机交互图形化用户界面设计。纵观国际相关产业在图形化用户界面设计方面的发展现状,许多国际知名公司早已意识到 GUI 在产品方面产生的强大增值功能,以及带动的巨大市场价值,因此在公司内部设立了相关部门专门从事 GUI 的研究与设计,同业间也成立了若干机构,以互相交流 GUI 设计理论与经验为目的。随着中国 IT 产业,移动通讯产业,家电产业的迅猛发展,在产品的人机交互界面设计水平发展上日显滞后,这对于提高产业综合素质,提升与国际同等业者的竞争能力等等方面无疑起了制约的作用。 GUI的广泛应用是当今计算机发展的重大成就之一,它极大地方便了非专业用户的使用。人们从此不再需要死记硬背大量的命令,取而代之的是可以通过窗口、菜单、按键等方式来方便地进行操作。而嵌入式GUI具有下面几个方面的基本要求:轻型、占用资源少、高性能、高可靠性、便于移植、可配置等特点。 from:https://baike.baidu.com/item/GUI/479966
View Details一个axios的简单教程
首先要明白的是axios是什么:axios是基于promise(诺言)用于浏览器和node.js是http客户端。 axios的作用是什么呢:axios主要是用于向后台发起请求的,还有在请求中做更多是可控功能。 特点:支持浏览器和node.js 支持promise 能拦截请求和响应 能转换请求和响应数据 能取消请求 自动转换JSON数据 浏览器支持防止CSRF(跨站请求伪造) 这里你一定会想promise是什么东西,以下是promise的个人理解: promise是什么:是一个对象用来传递异步操作的信息,它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的api,可供进一步的处理。 promise的作用:Promise的出现主要是解决地狱回调的问题,比如你需要结果需要请求很多个接口,这些接口的参数需要另外那个的接口返回的数据作为依赖,这样就需要我们一层嵌套一层,但是有了Promise 我们就无需嵌套。 promise的本质是什么:分离异步数据获取和业务 基本使用方法: axios执行GET请求 GET 请求方法 执行POST请求 POST请求方法 执行多个并发请求 多个并发请求 get和post都是基于promise的所以写法上很相似,是用then和catch,使用这种方法来进行发送请求。 还有一个axios重要的知识点就是拦截器 拦截器 在请求或响应被 then 或 catch 处理前拦截它们(拦截器可以做什么:在请求或者响应时拦截下来进行处理) 拦截器分为请求拦截器和响应拦截器 请求拦截器(interceptors.requst)是指可以拦截每次或指定HTTP请求,并可修改配置项。 响应拦截器(interceptors.response)可以在每次HTTP请求后拦截住每次或指定HTTP请求,并可修改返回结果项。 拦截器的写法 拦截器的工作流程: 拦截器工作流程 移除拦截器 移除拦截器 自定义 axios 实例添加拦截器 添加拦截器 取消 使用 cancel token 取消请求 可以使用 CancelToken.source 工厂方法创建 cancel token 参考资料:axios中文文档 from:https://www.jianshu.com/p/13cf01cdb81f
View Details如何快速搭建VPN,六款VPN服务器上最好的自由和开源工具,轻松搭建个人VPN
个人外贸企业需要访问国外的网络,怎么办?如果您想尝试建立您自己的 VPN,但是不确定从哪里开始,那么您来对地方了,我将比较 6 个在您自己的服务器上搭建和使用 VPN 的最好的自由和开源工具。不管您是想为您的企业建立站点到站点的 VPN,还是只是想创建一个远程代理访问以解除访问限制并对 ISP 隐藏你的互联网流量,都可以通过 VPN 来达成。 根据您的需求和条件,并参考您自己的技术特长、环境以及您想要通过 VPN 实现的目标。需要考虑以下因素: •VPN 协议 •客户端的数量和设备类型 •服务端的兼容性 •需要的技术专业能力 Algo Algo 是从下往上设计的,可以为需要互联网安全代理的商务旅客创建 VPN 专用网。它“只包括您所需要的最小化的软件”,这意味着为了简单而牺牲了可扩展性。Algo 是基于 StrongSwan 的,但是删除了所有您不需要的东西,这有另外一个好处,那就是去除了新手可能不会注意到的安全漏洞。 作为额外的奖励,它甚至可以屏蔽广告! Algo 只支持 IKEv2 协议和 Wireguard。因为对 IKEv2 的支持现在已经内置在大多数设备中,所以它不需要像 OpenVPN 这样的客户端应用程序。Algo 可以使用 Ansible 在 Ubuntu (首选选项)、Windows、RedHat、CentOS 和 FreeBSD 上部署。 使用 Ansible 可以自动化安装,它会根据您对一组简短的问题的回答来配置服务。卸载和重新部署也非常容易。 Algo 可能是在本文中安装和部署最简单和最快的 VPN。它非常简洁,考虑周全。如果您不需要其他工具提供的高级功能,只需要一个安全代理,这是一个很好的选择。请注意,Algo 明确表示,它不是为了解除地理封锁或逃避审查,主要是为了加密。 Streisand Streisand 可以使用一个命令安装在任何 Ubuntu 16.04 服务器上;这个过程大约需要 10 分钟。它支持 L2TP、OpenConnect、OpenSSH、OpenVPN、Shadowsocks、Stunnel、Tor bridge 和 WireGuard。根据您选择的协议,您可能需要安装客户端应用程序。 在很多方面,Streisand 与 Algo 相似,但是它提供了更多的协议和定制。这需要更多的工作来管理和维护,但也更加灵活。注意 Streisand 不支持 IKEv2。因为它的多功能性,我认为 Streisand 在某国和土耳其这样的地方绕过审查制度更有效,但是 Algo 的安装更容易和更快。 使用 Ansible 可以自动化安装,所以不需要太多的专业技术知识。通过向用户发送自定义生成的连接指令,包括服务器 SSL 证书的嵌入副本,可以轻松添加更多用户。 卸载 Streisand 是一个快速无痛的过程,您也可以随时重新部署。 OpenVPN OpenVPN 要求客户端和服务器应用程序使用其同名的协议建立 VPN 连接。OpenVPN […]
View Detailsphp7.1以上 mcrypt_generic_open is deprecated 报错处理
php7.1以上. mcrypt_generic_open is deprecated 这个错误, 就是因为mcrypt扩展,在php7.1以上被废弃,服务器不设置报错等级的话, 这个错误会被框架拦截,然后报出微信demo里的40007错误, 具体解决方案,所有 mcrypt扩展的代码,全部加上 错误抑制符 ,例如 //使用BASE64对需要解密的字符串进行解码 原来的代码
1 2 3 4 5 6 7 8 9 10 |
//使用BASE64对需要解密的字符串进行解码 $ciphertext_dec = base64_decode($encrypted); $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); $iv = substr($this->key, 0, 16); mcrypt_generic_init($module, $this->key, $iv); //解密 $decrypted = mdecrypt_generic($module, $ciphertext_dec); mcrypt_generic_deinit($module); mcrypt_module_close($module); |
修改的代码
1 2 3 4 5 6 7 8 9 10 |
//使用BASE64对需要解密的字符串进行解码 $ciphertext_dec = base64_decode($encrypted); @$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); $iv = substr($this->key, 0, 16); @mcrypt_generic_init($module, $this->key, $iv); //解密 @$decrypted = mdecrypt_generic($module, $ciphertext_dec); @mcrypt_generic_deinit($module); @mcrypt_module_close($module); |
然后我的问题就解决了。 我的问题主要出在微信的加解密函数上,遇到的坑有几个 1.文档给的class默认有的是小写, 2.一个文件有多个class得拆开 3.构造函数获取的变量名称不对得修改… 这些用断点调试都可以进行解决 还有一种方案是, 我听我朋友说可以用 openssl代替mcrypt扩展的方案(mcrypt编码,openssl解码), 得重写编写微信demo里的代码,虽然我没成功… from:https://blog.csdn.net/qq_38686693/article/details/81388329
View Details