springboot 集成dubbo

news2024/11/25 7:14:08

上一篇我们一起认识了Dubbo与RPC,今天我们就来一起学习如何使用Dubbo,并将Dubbo集成到Spring Boot的项目中。我们来看下今天要使用到的软件及版本:

软件

版本

说明

Java

11

Spring Boot

2.7.13

Spring Boot 3.0版本开始,最低支持到Java 17

Dubbo

3.2.2

Zookeeper

3.8.1

作为Dubbo的注册中心

注册中心的选择没有什么强制要求,我们这里以Zookeeper为例来做示范。

TIps:今天我们只处理Spring Boot,Dubbo与Zookeeper的集成,不会涉及到其他框架的集成。

部署Zookeeper

我们先来部署一个Zookeeper,这里我提供Windows和Linux的部署教程,如果你已经部署成功,可以跳过这部分内容。

首先是下载Zookeeper,这里我们选择Zookeeper-3.8.1版本。

Linux下可以使用wget命令下载:

wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.1/apache-zookeeper-3.8.1-bin.tar.gz

Tips:注意,这里我们下载的是apache-zookeeper-3.8.1-bin.tar.gz这个文件。

Linux部署Zookeeper

解压Zookeeper:

tar -zxvf apache-zookeeper-3.8.1-bin.tar.gz

Zookeeper的配置文件,配置文件位于../Zookeeper/conf目录下,复制zoo_sample.cfg文件,并命名为zoo.cfg:

cp zoo_sample.cfg zoo.cfg

在Dubbo的学习中,我们使用Zookeeper的默认配置即可,所以此处我们不需要再修改zoo.cfg。

修改profile文件:

vim /etc/profile

将Zookeeper的配置添加到profile文件中:

export ZOOKEEPER_HOME=/opt/opt/apache-zookeeper-3.8.1-bin
export PATH=$ZOOKEEPER_HOME/bin:$PATH
export PATH

刷新profile文件:

source profile

启动Zookeeper:

zkServer.sh start

正常情况下会输出日志:

ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

可以使用命令来查看Zookeeper的状态:

zkServer.sh status

单机状态输出如下日志:

ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone

到这里我们就在Linux服务器上成功的部署了一个简单可用的单机版Zookeeper了。

Windows部署Zookeeper

参照Linux上部署Zookeeper的步骤来到修改配置文件的部分,Windows上我们要修改dataDir的路径,并新增dataLogDir的路径:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=D:\Apache\Apache Zookeeper 3.8.1\data
dataLogDir=D:\Apache\Apache Zookeeper 3.8.1\logs
clientPort=2181

如果系统中没有配置环境变量JAVA_HOME,我们要修改zkEnv.cmd中的JAVA_HOME配置,该文件位于../Apache Zookeeper/bin目录下:

@echo off
REM Licensed to the Apache Software Foundation (ASF) under one or more
REM contributor license agreements.  See the NOTICE file distributed with
REM this work for additional information regarding copyright ownership.
REM The ASF licenses this file to You under the Apache License, Version 2.0
REM (the "License"); you may not use this file except in compliance with
REM the License.  You may obtain a copy of the License at
REM
REM     http://www.apache.org/licenses/LICENSE-2.0
REM
REM Unless required by applicable law or agreed to in writing, software
REM distributed under the License is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM See the License for the specific language governing permissions and
REM limitations under the License.

set ZOOCFGDIR=%~dp0%..\conf
set ZOO_LOG_DIR=%~dp0%..\logs

REM for sanity sake assume Java 1.6
REM see: http://java.sun.com/javase/6/docs/technotes/tools/windows/java.html

REM add the zoocfg dir to classpath
set CLASSPATH=%ZOOCFGDIR%

REM make it work in the release
SET CLASSPATH=%~dp0..\*;%~dp0..\lib\*;%CLASSPATH%

REM make it work for developers
SET CLASSPATH=%~dp0..\build\classes;%~dp0..\build\lib\*;%CLASSPATH%

set ZOOCFG=%ZOOCFGDIR%\zoo.cfg

@REM setup java environment variables

if not defined JAVA_HOME (
echo Error: JAVA_HOME is not set.
goto :eof
)

set JAVA_HOME=%JAVA_HOME%

if not exist "%JAVA_HOME%"\bin\java.exe (
echo Error: JAVA_HOME is incorrectly set: %JAVA_HOME%
echo Expected to find java.exe here: %JAVA_HOME%\bin\java.exe
goto :eof
)

