当前位置: 首页 > article >正文

【SpringCloud】Eureka的使用

3. Eureka

3.1 Eureka 介绍

Eureka主要分为两个部分:

EurekaServer:

作为注册中心Server端,向微服务应用程序提供服务注册,发现,健康检查等能力。

EurekaClient:

服务提供者,服务启动时,会向 EurekaServer 注册自己的信息 (IP,端口,服务信息
等),Eureka Server 会存储这些信息。

3.2 搭建 Eureka 服务

Eureka 是一个单独的服务,所以咱们要手动搭建出 Eureka 服务器。

这里使用父子项目来搭建 Eureka 服务,先创建一个 spring-cloud-demo 的父项目:

在这里插入图片描述

后续所有的项目创建都在这个父项目中创建子项目。

在这里插入图片描述

直接复制下面 spring-cloud-demo 的 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version><spring-cloud.version>2022.0.3</spring-cloud.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>${mybatis.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement>
</project>

pom.xml 关键部分解析:

  1. <modules>
    定义子模块(当前为空),用于多模块项目管理。所有子模块需在此声明,Maven 会按顺序构建。
  2. <parent>
    继承 Spring Boot 的默认配置(如插件、依赖管理),版本为 3.1.6,简化项目配置。
  3. <properties>
    统一定义变量,便于维护版本:
    • Java 版本:17
    • Spring Cloud:2022.0.3
  4. <dependencies>
    当前仅引入 Lombok(代码简化工具),<optional>true</optional> 表示不传递依赖给子模块。
  5. <dependencyManagement>
    统一管理依赖版本,子模块引用时无需指定版本:
    • 引入 Spring Cloud 全家桶的版本控制
    • 锁定 MyBatis 和 MySQL 驱动版本
    • 测试用 MyBatis 依赖(仅测试范围生效)

记得删除掉父工程的 src 目录,因为后续不会在父工程中写代码。

有了上述操作,咱们的父工程就创建好了,接下来开始创建子工程。

下面开始在父工程底下创建一个子模块,也就是用这个子模块去搭建 Eureka 服务:

在这里插入图片描述

创建子模块项目名为 eureka-server:
在这里插入图片描述

此时点击 Create 后,就会发现 spring-cloud-demo 目录下出现了 eureka-server 子项目,同时在父项目的 pom.xml 中的 modules 里出现了咱们子模块的名字

在这里插入图片描述

在子项目 eureka-server 的 pom.xml <dependencies> </dependencies> 中引入 eureka-server 依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

在子项目 eureka-server 的 pom.xml <project> </project> 加入项目构件插件

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

记得点击右上角 maven 的刷新,或者打开 maven 面板点击 Reload ALL Maven Project 按钮重新加载下依赖。

由于创建的子项目是一个空的项目,所以需要手动创建好对应的包和子模块的启动类:

EurekaServerApplication.class 代码如下:

package com.zlcode.eureka;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

编写配置文件,这里需要手动在 resoureces 中创建该项目的配置文件 papplication.yml

# Eureka相关配置
# Eureka 服务
server:port: 10010
spring:application:name: eureka-server
eureka:instance:hostname: localhostclient:# 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,# 不需要同步其他的Eureka Server节点的数据,这里设置为falsefetch-registry: false# 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.register-with-eureka: falseservice-url:# 设置Eureka Server的地址,查询服务和注册服务都需要依赖这个地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

有了上述的操作,就能执行 eureka-server 项目中的 main 方法了。

在浏览器中输入 http://127.0.0.01:10010 就能发现此时 eureka-server 已经成功启动了。

在这里插入图片描述

3.3 创建cook服务和waiter服务

接下来再来创建两个子项目,分别是 厨师(cook) 和 服务员(waiter),厨师需要让服务员上菜。

创建厨师服务和服务员服务跟创建 Eureka 项目一致,创建的流程这里就省略了,也就是在 spring-cloud-demo 目录下创建厨师子模块和服务员子模块。

### 3.3.1 cook-service 模块配置代码

cook-service 的 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cook-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

cook-service 的 application.yml 文件如下:

server:port: 8080
spring:application:name: cook-service # 添加服务器名称
#Eureka Client
eureka:client:service-url:# eureka 地址defaultZone: http://127.0.0.1:10010/eureka/

cook-service 的 启动类 文件如下:

package com.zlcode.cook;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class CookServiceApplication {public static void main(String[] args) {SpringApplication.run(CookServiceApplication.class, args);}
}

3.3.2 waiter-service 模块配置代码

waiter-service 的 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>waiter-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

waiter-service 的 application.yml 文件如下:

server:port: 9090
spring:application:name: waiter-service # 添加服务器名称
#Eureka Client
eureka:client:service-url:# eureka 地址defaultZone: http://127.0.0.1:10010/eureka/

waiter-service 的 启动类 文件如下:

package com.zlcode.waiter;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WaiterServiceApplication {public static void main(String[] args) {SpringApplication.run(WaiterServiceApplication.class, args);}
}

3.3.3 cook 实体类

将 CookInfo 创建在 cookie-service/*/cook/model/目录下:

package com.zlcode.cook.model;import lombok.Data;@Data
public class CookInfo {private Integer cookId;private String cookieName;
}

3.3.4 waiter 实体类

将 WaiterInfo 创建在 waiter-service/*/waiter/model/目录下:

package com.zlcode.waiter.model;import lombok.Data;@Data
public class WaiterInfo {private Integer waiterId;private String waiterName;
}

3.4 服务注册

启动咱们的 waiter-service 和 cook-service 项目,就能自动的进行 eureka 的服务注册了,因为咱们在 .yml 已经配置好了 eureka 的地址。
在这里插入图片描述

启动 waiter 和 cook 后,刷新 http://127.0.0.1:10010 就能发现:

在这里插入图片描述

通过上面可以看到,已经把 cook-service 和 waiter-service 注册到咱们部搭建的 eureka-server 服务中了。

上述这样的操作,咱们就称作为服务注册。

由于 cook-service 想通过 eureka-server 去发现 waiter-service 所以,也要让 cook-service 自己在 eureka 中注册,这样一来 cook-service 就可以从 eureka-server 中去发现 waiter-service 服务。

3.5 服务发现

前面咱们说,厨师想通过喊服务员名字来让服务员上菜,但是呢它并不知道当前哪些服务员是能提供服务的,于是便需要向 eureka-server 去获取可用服务列表,于是厨师就不需要关注服务员叫什么了。

咱们对 cook-service 和 waiter-service 分别创建一个 controller 包,在 cook 的 controller 包中新建 CookController类,在 waiter 的 controller 中新建 WaiterController 类,此处咱们就不新建 Service 层 和 Mapper 层了,这里只是为了学习服务发现,所以使用一层演示就足够了。

对于 waiter 服务来说,就提供一个接口,这个接口就是执行一个模拟的任务:

package com.zlcode.waiter.controller;import jakarta.websocket.server.PathParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/waiter")
@Slf4j
public class WaiterController {@RequestMapping("/up")public String up(@PathParam("content") String content) {log.info("正在执行: " + content);return "执行: " + content + "成功!";}
}

上述 waiter 就提供了 /waiter/up 这个接口,比如传递的 content 为 “给55桌上红烧肉”,这个请求就会打印一下这个content,然后再模拟返回结果。下面咱们来使用 postman 测试这个接口的可用性:

在这里插入图片描述

这里可用发现 waiter 服务的 up 接口成功返回了预期的值,同时在 waiter 的控制台也能看到:

在这里插入图片描述

调用 waiter 的 up 方法后,成功的模拟执行了上菜操作!

接下来咱们看一下 cook 提供了哪个接口:

package com.zlcode.cook.controller;import jakarta.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/cook")
public class CookController {@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/ok")public String ok(@PathParam("content")String content) {// 通过 discoveryClient 从 eureka-server 获取服务列表List<ServiceInstance> instances = discoveryClient.getInstances("waiter-service");String uri = instances.get(0).getUri().toString(); // 拿到服务列表的第一个 ip:端口号// ----------------------------------------------------------// 这里咱们拿到了 waiter 的 ip 地址和端口号// 也就是知道了服务员的名字,那么要如何告诉服务员你需要让他上菜呢?// 当然现实中可用喊一嗓子,但在代码中呢?// ---------------------------------------------------------return "";}
}

此时这里就可用通过 discoveryClient.getInstances 实例列表,此处是获取名字为 waiter-service 的服务列表,获取后,通过 instances.get(0).getUri().toString(); 获取这个实例的 ip 和 端口号。

为什么这里可能会有多个实例呢?别忘记了,把同一个项目换成不同的端口号,分别运行,这就是两个服务,同时这两个服务都进行服务注册,此时 eureka 上就会有两个这样的服务了,只是对应的端口号不同,如果端口号相同,但是ip不同,也就是在不同的主机上,这样也是 ok 的。

但是这里只启动了一个 waiter-service 服务,所以咱们取第 0 个就ok了。

ip 和端口号是拿到了,可是如何调用 waiter-service 服务提供的 up 接口呢?

其实也很简单,既然都拿到ip端口号了,直接使用 ip+端口号/waiter/up?content=“xxx” 这个 url 给 waiter 发一个 http 请求就ok了,但是使用 js 发 http 请求相信都会,但是在 Java 中如何给发送 http 请求呢?

这里可用使用 Spring 提供的 RestTemplate 类,通过这个可用发送一个 http 请求,但是注意了!!!

想认识 RestTemplate 就得知道什么是 Rest。

REST(Representational State Transfer),表现层资源状态转移。

简单来说:REST描述的是在网络中Client和Server的⼀种交互形式,REST本身不实用,实用的是如何设计RESTfulAPI(REST风格的网络接口)接口类似于:

GET/blog/{blogId}:查询博客
DELETE/blog/{blogId}:删除博客

而 RestTemplate 是Spring提供,封装HTTP调⽤,并强制使用RESTful风格。它会处理HTTP连接和关闭,只需要使用者提供资源的地地和参数即可。

所以要想使用这个 RestTemplate 进行 http 请求,先得把咱们 waiter 服务的 up 接口改成 Rest 风格的接口:

package com.zlcode.waiter.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/waiter")
@Slf4j
public class WaiterController {@RequestMapping("/up/{content}")public String up(@PathVariable("content") String content) {log.info("正在执行: " + content);return "执行: " + content + "成功!";}
}

接下来在 cook-service 项目中先定义 RestTemplate,把这个对象交给 Spring 容器管理,在 cook 目录下创建 config 目录,在这个目录下创建一个 BeanConfig 类,在这个类中定义好咱们要用的 RestTemplate 就 OK 了。

package com.zlcode.cook.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class BeanConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

接下来修改 CookConroller 的 ok 接口:

package com.zlcode.cook.controller;import jakarta.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.List;@RestController
@RequestMapping("/cook")
public class CookController {@Autowiredprivate DiscoveryClient discoveryClient;@Autowiredprivate RestTemplate restTemplate;// 咱们的 cook 里面的接口可以不遵循 Rest 规范,// 只要保证使用 restTemplate 调用的接口遵守 Rest 规范就ok了@RequestMapping("/ok")public String ok(@PathParam("content")String content) {// 通过 discoveryClient 从 eureka-server 获取服务列表List<ServiceInstance> instances = discoveryClient.getInstances("waiter-service");String uri = instances.get(0).getUri().toString(); // 拿到服务列表的第一个 ip:端口号// 通过 restTemplate 给 waiter-service 发送 http 请求String url = uri + "/waiter/up/{content}";// 第一个参数是请求 url, // 第二个参数是这个请求的返回值类型的class对象, // 第三个参数是占位符对应的值String resp = restTemplate.getForObject(url, String.class, content);return "调用成功, 已收到 waiter 的响应: " + resp;}
}

此时咱们此处的代码,就是 cook 厨师,通过 eureka 注册中心获取到服务列表,拿到第一个服务的 ip和端口,通过这个 ip 和 端口 拼接上完整的接口路由,带上参数,就实现了远程方法调用了。

此处如果服务员离职了,来了个新的服务员,对于厨师来说,没有任何影响,厨师只需要关注注册中心有哪些服务列表就行了。

3.6 服务注册和发现的注意点

List<ServiceInstance> instances = discoveryClient.getInstances("waiter-service");
String uri = instances.get(0).getUri().toString(); // 拿到服务列表的第一个 ip:端口号
String url = uri + "/waiter/up/{content}";
String resp = restTemplate.getForObject(url, String.class, content);

上面代码是服务发现和远程调用的重要代码。

上面的 discoveryClient.getInstances(“waiter-service”) 这里方法的形参,waiter-service 就像是给这个服务取了一个名字,比如传菜的都叫做服务员,只要名字叫 waiter-service 的服务,都能获取到,那么注册中心是如何知道每个服务的名字呢?

在这里插入图片描述

观察 waiter-service 的 spring.application.name 的值是 waiter-server,注册中心就是通过这个 name 来区分的,所以也就是有可能出现如下的情况:

服务A 的名字:waiter-service 这个服务只提供了 test 接口
服务B 的名字:waiter-service 这个服务只提供了 hello 接口

由于服务 AB 启动时都会进行服务注册,那么问题来了,通过discoveryClient.getInstances(“waiter-service”) 会拿到两个实例,也就是可以获取两个服务的 ip 和 端口号,假设 服务C 想调用 test 接口,而服务C 只知道 name 为 waiter-service 的服务提供了 test 接口,但是服务C不知道的是:AB都叫 test-service,但是服务B没有提供 test 接口。

如果此时 C 通过 instances.get(0).getUri().toString();,拿到的是服务B的ip和端口,此时再通过 restTemplate 进行调用 test 接口,那问题就大了!!

也就是说,如果统称为服务员,那么必须都得具备传菜的接口服务。

所以对于这里的 spring.application.name 的值,要保证相同的 name 它所提供的服务(接口)要是一致的!

在这里插入图片描述

现在咱们就来复现上面这种情况,先创建 B/hello 和 A/test 接口,并且这两个服务都叫做 waiter-service。

AController:

package com.zlcode.waiter.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AController {@RequestMapping("test")public String test () {return "成功调用了 服务A 的 test 接口";}
}

BController:

package com.zlcode.waiter.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class BController {@RequestMapping("/hello")public String hello() {return "成功调用了 服务B 的 hello 接口";}
}

启动这两个服务A和服务B,服务A的端口为9091,服务B的端口为9092,此时可以发现 服务A 只提供了 test 接口,服务B 只提供了 hello 接口。

在这里插入图片描述

此时启动服务A和服务B,都发现已经成功使用 waiter-service 这个名字进行服务注册了。

然后使用服务C去获取 waiter-service 对应的服务列表,调用下这两个服务的 test 接口:

package com.zlcode.cook.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;@Slf4j
@RestController
@RequestMapping("/C")
public class CController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/run")public void run() {List<ServiceInstance> instances = discoveryClient.getInstances("waiter-service");for (ServiceInstance instance : instances) {String uri = instance.getUri().toString();log.info("获取到服务器地址:" + uri);String url = uri + "/test";try {String resp = restTemplate.getForObject(url, String.class);log.info(uri + " 调用服务器 test 接口成功! resp: " + resp);} catch (Exception e) {e.printStackTrace();log.error("服务器: " + uri + "没有提供 test 接口.");}}}
}

