Dubbo高手之路2,6种扩展机制详解
目录
- 一、Dubbo扩展机制的概述
- 二、Dubbo的自适应扩展机制
- 1. 什么是自适应扩展机制
- 2. 自适应扩展机制的使用示例
- 三、Dubbo的SPI扩展机制
- 1. 什么是SPI扩展机制
- 2. SPI扩展机制的使用示例
- 3. Dubbo的SPI扩展机制中自定义扩展点的实现示例
- 四、Dubbo的自定义扩展点机制
- 1. 什么是自定义扩展点机制
- 2. 自定义扩展点机制的使用示例
- 3. Dubbo的自定义扩展点机制的实现示例
- 五、Dubbo的过滤器扩展机制
- 1. Dubbo的过滤器机制概述
- 2. 过滤器扩展机制的使用示例
- 3. 自定义过滤器的实现示例
- 六、Dubbo的负载均衡扩展机制
- 1. Dubbo的负载均衡扩展机制概述
- 2. 负载均衡扩展机制的使用示例
- 3.自定义负载均衡策略的实现示例
- 七、Dubbo的容错机制扩展
- 1. Dubbo的容错机制概述
- 2. 容错机制扩展的使用示例
- 3. 自定义容错策略的实现示例
- 八、Dubbo的扩展机制实践
- 1. 实现一个使用自定义扩展点、过滤器、负载均衡器和容错机制的 Dubbo 服务
大家好,我是哪吒。
Dubbo是一个高性能的Java RPC框架。RPC是远程过程调用的缩写,其基本思想是:客户端像调用本地方法一样,通过网络请求调用远程服务器上的服务。Dubbo可以帮助我们更方便地构建分布式应用程序,它具有高效的远程调用、服务自动注册和发现、负载均衡、容错机制等众多特性,是企业级应用中可靠的基础架构。
一、Dubbo扩展机制的概述
Dubbo是一个高性能的分布式服务框架,广泛应用于各种规模和种类的企业级项目中。在实际应用过程中,Dubbo的核心能力是扩展机制,它可以让Dubbo具有更强的可定制化能力,也可以让Dubbo更好地适应各种应用场景。
Dubbo的扩展机制主要包括:自适应扩展机制、SPI扩展机制、自定义扩展点机制、过滤器扩展机制、负载均衡扩展机制和容错机制扩展。这些机制使得Dubbo的使用更加灵活方便,可以满足不同需要的业务场景,也可以根据实际情况来选择合适的扩展机制。
在Dubbo的扩展机制中,尤其需要注意自定义扩展点机制和SPI扩展机制。这些机制是Dubbo中较为重要和常用的扩展机制,充分了解这些机制可以让应用程序更加灵活和可定制。
下图展示了Dubbo扩展机制的调用流程:
上图中,Dubbo客户端首先会通过ExtensionLoader加载需要使用的扩展点,ExtensionLoader会根据客户端传入的扩展点名和配置,创建对应的扩展点实例,并返回给客户端,客户端再通过返回的扩展点实例调用相应的方法。
二、Dubbo的自适应扩展机制
1. 什么是自适应扩展机制
自适应扩展机制是Dubbo提供的一种机制,它可以使Dubbo框架根据实际使用情况动态地选择不同的扩展实现,从而达到最优的效果。
自适应扩展机制的实现方式是通过在扩展接口的代理类中,根据实际情况动态地生成对应扩展实现的代理类实例。
下图是自适应扩展机制的详细时序图:
上图中,Client先调用ExtensionLoader加载扩展点,并解析配置文件,ExtensionLoader根据配置文件查找实现类,然后创建一个AdaptiveExtension的代理对象,并将该代理对象返回给Client。Client调用代理对象的方法时,AdaptiveExtension会根据配置使用具体的扩展点实现,并将调用转发给具体的扩展点实现,最后将结果返回给Client。
2. 自适应扩展机制的使用示例
在Dubbo框架中,有一个名为Protocol的扩展接口,它有多种不同的实现方式,如dubbo、rmi、http等。在使用Dubbo时,我们可以通过@Reference注解来注入对应的扩展实现,如:
@Reference(protocol = "dubbo")
private DemoService demoService;
在上述代码中,我们指定了使用dubbo协议的DemoService接口的扩展实现。
我们也可以通过adaptive属性来实现自适应调用,如:
@Reference(adaptive = "true")
private Protocol protocol;
在上述代码中,我们使用了adaptive属性,并注入了Protocol类型的实例。这时,Dubbo框架会根据实际情况动态地生成对应实现的代理类,并返回对应的实例。
三、Dubbo的SPI扩展机制
1. 什么是SPI扩展机制
Dubbo使用了Java的SPI(Service Provider Interface)扩展机制。SPI是JDK内置的一种服务发现机制,其具体实现方式是在资源文件META-INF/services中通过名称为SPI接口的全限定类名创建一个文本文件,在这个文本文件中可以写入该SPI接口的实现类全限定类名,这样可以实现动态加载实现类的目的。
Dubbo中的SPI扩展机制能够在不修改核心源代码的前提下,通过修改配置文件或者实现自定义拓展类的方式来替换或增加核心功能。
下图描述了 Dubbo SPI 扩展机制的工作流程:
上图描述了 Dubbo SPI 扩展机制的工作流程,其中:
- 用户向 Dubbo Framework 请求获取 ExtensionLoader,ExtensionLoader 是 Dubbo SPI 扩展机制的核心类。
- Dubbo Framework 加载 ExtensionLoader,并返回给用户。
- 用户调用 ExtensionLoader 的方法。
- ExtensionLoader 根据指定的 Extension 接口,通过 SPI 机制加载 Extension 实现。
- Extension 实现将被加载,ExtensionLoader 返回 Extension 实现给用户。
2. SPI扩展机制的使用示例
首先,我们需要定义一个SPI扩展接口,让Dubbo的扩展实现类都实现该接口。示例代码:
package com.example.extension;import com.alibaba.dubbo.common.extension.SPI;@SPI("default")
public interface PrintService {void print(String msg);
}
在接口上添加@SPI注解,指定该扩展的默认实现类。
然后,我们需要在META-INF/services目录下创建一个“接口全限定类名”的文件名的文件,文件中写入我们实现的SPI扩展类的全限定类名。比如我们需要同过实现PrintService接口来实现打印功能,那么我们在META-INF/services/目录下创建一个名为“com.example.extension.PrintService”的文件,文件内容为:
com.example.extension.impl.ConsolePrintServiceImpl
接下来,我们就可以通过Dubbo框架自动加载通过SPI机制注册的实现类了。示例代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);PrintService printService = ExtensionLoader.getExtensionLoader(PrintService.class).getDefaultExtension();printService.print("hello world!");
以上代码中,我们使用Dubbo的扩展加载器ExtensionLoader来获取PrintService接口的默认实现类,然后调用该实现类的print()方法即可实现打印功能。
3. Dubbo的SPI扩展机制中自定义扩展点的实现示例
在Dubbo框架中,我们可以通过自定义扩展点来增强Dubbo的功能。自定义扩展点需要实现Dubbo提供的ExtensionFactory接口,并在META-INF/dubbo/internal/路径下创建一个文件名为com.alibaba.dubbo.common.extension.ExtensionFactory
的文件,文件中写入
扩展点实现类的全限定类名。示例代码:
package com.example.extension;import com.alibaba.dubbo.common.extension.ExtensionFactory;public class MyExtensionFactory implements ExtensionFactory {
@Override
public <T> T getExtension(Class<T> type, String name) {
if (type.equals(PrintService.class)) {
return (T) new ConsolePrintServiceImpl();
}
return null;
}
}
在MyExtensionFactory中实现getExtension()方法,并根据type参数判断获取哪个扩展实现类。在本示例中,我们仅仅实现了PrintService接口的实现类,因此只需要判断type参数是否为PrintService类即可。
下一步,我们需要在META-INF/dubbo/internal/目录下创建一个名为com.alibaba.dubbo.common.extension.ExtensionFactory
的文件,文件内容为我们实现的扩展点实现类全限定类名。比如我们实现的扩展点实现类为com.example.extension.MyExtensionFactory
,那么我们就要在META-INF/dubbo/internal/目录下创建一个名为com.alibaba.dubbo.common.extension.ExtensionFactory
的文件,并将文件内容写为com.example.extension.MyExtensionFactory。
最后,我们在程序中就可以使用自定义的扩展点了。示例代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
PrintService printService = ExtensionLoader.getExtensionLoader(PrintService.class).getExtension("console");
printService.print("hello world!");
在以上示例代码中,我们通过getExtension()方法来获取PrintService接口的实现类。getExtension()方法中的参数为扩展点的name属性,该属性值默认为“default”。在本示例中我们将name的值设置为“console”,因此即使用了我们自定义的扩展点实现类。
四、Dubbo的自定义扩展点机制
1. 什么是自定义扩展点机制
Dubbo的自定义扩展点机制是在SPI扩展机制的基础上,增加了自定义扩展点的实现方式。通过Dubbo的扩展机制,我们可以通过配置文件切换Dubbo内部的实现方式,但是对于用户自己实现的功能模块,如何进行扩展呢?这里就需要用到自定义扩展点机制了。
下图是自定义扩展点机制的详细时序图:
在上图中,用户首先将自己实现的扩展点注册到Dubbo中,然后在需要使用该扩展点的时候,Dubbo会根据扩展点的名称进行查找并返回相应的扩展点实例。通过这样的机制,用户可以灵活地扩展Dubbo的功能,同时也可以让Dubbo更加适应不同的业务场景。
自定义扩展点的核心思想就是:“面向接口编程,实现类实现接口,接口与实现类通过扩展点Binder关联。”其中,Binder的定义可以参考以下的代码:
public interface ExtensionFactory {// 返回一个扩展点的代理对象<T> T getExtension(Class<T> type, String name) throws IllegalStateException;
}public interface ExtensionLoader<T> {T getExtension(String name);
}public interface ExtensionBinder<T> {// 绑定void bind(T instance);// 获取绑定的扩展对象T get();
}public interface ExtensionLoaderListener {void onLoad();
}
2. 自定义扩展点机制的使用示例
为了更好地理解Dubbo的自定义扩展点机制,我们可以通过一个简单的示例来演示其使用方法。假设我们有一个接口HelloService,我们想要通过自定义扩展点机制,为这个接口添加一个实现类。
首先,我们需要创建一个实现类HelloServiceImpl,该实现类需要实现HelloService接口。接着,我们需要在resources/META-INF/dubbo目录下创建一个名为com.xxx.HelloService的文件,该文件中需要指定HelloService接口的实现类名称。
helloService=com.xxx.HelloServiceImpl
接下来,我们需要在代码中获取HelloService接口的实例。这可以通过以下方式实现:
ExtensionLoader<HelloService> loader = ExtensionLoader.getExtensionLoader(HelloService.class);
HelloService helloService = loader.getExtension("helloService");
helloService.sayHello();
其中,getExtensionLoader()方法用于获取扩展点的ExtensionLoader实例,getExtension()方法用于
获取具体的扩展实例。在上面的代码中,我们通过“helloService”这个名称获取到了实现了HelloService接口的HelloServiceImpl实例,并调用了其中的sayHello()方法。
通过上述示例,我们可以看出,使用Dubbo的自定义扩展点机制非常简单,只需要在配置文件中指定实现类的名称,然后通过getExtensionLoader()和getExtension()方法获取实例即可。
3. Dubbo的自定义扩展点机制的实现示例
在Dubbo的自定义扩展点机制中,最核心的是ExtensionLoader类和ExtensionFactory类。其中,ExtensionLoader用于加载和管理扩展实例,ExtensionFactory用于创建扩展实例。
下面,我们将通过一个简单的示例,演示Dubbo的自定义扩展点机制的具体实现方式。
首先,我们需要定义一个扩展点接口:
public interface HelloService {
String sayHello(String name);
}
接着,我们需要实现该接口的一个实现类:
@SPI("helloWorld")
public class HelloWorldService implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name;
}
}
在这里,我们使用了@SPI注解来指定该扩展点的默认实现,如果配置文件中没有指定其他实现,则会使用该默认实现。
接下来,我们需要创建一个名为com.xxx.HelloService的文件,该文件中需要指定扩展点接口的实现类名称:
helloWorld=com.xxx.HelloWorldService
最后,我们需要在代码中获取HelloService接口的实例,这可以通过以下代码实现:
ExtensionLoader<HelloService> loader = ExtensionLoader.getExtensionLoader(HelloService.class);
HelloService helloService = loader.getExtension("helloWorld");
System.out.println(helloService.sayHello("Dubbo"));
在上述代码中,我们通过getExtensionLoader()方法获取HelloService接口的ExtensionLoader实例,然后通过getExtension()方法获取名为“helloWorld”的实现类实例,并调用其中的sayHello()方法。
五、Dubbo的过滤器扩展机制
1. Dubbo的过滤器机制概述
Dubbo的过滤器机制允许在调用前、调用后以及抛出异常时执行一些额外的操作。过滤器在调用链路中按顺序执行,可以在过滤器中实现各种功能,例如:日志记录、性能统计、权限控制等。
Dubbo中内置了多个过滤器,包括:ClassLoader过滤器、Context过滤器、Generic过滤器、Echo过滤器、Token过滤器、AccessLog过滤器等。
下面是Dubbo的过滤器机制的时序图:
上图中,服务消费者向服务提供者发送请求时,请求先经过过滤器1,如果过滤器1通过则进一步经过过滤器2,如果过滤器2通过则进一步经过过滤器3,如果过滤器3通过则将请求发送给服务提供者,服务提供者处理请求后将响应返回给服务消费者,响应也会经过相同的过滤器链路。如果任意一个过滤器拒绝请求,则直接返回错误响应。
2. 过滤器扩展机制的使用示例
Dubbo提供了扩展机制,可以在dubbo配置文件中配置过滤器,示例如下:
<dubbo:provider filter="accessLogFilter" />
在上面的例子中,accessLogFilter表示需要使用的过滤器名称,可以在dubbo配置文件中通过dubbo:filter标签进行定义。
3. 自定义过滤器的实现示例
要实现自定义过滤器,需要按照以下步骤进行:
- 定义一个类实现org.apache.dubbo.rpc.Filter接口;
- 实现接口中的方法;
- 在META-INF/dubbo目录下创建一个以org.apache.dubbo.rpc.Filter接口全限定名为名称的文件,并在文件中添加自定义过滤器的类名。
下面是一个自定义的过滤器示例:
package com.example;import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;@Activate(group = "provider")
public class MyFilter implements Filter {@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {// 在这里实现自己的逻辑return invoker.invoke(invocation);}
}
在上面的例子中,我们实现了一个MyFilter过滤器,并使用@Activate注解指定了它是一个provider端的过滤器,然后在invoke()方法中编写自己的逻辑,最后调用invoker.invoke(invocation)方法来执行调用链路中的下一个过滤器或服务。
六、Dubbo的负载均衡扩展机制
1. Dubbo的负载均衡扩展机制概述
负载均衡是分布式系统中的一个重要问题,它可以实现将请求分摊到多个服务提供者上,提高系统的并发能力和可用性。Dubbo的负载均衡扩展机制允许用户自定义负载均衡策略,实现更加灵活、适合特定场景的负载均衡算法。Dubbo内置了多种负载均衡算法,包括随机、轮询、最少活跃调用等。
下面是Dubbo的负载均衡扩展机制的时序图:
2. 负载均衡扩展机制的使用示例
Dubbo的负载均衡扩展机制可以通过在服务提供方和服务消费方的配置文件中指定负载均衡策略来使用。例如,在服务提供方的配置文件中可以添加以下配置:
<dubbo:service interface="com.xxx.XxxService" loadbalance="roundrobin" />
在服务消费方的配置文件中可以添加以下配置:
<dubbo:reference interface="com.xxx.XxxService" loadbalance="random" />
这样就可以实现使用Dubbo内置的轮询
3.自定义负载均衡策略的实现示例
用户可以通过实现Dubbo的LoadBalance接口来自定义负载均衡策略。以下是一个示例:
public class MyLoadBalance implements LoadBalance {@Overridepublic <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {// 自定义负载均衡算法实现return invokers.get(0);}
}
七、Dubbo的容错机制扩展
1. Dubbo的容错机制概述
Dubbo的容错机制是指当Dubbo服务调用出现异常时,Dubbo框架会根据预设的容错机制进行处理,以保证服务的高可用性。Dubbo框架默认提供了多种容错机制,如Failover、Failfast、Failsafe、Failback、Forking等,也支持自定义容错机制。
Dubbo的容错机制通常是通过在客户端代理层实现的,当远程服务调用出现异常时,客户端代理会根据预设的容错机制进行重试或处理,以保证服务的高可用性。
在Dubbo的容错机制中,ClusterInvoker负责调用远程服务,并进行容错处理。当调用远程服务发生异常时,Dubbo会按照以下顺序进行容错处理:
- ClusterInvoker处理异常;
- 如果ClusterInvoker处理异常失败,则交由Router处理异常;
- 如果Router处理异常失败,则交由LoadBalance处理异常;
- 如果LoadBalance处理异常失败,则抛出异常给InvokerInvocationHandler,最终抛出给Consumer。同时,Dubbo还会将异常信息进行监控,并更新调用统计信息。
2. 容错机制扩展的使用示例
Dubbo默认的容错机制是Failover,即自动切换重试其他节点,达到容错和负载均衡的效果。如果需要使用其他容错机制,可以通过在服务提供方和服务消费方的配置文件中进行配置。例如,我们可以通过以下方式配置使用Failfast容错机制:
在服务提供方的配置文件中增加如下配置:
<dubbo:service interface="com.example.service.SomeService" retries="0"/>
在服务消费方的配置文件中增加如下配置:
<dubbo:reference interface="com.example.service.SomeService" check="false" cluster="failfast"/>
这样,在服务调用出现异常时,Dubbo框架会自动使用Failfast容错机制进行处理,即只进行一次调用,若调用失败则立即抛出异常,不进行重试。
3. 自定义容错策略的实现示例
如果需要实现自定义的容错策略,可以通过继承org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker类,并实现org.apache.dubbo.rpc.Invoker接口,来自定义容错策略的实现。
例如,我们可以通过以下代码实现一个自定义的容错策略:
public class MyClusterInvoker<T> extends AbstractClusterInvoker<T> {public MyClusterInvoker(Directory<T> directory) {super(directory);}@Overrideprotected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {// 自定义容错逻辑...}
}
在实现自定义容错策略后,需要在服务提供方和服务消费方的配置文件中进行配置。例如,在服务提供方的配置文件中增加如下配置:
<dubbo:service interface="com.example.service.SomeService" cluster="myClusterInvoker"/>
在服务消费方的配置文件中增加如下配置:
<dubbo:reference interface="com.example.service.SomeService" check="false" cluster="myClusterInvoker"/>
这样,在服务调用时,Dubbo框架会使用我们自定义的MyClusterInvoker容错策略进行处理。
八、Dubbo的扩展机制实践
1. 实现一个使用自定义扩展点、过滤器、负载均衡器和容错机制的 Dubbo 服务
在这个实践中,我们将实现一个使用自定义扩展点、过滤器、负载均衡器和容错机制的 Dubbo 服务。
首先,我们需要定义一个服务接口。例如,我们可以定义一个名为 SomeService 的服务接口,如下所示:
public interface SomeService {String sayHello(String name);
}
然后,我们需要实现该服务接口。例如,我们可以实现一个名为 SomeServiceImpl 的服务实现类,如下所示:
public class SomeServiceImpl implements SomeService {@Overridepublic String sayHello(String name) {return "Hello, " + name + "!";}
}
接下来,我们需要配置 Dubbo 的扩展点、过滤器、负载均衡器和容错机制。例如,我们可以在服务提供方和服务消费方的配置文件中进行如下配置:
<!-- 扩展点配置 -->
<dubbo:protocol name="dubbo" extension="com.example.extension.MyProtocol"/><!-- 过滤器配置 -->
<dubbo:provider filter="com.example.filter.MyProviderFilter"/>
<dubbo:consumer filter="com.example.filter.MyConsumerFilter"/><!-- 负载均衡器配置 -->
<dubbo:reference interface="com.example.service.SomeService" loadbalance="com.example.loadbalance.MyLoadBalance"/><!-- 容错机制配置 -->
<dubbo:service interface="com.example.service.SomeService" cluster="com.example.cluster.MyCluster"/>
<dubbo:reference interface="com.example.service.SomeService" cluster="com.example.cluster.MyCluster"/>
其中,com.example.extension.MyProtocol 是一个自定义的 Dubbo 协议扩展点实现类,com.example.filter.MyProviderFilter 和 com.example.filter.MyConsumerFilter 是自定义的 Dubbo 过滤器实现类,com.example.loadbalance.MyLoadBalance 是一个自定义的 Dubbo 负载均衡器实现类,com.example.cluster.MyCluster 是一个自定义的 Dubbo 容错机制实现类。
最后,我们可以使用 Dubbo 的 API 在客户端调用该服务。例如,我们可以使用如下代码在客户端调用该服务:
// 获取 Dubbo 服务引用
SomeService someService = DubboReferenceBuilder.newBuilder().setInterface(SomeService.class).setUrl("dubbo://localhost:20880").build();// 调用 Dubbo 服务
String result = someService.sayHello("Dubbo");
System.out.println(result);
这样,我们就实现了一个使用自定义扩展点、过滤器、负载均衡器和容错机制的 Dubbo 服务。
上一篇:Dubbo高手之路1,Dubbo原理和机制,Dubbo的核心组件
🏆本文收录于,Java进阶教程系列。
全网最细Java零基础手把手入门教程,系列课程包括:基础篇、集合篇、Java8新特性、多线程、代码实战,持续更新中(每周1-2篇),适合零基础和进阶提升的同学。
🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师。
相关文章:

Dubbo高手之路2,6种扩展机制详解
目录 一、Dubbo扩展机制的概述二、Dubbo的自适应扩展机制1. 什么是自适应扩展机制2. 自适应扩展机制的使用示例 三、Dubbo的SPI扩展机制1. 什么是SPI扩展机制2. SPI扩展机制的使用示例3. Dubbo的SPI扩展机制中自定义扩展点的实现示例 四、Dubbo的自定义扩展点机制1. 什么是自定…...

C语言快速回顾(二)
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。C/C是音视频必…...

ADB连接安卓手机提示unauthorized
近期使用airtest进行自动化测试时,因为需要连接手机和电脑端,所以在使用adb去连接本人的安卓手机vivo z5时,发现一直提示unauthorized。后来经过一系列方法尝试,最终得以解决。 问题描述: 用数据线将手机接入电脑端&…...
【软件工程】内聚
概念 是指一个模块内部个成分之间相互关联程度的度量。也就是说,凝聚是对模块内各处理动作组合强度的一种度量。很显然,一个模块的内聚越大越好。 偶然凝聚 一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一起。这种模块也称为…...

支持对接鸿蒙系统的无线模块及其常见应用介绍
近距离的无线通信得益于万物互联网的快速发展,基于集成部近距离无线连接,为固定和移动设备建立通信的蓝牙技术也已经广泛应用于汽车领域、工业生产及医疗领域。为协助物联网企业终端产品能快速接入鸿蒙生态系统,SKYLAB联手国产芯片厂家研发推…...

java项目打包运行报异常:Demo-1.0-SNAPSHOT.jar中没有主清单属性
检查后发现pom文件中有错误,需要添加build内容才能恢复正常。 添加下面文件后再次启动恢复正常。 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactI…...
nginx+keepalived实现负载均衡和高可用
环境准备 IPVIP环境客户端192.168.134.174Master192.168.134.170192.168.134.100需要配置nginx负载均衡Backup192.168.134.172192.168.134.100需要配置nginx负载均衡web1服务器192.168.134.171 web2服务器 192.168.134.173 1、首先安装nginx服务器(此处采用yum安装…...
微信小程序实现图片多点裁剪
话不多说,直接上代码 1、页面布局 <view class"buttons" style"height: 50px;"><view class"upload btn" style"background-color: #d18118;"bindtap"uploadImage"> 上传图片 </view><vie…...
计算图片的均值和方差用图片的归一化取值
计算图片的均值和方差用图片的归一化取值 注意:使用这种方法的前提是进行了数据批量化操作,需要使用神经网络库,torch,DataLoader def getStat(data):print(len(data))loader torch.utils.data.DataLoader(data, batch_size1, …...

预测算法|改进粒子群算法优化极限学习机IDM-PSO-ELM
回归拟合: 分类 本文是作者的预测算法系列的第四篇,前面的文章中介绍了BP、SVM、RF及其优化,感兴趣的读者可以在作者往期文章中了解,这一篇将介绍——极限学习机 过去的几十年里基于梯度的学习方法被广泛用于训练神经网络&am…...

小黑子—JavaWeb:第六章 - Filter、Listener、AJAX与JSON
JavaWeb入门6.0 1. Filter1.1 Filter快速入门1.2 Filter执行流程1.3 Filter拦截路径配置1.4 Filter过滤器链1.5 案例登录验证 2. Listener2.1 ServletContextListener使用 3. AJAX3.1 AJAX 快速入门3.2 案例 验证用户名是否存在3.3 Axios 异步框架3.3.1 Axios 快速入门3.3.2 Ax…...

STM32 LL库开发
一、STM32开发方式 标准库开发:Standard Peripheral Libraries,STDHAL库开发:Hardware Abstraction Layer,硬件抽象层LL库开发:Low-layer,底层库 二、HAL库与LL库开发对比 ST在推行HAL库的时候,…...

标记垃圾,有三种色彩:四千长文带你深入了解三色标记算法
🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏&…...
277/300 React+react-router-dom+Vite 二级页面刷新时,白屏问题解决
(一)方案 BrowserRouter 换为 HashRouter (二)代码 import routes from ./routes import {ReactElement, Suspense} from react import {createHashRouter, Navigate} from react-router-dom // 生成路由数据 const generateR…...
如何做线上监控
1、背景 软件的质量是需要全生命周期进行关注的,在生产环境下QA的活动就是测试右移,测试右移最关键的手段就是线上监控,也是至关重要的一个环节,可以通过技术的手段,提前感知到线上问题和风险,先于用户提前发现问题,提升服务可感知性,从而降低客户投诉。 2、通用原则…...
饥荒开服教程——游戏
饥荒开服教程——游戏 1. 开服环境2. 开服步骤2.1 创建集群2.2 安装服务端2.3 上传mod2.4 启动脚本2.5 上传地图2.6 设置访问令牌2.7 修改配置 3. 服务器命令3.1 关闭服务器3.2 回档 记录一些在饥荒联机版开服中遇到过的问题。 参考:3分钟创建你的饥荒联机专属服务…...
查询 npm/yarn 安装依赖的全局路径及路径修改
一、NPM 1.查询 npm 安装依赖的全局路径 npm prefix -g 2. 修改 npm 全局安装位置 npm config set prefix "D:\nodejs\node_modules\npm\node_modules" 3. 修改 npm 全局 cache 位置 npm config set cache "D:\nodejs\node_modules\npm\cache" 4. np…...

掌握Python的X篇_35_用Python为美女打码_图像库Pillow
本篇将会介绍python中的一个图像库Pillow。 文章目录 1. Pillow与PIL的关系2. 调整大小3. 加滤镜4. 剪裁5. 生成验证码 1. Pillow与PIL的关系 我们在网上搜python的图像库的话,可能搜到的时PIL。实际上之前python发展的时候就是PIL,这个库比较好用&…...

SpringBoot 异步、邮件任务
异步任务 创建一个Hello项目 创建一个类AsyncService 异步处理还是非常常用的,比如我们在网站上发送邮件,后台会去发送邮件,此时前台会造成响应不动,直到邮件发送完毕,响应才会成功,所以我们一般会采用多线…...

【LeetCode】45. 跳跃游戏 II - 贪婪算法
目录标题 2023-8-11 09:49:25 45. 跳跃游戏 II 2023-8-11 09:49:25 自己没做出来,废物Orz class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0;int steps 0;for (int i 0; i < length - 1; i) {maxPosit…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...