REM strip off trailing \ from JAVA_HOME or java does not start
if "%JAVA_HOME:~-1%" EQU "\" set "JAVA_HOME=%JAVA_HOME:~0,-1%"

set JAVA="%JAVA_HOME%"\bin\java

我们将第41行的set JAVA_HOME=%JAVA_HOME%提前到第36行前,在在判断环境变量中是否存在JAVA_HOME前进行设置,并使用完整的路径,如:set JAVA_HOME=D:\Java\jdk11.0.18

上述内容修改完成后直接双击执行zkServer.cmd就可以启动Zookeeper了。注意,Windows下启动可能出现各种各样的错误,最常见的如启动闪退,这时可以在PowerShell中启动zkServer.cmd,来查看日志解决问题:

cd D:
PS D:\> cd '.\Apache\Apache Zookeeper 3.8.1\bin\'
PS D:\Apache\Apache Zookeeper 3.8.1\bin> .\zkServer.cmd

好了,到这里你应该已经完成了Zookeeper的部署工作了,接下来我们在Spring Boot应用中集成Dubbo。

Dubbo的XML形式集成

首先我们准备两个工程,DubboProviderXML和DubboConsumerXML,模仿服务提供方和服务使用方,创建工程的部分我们就直接跳过了,相信这一步大家都没问题。

另外Dubbo官方提供了Dubbo Initializer项目脚手架,方便大家快速构建Dubbo项目:

使用方式类似于Spring Initializr:

Tips

  • 当然你也可以在同一个工程中模拟提供方和使用方;
  • Spring Initializr严格意义上是一个错别字,但大家也都接受了这种方式,V2EX上有关于名字的讨论。

DubboProviderXML工程

在DubboProviderXML项目下创建了两个子工程:

  • provider-api,声明RPC接口
  • provider-service,核心业务逻辑的实现

此时工程结构如下:

现在修改DubboProviderXML工程的POM文件:

<modelVersion>4.0.0</modelVersion>
<groupId>com.wyz</groupId>
<artifactId>DubboProviderXML</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>DubboProviderXML</name>
<description>DubboProviderXML</description>

<properties>
  <maven.compiler.source>11</maven.compiler.source>
  <maven.compiler.target>11</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<modules>
  <module>provider-api</module>
  <module>provider-service</module>
</modules>

通常我会在DubboProviderXML工程中添加所有子项目都会用到的依赖,例如:lombok,commons-lang3等,在此我们忽略这部分内容。

配置provider-api

接着处理子工程provider-api中的POM文件:

<modelVersion>4.0.0</modelVersion>
<parent>
  <groupId>com.wyz</groupId>
  <artifactId>DubboProviderXML</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>provider-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider-api</name>
<packaging>jar</packaging>
<description>provider-api</description>

然后在provider-api中声明RPC接口:

package com.wyz.api;

/**
* @author wyz
* @version 1.0
* @date 2023/6/28
*/
public interface DubboDemoXMLService {
	String say(String message);
}

这样provider-api就配置完成了,DubboProviderXML就有了对外提供RPC服务的入口。

Tips:需要将provider-api打包成jar,以便DubboConsumerXML使用。

配置provider-service

下面我们配置子工程provider-service的POM文件:

<modelVersion>4.0.0</modelVersion>
<parent>
  <groupId>com.wyz</groupId>
  <artifactId>DubboProviderXML</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>provider-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider-service</name>
<description>provider-service</description>

<properties>
  <spring.boot.version>2.7.13</spring.boot.version>
  <dubbo.version>3.2.2</dubbo.version>
  <zookeeper.version>3.8.1</zookeeper.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>${spring.boot.version}</version>
  </dependency>

  <!-- dubbo-spring-boot-starter引入了dubbo -->
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>${dubbo.version}</version>
  </dependency>

  <!-- DUbbo与Zookeeper的连接器 -->
  <!-- curator5自身引入了Zookeeper的依赖,因此无需额外引入 -->
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
    <version>${dubbo.version}</version>
    <type>pom</type>
  </dependency>

  <dependency>
    <groupId>com.wyz</groupId>
    <artifactId>provider-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </dependency>
</dependencies>

接下来我们在provider-service中实现这个接口:

package com.wyz.service.impl;