上述就是服务C,咱们给它运行在 8080 端口上,然后调用 127.0.0.1/C/run 这个接口后,他就会从注册中心获取 waiter-service 服务信息,此时能拿到两个,9091 端口是提供了 test 接口服务的,而 9092 则没有提供 test 接口服务。

在 postman 调用 127.0.0.1/C/run 观察项目打印日志:

在这里插入图片描述

果然不出所料,没有提供 test 接口的服务B就会报 404 错误。所以现在你理解了服务名的重要性了吗?

相关文章:

【SpringCloud】Eureka的使用

3. Eureka 3.1 Eureka 介绍 Eureka主要分为两个部分&#xff1a; EurekaServer: 作为注册中心Server端&#xff0c;向微服务应用程序提供服务注册&#xff0c;发现&#xff0c;健康检查等能力。 EurekaClient: 服务提供者&#xff0c;服务启动时&#xff0c;会向 EurekaS…...

nuxt3 seo优化

在 Nuxt3 中&#xff0c;通过 nuxtjs/seo、nuxtjs/sitemap 和 nuxtjs/robots 模块可以生成包含动态链接的站点地图&#xff08;sitemap.xml&#xff09;&#xff0c;但具体是“实时生成”还是“部署时生成”&#xff0c;取决于你的配置方式和数据更新频率。以下是具体分析&…...

初识MySQL · 数据类型

目录 前言&#xff1a; 数值类型 文本、二进制数据类型 时间类型 String类型 前言&#xff1a; 对于MySQL来说&#xff0c;是一门编程语言&#xff0c;可能定义不是那么的严格&#xff0c;但是对于MySQL来说也是拥有自己的数据类型的&#xff0c;比如tinyint&#xff0c;…...

【Go】数组

数组Array 重点&#xff1a; 数组是值类型 注意点: 1. 数组&#xff1a;是同一种数据类型的固定长度的序列。2. 数组定义&#xff1a;var a [len]int&#xff0c;比如&#xff1a;var a [5]int&#xff0c;数组长度必须是常量&#xff0c;且是类型的组成部分。一旦定义&…...

QT图片轮播器(QT实操学习2)

1.项目架构 1.UI界面 2.widget.h​ #ifndef WIDGET_H #define WIDGET_H#include <QWidget>#define TIMEOUT 1 * 1000 QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent n…...

深度解析衡石科技HENGSHI SENSE嵌入式分析能力:如何实现3天快速集成

嵌入式分析成为现代SaaS的核心竞争力 在当今SaaS市场竞争中&#xff0c;数据分析能力已成为产品差异化的关键因素。根据Bessemer Venture Partners的最新调研&#xff0c;拥有深度嵌入式分析功能的SaaS产品&#xff0c;其客户留存率比行业平均水平高出23%&#xff0c;ARR增长速…...