import com.wyz.DubboDemoXMLService;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
public class DubboDemoXMLServiceImpl implements DubboDemoXMLService {

	@Override
	public String say(String message) {
		return "XML Provider say : " + message;
	}
}

现在,我们有了接口,也有了接口的实现,只需要配置成Dubbo的服务即可,新增dubbo-provider.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://dubbo.apache.org/schema/dubbo
  http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

  <!-- Dubbo的基本配置-->
  <dubbo:application name="DubboProviderXML" qos-port="2222"/>
  <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
  <dubbo:protocol name="dubbo"/>

  <!-- 配置提供的服务dubboDemoXMLServiceImpl -->
  <bean id="dubboDemoXMLServiceImpl" class="com.wyz.service.impl.DubboDemoXMLServiceImpl"/>
  <dubbo:service interface="com.wyz.api.DubboDemoXMLService" ref="dubboDemoXMLServiceImpl"/>
</beans>

所有配置完成后,我们导入dubbo-provider.xml文件:

package com.wyz.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@SpringBootApplication
@ImportResource(locations = "classpath:dubbo-provider.xml")
public class ProviderServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(ProviderServiceApplication.class, args);
	}
}

到这里我们的DubboProviderXML工程就配置完了,此时工程的结构如下:

DubboConsumerXML工程

我们继续配置服务使用方DubboConsumerXML工程,整体流程和DubboProviderXML的配置基本一致,我们直接快进到consumer-service中的配置部分。

配置consumer-service

consumer-service的POM文件与DubboProviderXML工程的子工程provider-service完全一致,我们也直接跳过这部分内容。

接下来实现对DubboDemoXMLService#say的调用:

package com.wyz.service.impl;

import com.wyz.DubboDemoXMLService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@Component
public class DubboConsumerXMLService implements CommandLineRunner {

	@Autowired
	DubboDemoXMLService dubboDemoXMLServiceImpl;

	@Override
	public void run(String... args) {
		String message = dubboDemoXMLServiceImpl.say("wyz");
		System.out.println(message);
	}
}

接着我们新增dubbo-consumer.xml文件,配置使用方要调用的服务:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://dubbo.apache.org/schema/dubbo
  http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

  <!-- Dubbo的基本配置-->
  <dubbo:application name="DubboConsumerXML" qos-port="2223"/>
  <dubbo:registry address="zookeeper://106.75.33.232:2181"/>
  <dubbo:protocol name="dubbo"/>

  <!-- 配置需要调用的服务 -->
  <dubbo:reference id="DubboDemoXMLService" interface="com.wyz.api.DubboDemoXMLService"/>
</beans>

同样的,我们导入dubbo-consumer.xml文件:

package com.wyz.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@SpringBootApplication
@ImportResource(locations = "classpath:dubbo-consumer.xml")
public class ConsumerServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerServiceApplication.class, args);
	}
}

最后,我们启动程序,控制台应该输出如下日志:

此时DubboConsumerXML的工程结构如下:

Dubbo的注解形式集成

除了使用XML外,我们还可以使用注解的方式配置Dubbo(毕竟有很多人不喜欢XML)。同样的我们需要先创建两个工程DubboProviderAnnotation和DubboConsumerAnnotation。

DubboProviderAnnotation工程

DubboProviderAnnotation工程与DubboProviderXML的配置步骤基本一致,我们快进到接口的实现部分,这次我们需要使用@DubboService注解声明这是一个Dubbo服务:

package com.wyz.service.impl;

import com.wyz.api.DubboProviderAnnotationService;
import org.apache.dubbo.config.annotation.DubboService;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@DubboService
public class DubboProviderAnnotationServiceImpl implements DubboProviderAnnotationService {

	@Override
	public String say(String message) {
		return "DubboProviderAnnotationService say : " + message;
	}
}

接口有了,实现也有了,我们来配置Dubbo的相关内容,这次我们使用YAML配置:

dubbo:
  application:
    name: DubboProviderAnnotation
    qos-port: 2222
  protocol:
    name: dubbo
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

接着,我们在启动类上添加@EnableDubbo注解,开启Dubbo的自动注入:

package com.wyz.service;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@SpringBootApplication
@EnableDubbo
public class ProviderServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(ProviderServiceApplication.class, args);
	}
}

此时DubboProviderAnnotation的结构如下:

最后我们就可以正常启动DubboProviderAnnotation项目了。

DubboConsumerAnnotation工程

有了前面的基础,相信你一定可以想到DubboConsumerAnnotation该如何配置,我们先来写调用DubboDemoAnnotationService#say的调用逻辑,此时通过@DubboReference注入接口:

package com.wyz.service.impl;

import com.wyz.api.DubboProviderAnnotationService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@Component
public class DubboConsumerAnnotationService implements CommandLineRunner {

	@DubboReference
	DubboProviderAnnotationService dubboProviderAnnotationService;

	@Override
	public void run(String... args) {
		String message = dubboProviderAnnotationService.say("wyz");
		System.out.println(message);
	}
}

接着来配置YAML文件:

dubbo:
  application:
    name: DubboConsumerAnnotation
    qos-port: 2223
  protocol:
    name: dubbo
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

同样的,我们需要在服务使用方添加@EnableDubbo注解,开启Dubbo的自动注入:

package com.wyz.service;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @author wyz
* @version 1.0
* @date 2023/7/3
*/
@SpringBootApplication
@EnableDubbo
public class ConsumerServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConsumerServiceApplication.class, args);
	}
}

此时DubboConsumerAnnotation的结构如下:

最后我们就可以正常启动DubboConsumerAnnotation项目了。

结语

到这里我们就完成了两种形式在Spring Boot中集成Dubbo 3.X。通常来说我会选择使用XML的形式来配置Dubbo提供的服务,但会选择将Dubbo的基本信息,如:协议类型,注册中心地址等配置到YAML文件中,这是为了统一管理对外提供的服务和使用的服务,可以一目了然的看到项目提供了哪些能力,和依赖了哪些外部接口。


如果本文对你有帮助的话,还请多多点赞支持。如果文章中出现任何错误,还请批评指正。最后欢迎大家关注分享硬核Java技术的金融摸鱼侠王有志,我们下次再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

揭榜!年度智能汽车「软件/座舱/车联」TOP10供应商奖项官宣

过去几年&#xff0c;在特斯拉及新势力的带动下&#xff0c;车企的盈利模式正在寻求从“一次售卖”转变为“硬件预埋&#xff0b;软件付费解锁”&#xff0c;背后是驱动汽车软件架构的迭代&#xff0c;即从面向信号的软件架构&#xff0c;过渡至面向服务的SOA架构。 同时&…

uni-app 之 目录结构

目录结构&#xff1a; 工程简介 | uni-app官网 (dcloud.net.cn) pages/index/index.vue 页面元素等 static 静态文件&#xff0c;图片 字体文件等 App.vue 应用配置&#xff0c;用来配置App全局样式以及监听 应用生命周期 index.html 项目运行最终生成的文件 main.js 引用的…

JVM之程序计数器和栈

Java虚拟机&#xff08;JVM&#xff09;是运行Java程序的关键组件&#xff0c;它负责将Java源代码转换为可执行的字节码&#xff0c;并在运行时管理内存、执行程序等。在JVM的内部&#xff0c;有许多重要的组成部分&#xff0c;如下图&#xff1a; 1. JVM程序计数器 程序计数器…

电脑硬盘数据恢复一般需要收费多少钱

随着电子信息时代的发展&#xff0c;个人和企业对电脑硬盘中存储的数据越发重视。然而&#xff0c;由于各种原因&#xff0c;硬盘数据丢失的情况屡见不鲜。如果您正陷入这样的困境&#xff0c;您可能会好奇恢复失去的数据需要花费多少钱。本文将为您介绍电脑硬盘数据恢复的一般…

Unity ShaderGraph教程——进阶shader(水面、积雪)

1.水面&#xff08;一&#xff09; 公式&#xff1a;场景深度 节点深度 — 屏幕空间位置的W向量 半透明物体与不透明物体的相交边缘 原理&#xff1a;场景深度 节点深度包含透明像素&#xff0c;屏幕空间w向量不包含透明像素。 注意&#xff1a;需要在UniversalRP-xxxQuali…

Linux常用命令——cu命令

在线Linux命令查询工具 cu 用于连接另一个系统主机。 补充说明 cu命令用于连接另一个系统主机。cu(call up)指令可连接另一台主机&#xff0c;并采用类似拨号终端机的接口工作&#xff0c;也可执行简易的文件传输作业。 语法 cu [dehnotv][-a<通信端口>][-c<电话…