杂草YOLO系列数据集4000张

一份开源数据集——杂草YOLO数据集&#xff0c;该数据集适用于农业智能化、植物识别等计算机视觉应用场景。 数据集详情 ​训练集&#xff1a;3,664张高清标注图像​测试集&#xff1a;180张多样性场景样本​验证集&#xff1a;359张严格筛选数据 下载链接 杂草YOLO数据集分…...

Mybatis_Plus中常用的IService方法

查询 方法名 查询记录总数 /*** 查询总记录数** see Wrappers#emptyWrapper()*/default long count() {return count(Wrappers.emptyWrapper());} 方法实现 Testpublic void testGetCount(){long count userService.count();System.out.println("总记录数&#xff1a;&…...

​Flink/Kafka在python中的用处

一、基础概念 1. ​Apache Kafka 是什么&#xff1f; ​核心功能&#xff1a;Kafka 是一个分布式流处理平台&#xff0c;主要用于构建实时数据管道和流式应用程序。​核心概念&#xff1a; ​生产者&#xff08;Producer&#xff09;​&#xff1a;向 Kafka 发送数据的程序。…...

Vue 2 探秘:visible 和 append-to-body 是谁的小秘密?

&#x1f680; Vue 2 探秘&#xff1a;visible 和 append-to-body 是谁的小秘密&#xff1f;&#x1f914; 父组件&#xff1a;identify-list.vue子组件&#xff1a;fake-clue-list.vue 嘿&#xff0c;各位前端探险家&#xff01;&#x1f44b; 今天我们要在 Vue 2 的代码丛林…...

机器学习的一百个概念(1)单位归一化

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…...

SpringCould微服务架构之Docker(5)

Docker的基本操作&#xff1a; 镜像相关命令&#xff1a; 1.镜像名称一般分两部分组成&#xff1a;[repository]:[tag]。 2. 在没有指定tag时&#xff0c;默认是latest&#xff0c;代表着最新版本的镜像。 镜像命令的案例&#xff1a; 镜像操作常用的命令&#xff1a; dock…...

JVM 如何打破双亲委派模型?

虽然双亲委派模型是 Java 类加载机制的推荐实现方式&#xff0c;但在某些情况下&#xff0c;为了实现特定的功能&#xff0c;可能需要打破双亲委派模型。以下是一些常见的打破双亲委派模型的方法和场景&#xff1a; 1. 重写 loadClass 方法 (不推荐): 原理&#xff1a; java.l…...

DeepSeek结合MCP Server与Cursor,实现服务器资源的自动化管理

MCP Server是最近AI圈子中又一个新的热门话题。很多用户都通过结合大语言模型、MCP Server&#xff0c;实现了一些工具流的自动化&#xff0c;例如&#xff0c;你只需要给出文字指令&#xff0c;就可以让Blender自动化完成建模的工作。你有没有想过&#xff0c;利用MCP来让AI A…...

SpringAI与JBoltAI深度对比:从工具集到企业级AI开发范式的跃迁

一、Java生态下大模型开发的困境与需求 技术公司的能力断层 多数企业缺乏将Java与大模型结合的标准开发范式&#xff0c;停留在碎片化工具使用阶段。 大模型应用需要全生命周期管理能力&#xff0c;而不仅仅是API调用。 工具集的局限性 SpringAI作为工具集的定位&#xff1…...

后端返回了 xlsx 文件流,前端怎么下载处理

当后端返回一个 .xlsx 文件流时&#xff0c;前端可以通过 JavaScript 处理这个文件流并触发浏览器下载。 实现步骤 发送请求获取文件流&#xff1a; 使用 fetch 或 axios 等工具向后端发送请求&#xff0c;确保响应类型设置为 blob&#xff08;二进制数据流&#xff09;。 创建…...

一文读懂Python之json模块(33)

一、json模块介绍 json模块的功能是将序列化的json数据从文件里读取出来或者存入文件。json是一种轻量级的数据交换格式&#xff0c;在大部分语言中&#xff0c;它被理解为数组&#xff08;array&#xff09;。 json模块序列化与反序列化的过程分别是 encoding和 decoding。e…...

Python中multiprocessing的使用详解

1.实现多进程 代码实现&#xff1a; from multiprocessing import Process import datetime import timedef task01(name):current_timedatetime.datetime.now()start_timecurrent_time.strftime(%Y-%m-%d %H:%M:%S). "{:03d}".format(current_time.microsecond //…...

强化学习与神经网络结合(以 DQN 展开)

目录 基于 PyTorch 实现简单 DQN double DQN dueling DQN Noisy DQN&#xff1a;通过噪声层实现探索&#xff0c;替代 ε- 贪心策略 Rainbow_DQN如何计算连续型的Actions 强化学习中&#xff0c;智能体&#xff08;Agent&#xff09;通过与环境交互学习最优策略。当状态空间或动…...

函数式组件中的渲染函数 JSX

在 Vue.js 和 React 等现代前端框架中&#xff0c;函数式组件已成为一种非常流行的设计模式。函数式组件是一种没有内部状态和生命周期方法的组件&#xff0c;其主要功能是接受 props 并渲染 UI。随着这些框架的演进&#xff0c;渲染函数和 JSX&#xff08;JavaScript XML&…...

北斗导航 | 基于因子图优化的GNSS/INS组合导航完好性监测算法研究,附matlab代码

以下是一篇基于因子图优化(FGO)的GNSS/INS组合导航完好性监测算法的论文框架及核心内容,包含数学模型、完整Matlab代码及仿真分析基于因子图优化的GNSS/INS组合导航完好性监测算法研究 摘要 针对传统卡尔曼滤波在组合导航完好性监测中对非线性与非高斯噪声敏感的问题,本文…...

飞书电子表格自建应用

背景 coze官方的插件不支持更多的飞书电子表格操作&#xff0c;因为需要自建应用 飞书创建文件夹 创建应用 开发者后台 - 飞书开放平台 添加机器人 添加权限 创建群 添加刚刚创建的机器人到群里 文件夹邀请群 创建好后&#xff0c;就可以拿到id和key 参考教程&#xff1a; 创…...

深度学习四大核心架构:神经网络(NN)、卷积神经网络(CNN)、循环神经网络(RNN)与Transformer全概述

目录 &#x1f4c2; 深度学习四大核心架构 &#x1f330; 知识点概述 &#x1f9e0; 核心区别对比表 ⚡ 生活化案例理解 &#x1f511; 选型指南 &#x1f4c2; 深度学习四大核心架构 第一篇&#xff1a; 神经网络基础&#xff08;NN&#xff09; &#x1f330; 知识点概述…...

MCP Server 实现一个 天气查询

​ Step1. 环境配置 安装 uv curl -LsSf https://astral.sh/uv/install.sh | shQuestion: 什么是 uv 呢和 conda 比有什么区别&#xff1f; Answer: 一个用 Rust 编写的超快速 (100x) Python 包管理器和环境管理工具&#xff0c;由 Astral 开发。定位为 pip 和 venv 的替代品…...

《强化学习基础概念:四大模型与两大损失》

强化学习基础概念一、策略模型1. 策略的定义2. 策略的作用3.策略模型 二、价值模型1. 价值函数的定义&#xff08;1&#xff09;状态值函数&#xff08;State Value Function&#xff09;&#xff08;2&#xff09;动作值函数&#xff08;Action Value Function&#xff09; 2.…...

Headless Chrome 优化:减少内存占用与提速技巧

在当今数据驱动的时代&#xff0c;爬虫技术在各行各业扮演着重要角色。传统的爬虫方法往往因为界面渲染和资源消耗过高而无法满足大规模数据采集的需求。本文将深度剖析 Headless Chrome 的优化方案&#xff0c;重点探讨如何利用代理 IP、Cookie 和 User-Agent 设置实现内存占用…...

知识就是力量——HELLO GAME WORD!

你好&#xff01;游戏世界&#xff01; 简介环境配置前期准备好文章介绍创建头像小功能组件安装本地中文字库HSV颜色空间音频生成空白的音频 游戏UI开发加载动画注册登录界面UI界面第一版第二版 第一个游戏&#xff08;贪吃蛇&#xff09;第二个游戏&#xff08;俄罗斯方块&…...

电脑连不上手机热点会出现的小bug

一、问题展示 注意: 不要打开 隐藏热点 否则他就会在电脑上 找不到自己的热点 二、解决办法 把隐藏热点打开即可...

unity 做一个圆形分比图

// 在其他脚本中控制多段进度 using System.Collections.Generic; using UnityEngine;public class GameManager : MonoBehaviour {public MultiCircleProgress circleProgress;void Start(){// 初始化数据circleProgress.segments new List<MultiCircleProgress.ProgressS…...

JAVA反序列化深入学习(八):CommonsCollections6

与CC5相似&#xff1a; 在 CC5 中使用了 TiedMapEntry#toString 来触发 LazyMap#get在 CC6 中是通过 TiedMapEntry#hashCode 来触发 LazyMap#get 之前看到了 hashcode 方法也会调用 getValue() 方法然后调用到其中 map 的 get 方法触发 LazyMap&#xff0c;那重点就在于如何在反…...