vue页面添加水印(可用于H5,APP)

vue页面添加水印 背景实现新建vue组件使用效果 尾巴 背景 最近实现了一个小功能&#xff0c;就是给页面添加背景水印。实现思路就是定义一个宽高充满屏幕的组件&#xff0c;然后使用绝对定位并通过层级控制让水印显示在页面的最前端。 实现 代码相对简单&#xff0c;相信有点…

如何熟练使用vector?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

ue5 物理场的应用

cable mat wpo particle 流体粒子 choas 破损 刚体 布料 cloud abp blueprint riggedbody 体积雾 毛发 全局的 局部的 非均匀的 连续变化的 也可以多个叠加 从全局 到 范围

软件安全检测相关政策法规及安全测试的作用

安全测试 一、软件安全检测相关政策法规&#xff1a; 《网络安全法》 《网络产品和服务安全审查办法&#xff08;试行&#xff09;》 《政府信息系统安全检查办法》&#xff08; 国办发〔2009〕28 号&#xff09; 《国务院办公厅关于开展重点领域网络与信息安全检查行动的…

ssm+vue亿互游在线平台源码和论文

ssmvue亿互游在线平台源码和论文118 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 随着旅游业的迅速发展&#xff0c;传统的旅游资讯查询方式&#xff0c;已经无法满足用户需求&#xff0c;因此&#x…

2023开学礼山东财经大学《乡村振兴战略下传统村落文化旅游设计》许少辉新财经图书馆

2023开学礼山东财经大学《乡村振兴战略下传统村落文化旅游设计》许少辉新财经图书馆

SQL sever中用户管理

目录 一、用户管理常见方法 二、用户管理方法示例 2.1. 创建登录账户&#xff1a; 2.1.1 检查是否创建账户成功&#xff1a; 2.2. 创建数据库用户&#xff1a; 2.2.1检查用户是否创建成功&#xff1a; 2.3. 授予权限&#xff1a; 2.3.1授予 SELECT、INSERT 和 U…

nacos 配置中心配置优先级

默认配置文件&#xff1a; 这的默认配置名为&#xff1a;com.tulingmall.order 名称的properties文件 如果不是properties需修改下图配置 默认配置文件只需名称对应 类型就算不为properties也无需加后缀名称 后面级别更低的为配置文件引入的多文件配置

机器人中的数值优化(八)——拟牛顿方法(上)

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

1.14 手工插入ShellCode反弹

PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如文件加密与解密,病毒分析,外挂技术等&#xff0c;本次的目标是手工修改或增加节…

【单片机】有人 WH-LTE-7S1 4G cat1 模块连接服务器,教程,记录。GPRS模块连接服务器教程。socket编程。

文章目录 4G cat1 模块封装引脚名称功能拓扑图串口模块调试WH-LTE-7S1公网服务器建立python程序服务服务器程序WH-LTE-7S1 模块连接服务器与多个模块建立TCP长连接的服务器程序 本文主要介绍了一个4G Cat1模块&#xff0c;该模块具有多种功能和特性。文章接下来展示了4G Cat1模…

手把手教你Typora大纲如何显示序号(支持六级标题栏序号)

1 打开偏好设置 2 新建 base.user.css文件 3 复制代码&#xff08;重启typora生效&#xff09;&#xff1a; /************************************** * Header Counters in TOC **************************************//* No link underlines in TOC */ .md-toc-inner { …

第四章:照相机模型与增强实现

文章目录 第四章&#xff1a;照相机模型与增强实现4.1 针孔照相机模型4.1.1 照相机矩阵4.1.2 三维点的投影4.1.3 照相机矩阵的分解4.1.4 计算照相机中心 4.2 照相机标定4.3 以平面和标记物进行姿态估计4.4 增强现实4.4.1 PyGame 和 PyOpenGL4.4.2 从照相机矩阵到 Open…

PMD 检查java代码:运行过程中只需要赋值一次的局部变量可以用final修饰(LocalVariableCouldBeFinal)

https://docs.pmd-code.org/pmd-doc-6.55.0/pmd_rules_java_codestyle.html#localvariablecouldbefinal 如果一个局部变量在运行过程中只需要赋值一次&#xff0c;那么可以定义为final的。 属性ignoreForEachDecl可以控制是否忽略对for-each声明中的局部变量的检查&#xff0c…