SpringCloud基础篇

文章目录

  • 创建新模块
  • 拷贝yml配置文件
  • 修改配置文件的信息
  • 修改`pom.xml`文件
  • 启动入口
  • 拷贝相关文件
  • 接口文档配置
  • 配置启动项
  • 注册中心原理
  • Nacos注册中心
    • 创建nacos数据库存储数据
    • 部署nacos在docker容器中
  • 服务注册
    • 引入依赖
    • 配置Nacos地址
    • 启动
  • 服务发现(调用)
    • 引入依赖
    • 配置nacos地址
    • 发现并调用服务
  • 快速入门
    • 引入依赖
    • 启动OpenFeign
    • 编写OpenFeign客户端Client
    • 使用FeignClient
  • 连接池(提高响应速度)
    • 引入依赖
    • 开启连接池
  • 最佳实践
    • 抽取Feign客户端
    • 扫描包
  • 日志配置
    • 定义日志级别
    • 配置生效
  • 总结
    • 如何利用OpenFeign实现远程调用
    • 如何配置OpenFeign连接池
    • OpenFeign使用的最佳实践方式是什么
    • 如何配置OpenFeign输出日志的级别

image.png

之前我们说过,微服务拆分时粒度要小,这其实是拆分的目标。具体可以从两个角度来分析:

  • 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。
  • 低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。

高内聚首先是单一职责,但不能说一个微服务就一个接口,而是要保证微服务内部业务的完整性为前提。目标是当我们要修改某个业务时,最好就只修改当前微服务,这样变更的成本更低。
一旦微服务做到了高内聚,那么服务之间的耦合度自然就降低了。

当然,微服务之间不可避免的会有或多或少的业务交互,比如下单时需要查询商品数据。这个时候我们不能在订单服务直接查询商品数据库,否则就导致了数据耦合。而应该由商品服务对应暴露接口,并且一定要保证微服务对外接口的稳定性(即:尽量保证接口外观不变)。虽然出现了服务间调用,但此时无论你如何在商品服务做内部修改,都不会影响到订单微服务,服务间的耦合度就降低了。

明确了拆分目标,接下来就是拆分方式了。我们在做服务拆分时一般有两种方式:

  • 纵向拆分
  • 横向拆分

所谓纵向拆分,就是按照项目的功能模块来拆分。例如黑马商城中,就有用户管理功能、订单管理功能、购物车功能、商品管理功能、支付功能等。那么按照功能模块将他们拆分为一个个服务,就属于纵向拆分。这种拆分模式可以尽可能提高服务的内聚性。

而横向拆分,是看各个功能模块之间有没有公共的业务部分,如果有将其抽取出来作为通用服务。例如用户登录是需要发送消息通知,记录风控数据,下单时也要发送短信,记录风控数据。因此消息发送、风控数据记录就是通用的业务功能,因此可以将他们分别抽取为公共服务:消息中心服务、风控管理服务。这样可以提高业务的复用性,避免重复开发。同时通用业务一般接口稳定性较强,也不会使服务之间过分耦合。

当然,由于黑马商城并不是一个完整的项目,其中的短信发送、风控管理并没有实现,这里就不再考虑了。而其它的业务按照纵向拆分,可以分为以下几个微服务:

  • 用户服务
  • 商品服务
  • 订单服务
  • 购物车服务
  • 支付服务

创建新模块

image.png

拷贝yml配置文件

image.png

修改配置文件的信息

image.png

application.yaml
application-dev.yaml
application-local.yaml

因为我的mysql是部署在docker里面的, 所以dev环境与虚拟机里部署的mysql相挂载

修改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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>hmall</artifactId>
        <groupId>com.heima</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-service</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!--common-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--feign模块-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-api</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--nacos 服务注册发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--openFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--负载均衡器-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--OK http 的依赖 -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

记得修改SpringBoot的版面本号为2.xxx

启动入口

package com.hmall.cart;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
public class CartApplication {

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

	@Bean
	public RestTemplate restTemplate(){
		return new RestTemplate();
	} // 这个是远程调用需要的工具 后面就不用这个了
}

记得加上mapper扫包, 如果需要远程调用别的模块的方法, 在此加上RestTemplate

image.png

在这里启动服务, 而不是跑到每个启动入口去启动, 这里还要修改启动端口, 具体如下

image.pngimage.png

拷贝相关文件

image.png

拷贝顺序最好是: domain -> mapper -> service -> impl -> controller 这样报错就会少一些

接口文档配置

knife4j:
  enable: true
  openapi:
    title: 黑马商城购物车管理接口文档
    description: "黑马商城购物车管理接口文档"
    email: zhanghuyi@itcast.cn
    concat: 虎哥
    url: https://www.itcast.cn
    version: v1.0.0
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - com.hmall.cart.controller // 这里扫包路径记得更改!!!!!!

记得改扫描路径

配置启动项

image.png

这是一个引导, 后面介绍的Nacos更方便操作远程调用

image.png

先将RestTemplate注册为一个Bean:

package com.hmall.cart.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RemoteCallConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

接下来,我们修改cart-service中的com.hmall.cart.service.impl.CartServiceImplhandleCartItems方法,发送http请求到item-service
image.png

注册中心原理

在微服务远程调用的过程中,包括两个角色:

  • 服务提供者:提供接口供其它微服务访问,比如item-service
  • 服务消费者:调用其它微服务提供的接口,比如cart-service

image.png

流程如下:

  • 服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心
  • 调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)
  • 调用者自己对实例列表负载均衡,挑选一个实例
  • 调用者向该实例发起远程调用

当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?

  • 服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)
  • 当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除
  • 当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表
  • 当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表

Nacos注册中心

拉取nacos-server镜像

docker pull nacos/nacos-server:v2.1.0-slim

创建nacos数据库存储数据

新建一个名为nacos的数据库, 然后导入下面的nacos.sql文件即可

我们基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,将SQL文件导入到Docker中的MySQL容器中:

image.png

部署nacos在docker容器中

请自行创建一个nacos文件夹, 里面再创建一个custom.env文件,内容如下:
其中的nacos/custom.env文件中,有一个MYSQL_SERVICE_HOST也就是mysql地址,
需要修改为你自己的虚拟机IP地址:

PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=8.134.57.218
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=123456
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

image.png

然后,将nacos目录上传至虚拟机的/root目录。
进入root目录,然后执行下面的docker命令:

docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim

mkdir -p /data/nacos/{conf,logs}
chmod -R 777 /data/nacos/{conf,logs}
docker cp nacos:/home/nacos/conf/application.properties /data/nacos/conf/

docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
-v /data/nacos/logs:/home/nacos/logs \
-v /data/nacos/conf/application.properties:/home/nacos/conf/application.properties \
-v /data/nacos/data:/home/nacos/data \
--restart=always \
nacos/nacos-server:v2.1.0-slim

=---=
docker run -d \
-e MODE=standalone \
--privileged=true \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.100.100 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=ovoAdmin123 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e TIME_ZONE='Asia/Shanghai' \
-v /data/nacos/logs:/home/nacos/logs \
-v /data/nacos/data:/home/nacos/data \
-v /data/nacos/conf:/home/nacos/conf \
-p 8848:8848 -p 9848:9848 -p 9849:9849 \
--name nacos --restart=always nacos/nacos-server:v2.1.0-slim
  1. docker run -d: 这部分启动一个后台(detached)容器,使容器在后台运行。
  2. –name nacos: 指定容器的名称为 “nacos”。
  3. –env-file ./nacos/custom.env: 从指定的环境变量文件 ./nacos/custom.env 中读取环境变量。这可以包含 Nacos 服务的配置信息。
  4. -p 8848:8848 -p 9848:9848 -p 9849:9849: 将容器内部的端口映射到主机上。这里将 Nacos 默认的三个端口 8848、9848、9849 映射到主机的对应端口。
  5. –restart=always: 在容器退出时,总是重新启动容器。这样可以确保 Nacos 服务在意外退出后自动重新启动。
  6. nacos/nacos-server:v2.1.0-slim: 指定要运行的 Docker 镜像的名称和版本。这里使用的是 Nacos 的官方镜像 nacos/nacos-serverv2.1.0-slim 版本。

启动完成后,访问下面地址:http://192.168.164.128:8848/nacos/,注意将192.168.164.128替换为你自己的虚拟机IP地址。首次访问会跳转到登录页,账号密码都是nacos

image.png

服务注册

  • 引入依赖
  • 配置Nacos地址
  • 启动 !!!

引入依赖

如果父工程配有springcloud的版本的话, 这里就不用带version了

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.0.4.0</version> 
</dependency>

配置Nacos地址

在item-service的application.yml中添加nacos地址配置:

spring:
  application:
    name: item-service # 服务名称
  cloud:
    nacos:
      server-addr: 192.168.164.128:8848 # nacos地址

启动

可以copy多一份启动两份服务实例
image.png
image.png

重启item-service的两个实例:
image.png

访问Nacos控制台, 发现启动成功:
image.png

点击详情,可以查看到item-service服务的两个实例信息:
image.png

服务发现(调用)

这里也只是引导, 后面用OpenFeign代码更简洁

  • 引入依赖
  • 配置Nacos地址
  • 发现并调用服务

引入依赖

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置nacos地址

spring:
  cloud:
    nacos:
      server-addr: 192.168.164.128:8848

发现并调用服务

接下来,服务调用者cart-service就可以去订阅item-service服务了。不过item-service有多个实例,而真正发起调用时只需要知道一个实例的地址。

因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:

  • 随机
  • 轮询
  • IP的hash
  • 最近最少访问

这里我们可以选择最简单的随机负载均衡。

另外,服务发现需要用到一个工具,
DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:

image.png

接下来,我们就可以对原来的远程调用做修改了,之前调用时我们需要写死服务提供者的IP和端口:
现在不需要了,我们通过DiscoveryClient发现服务实例列表,通过负载均衡算法,选择一个实例去调用:

private void handleCartItems(List<CartVO> vos) {
    // 1.获取商品id
    Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toS
    // 2.查询商品
    //List<ItemDTO> items = itemService.queryItemByIds(itemIds);
    // 2.1 根据服务名称获取服务实例列表
    List<ServiceInstance> instances = discoveryClient.getInstances("item-service")
    if(CollUtil.isEmpty(instances)){
        // 服务不存在
        return;
    }
    // 2.2 手写负载均衡, 从实例列表中挑选一个实例
    ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()
    // 2.3 利用RestTemplate发送http请求,得到http相应(远程调用)
    ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
            instance.getUri() + "/items?ids={ids}",
            HttpMethod.GET,
            null,
            new ParameterizedTypeReference<List<ItemDTO>>() {
            },
            Map.of("ids", CollUtil.join(itemIds, ","))
    );
    // 2.2 解析响应
    if(!response.getStatusCode().is2xxSuccessful()){
        // 查询失败, 直接结束
        return;
    }

到这里nacos的基本注册和使用就结束啦~

快速入门

引入依赖

<!--openFeign-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

启动OpenFeign

我们在cart-service的CartApplication启动类上添加注解,启动OpenFeign功能:
image.png

编写OpenFeign客户端Client

这里可以直接参考最佳实践~client统一写在一个package里

在cart-service中,定义一个新的接口,编写Feign客户端:

package com.hmall.cart.client;

import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient("item-service")
public interface ItemClient {

    @GetMapping("/items")
    List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}

这里只需要声明接口,无需实现方法。接口中的几个关键信息:

  • @FeignClient(“item-service”) :声明服务名称
  • @GetMapping :声明请求方式
  • @GetMapping(“/items”) :声明请求路径
  • @RequestParam(“ids”) Collection ids :声明请求参数
  • List:返回值类型

有了上述信息,OpenFeign就可以利用动态代理帮我们实现这个方法,并且向http://item-service/items发送一个GET请求,携带ids为请求参数,并自动将返回值处理为List。
我们只需要直接调用这个方法,即可实现远程调用了。

使用FeignClient

我们在cart-service对应的实现层中改造代码,直接调用ItemClient的方法:
image.png

feign替我们完成了服务拉取、负载均衡、发送http请求的所有工作,是不是看起来优雅多了。
而且,这里我们不再需要RestTemplate了,还省去了RestTemplate的注册

连接池(提高响应速度)

  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

引入依赖

在cart-service的pom.xml中引入依赖:

<!--OK http 的依赖 -->
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
</dependency>

开启连接池

feign:
  okhttp:
    enabled: true # 开启OKHttp功能

最佳实践

  • 思路1:抽取到微服务之外的公共module
  • 思路2:每个微服务自己抽取一个module

image.png

方案1抽取更加简单,工程结构也比较清晰,但缺点是整个项目耦合度偏高。
方案2抽取相对麻烦,工程结构相对更复杂,但服务之间耦合度降低。

我们最终采取方案一, 代码较少~

抽取Feign客户端

在hmall下定义一个新的module,命名为hm-api
image.png

记得在父工程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">
    <parent>
        <artifactId>hmall</artifactId>
        <groupId>com.heima</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hm-api</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!--open feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- load balancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!-- swagger 注解依赖 -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.6</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

然后把ItemDTO和ItemClient都拷贝过来,最终结构如下:
image.png

扫描包

任何微服务要调用item-service中的接口,只需引hm-api模块依赖即可,无需自己编写Feign客户端了。

<!--feign模块-->
  <dependency>
      <groupId>com.heima</groupId>
      <artifactId>hm-api</artifactId>
      <version>1.0.0</version>
  </dependency>
  • 方式1:声明扫描包:

image.png

  • 方式2:声明要用的FeignClient

image.png

这里比较推荐使用方式1, 直接扫描整个client包, 小孩才做选择, 我全都要~

日志配置

OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

定义日志级别

在hm-api模块下新建一个配置类,定义Feign的日志级别:

后面的保存用户登录信息在各微服务使用也是在这个配置里写Bean, 划重点~

image.png

package com.hmall.api.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.Basic; // 推荐使用Basic
    }
}

配置生效

要让日志级别生效,还需要配置这个类。有两种方式:

  • 局部生效:在某个FeignClient中配置,只对当前FeignClient生效
@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
  • 全局生效:在@EnableFeignClients中配置,针对所有FeignClient生效。
@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)

总结

如何利用OpenFeign实现远程调用

  • 引入OpenFeign和SpringCloudLoadBalancer依赖
  • 利用@EnableFeignClients注解开启OpenFeign功能
  • 编写FeignClient

如何配置OpenFeign连接池

  • 引入http客户端依赖, 例如OKhttp, HttpClient
  • 配置yml文件, 打开OpenFeign连接池开关

OpenFeign使用的最佳实践方式是什么

  • 由服务提供者编写独立module, 将FeignClient及DTO抽取

如何配置OpenFeign输出日志的级别

  • 声明类型为Logger].Level的Bean
  • 在@FeignClient或@EnableFeignClient注解上使用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OK527N-C开发板-简单的性能测试

OK527N-C CoreMark 获取CoreMark源码 首先使用Git克隆仓库&#xff1a; git clone https://github.com/eembc/coremark.git cd coremark修改Makefile 首先复制文件夹 cp -rf posix ok527之后修改ok527文件夹下的core_portme.mak文件&#xff0c;将CC修改如下 CC aarch6…

全国1:100万地貌类型空间分布数据

我们在《136G全国1m土地覆盖数据》一文中&#xff0c;为你分享了全国1米分辨率的土地覆盖数据。 现在再为你分享全国1:100万地貌类型空间分布数据&#xff0c;你可以在文末查看该数据的领取方式。 全国1:100万地貌类型空间分布数据 全国1:100万地貌类型空间分布数据来源于《…

【QT】多元素控件

目录 概述 List Widget 核心属性 核心方法 核心信号 QListWidgetItem核心方法 Table Widget 核心方法 QTableWidgetItem 核心信号 QTableWidgetItem 核心方法 使用示例&#xff1a; Tree Widget 核心方法 核心信号 QTreeWidgetItem核心属性 QTreeWidgetItem核…

(九)绘制彩色三角形

前面的学习中并未涉及到颜色&#xff0c;现在打算写一个例子&#xff0c;在顶点着色器和片元着色器中加入颜色&#xff0c;绘制有颜色的三角形。 #include <glad/glad.h>//glad必须在glfw头文件之前包含 #include <GLFW/glfw3.h> #include <iostream>void …

13-4 GPT-5:博士级AI,人工智能的新时代

图片来源&#xff1a;AI Disruptive 人工智能世界正在迅速发展&#xff0c;新的创新和突破层出不穷。在本文中&#xff0c;我们将深入探讨最新的进展&#xff0c;从即将推出的 GPT-5 模型到 Apple 和 Meta 之间可能的合作。 GPT-5&#xff1a;博士级别的人工智能 虽然尚未正…

GL823K USB 2.0 SD/MSPRO读卡器控制芯片

概述 GL823K是一个USB 2.0单轮读卡器控制芯片&#xff0c;可以支持SD/MMC/MSPRO闪存卡。它支持USB 2.0高速传输&#xff0c;它在一个芯片上可以控制读取诸如安全数字卡&#xff08;SD卡&#xff09;&#xff0c;SDHC卡&#xff0c;迷你SD卡&#xff0c;微SD卡&#xff08;T-Fl…

Upload-Labs靶场闯关

文章目录 Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16Pass-17Pass-18Pass-19Pass-20 以下是文件上传绕过的各种思路&#xff0c;不过是鄙人做题记下来的一些思路笔记罢了。 GitHub靶场环境下载&#x…

带电池监控功能的恒流直流负载组

EAK的交流和直流工业电池负载组测试仪对于测试和验证关键电力系统的能力至关重要&#xff0c;旨在实现最佳精度。作为一家客户至上的公司&#xff0c;我们继续尽我们所能应对供应链挑战&#xff0c;以提供出色的交货时间&#xff0c;大约是行业其他公司的一半。 交流负载组 我…

嵌入式c语言2——预处理

在c语言中&#xff0c;头部内容&#xff0c;如include与define是不参与编译而直接预先处理的 如include相当于把头文件扩展&#xff0c;define相当于做了替换 c语言大型工程创建时&#xff0c;会有调试版本与发行版本&#xff0c;发行时不希望看到调试部分内容&#xff0c;此时…

如何使用 Builder 设计模式和 DataFaker 库在自动化测试中生成测试数据

在自动化 API/Web 或移动应用程序时&#xff0c;您可能会遇到这样的情况&#xff1a;在注册用户时&#xff0c;您可能正在设置用于在测试自动化的端到端用户旅程中签出产品的地址。 那么&#xff0c;你是怎么做到的呢&#xff1f; 通常&#xff0c;我们在 Java 中创建一个 POJO…

鸿蒙开发设备管理:【@ohos.distributedHardware.deviceManager (设备管理)】

设备管理 本模块提供分布式设备管理能力。 系统应用可调用接口实现如下功能&#xff1a; 注册和解除注册设备上下线变化监听发现周边不可信设备认证和取消认证设备查询可信设备列表查询本地设备信息&#xff0c;包括设备名称&#xff0c;设备类型和设备标识 说明&#xff1a…

检索增强生成RAG系列5--RAG提升之路由(routing)

在系列3和系列4我讲了关于一个基本流程下&#xff0c;RAG的提高准确率的关键点&#xff0c;那么接下来&#xff0c;我们再次讲解2个方面&#xff0c;这2个方面可能与RAG的准确率有关系&#xff0c;但是更多的它们是有其它用途。本期先来讲解RAG路由。 目录 1 基本思想2 Logica…

Linux基础 - LNMP 架构部署动态网站环境

目录 零. 简介 一. 部署 二. 安装 Nginx 三. 安装MySQL 四. 安装PHP 五. 配置网站目录 六. 测试环境 零. 简介 LNMP 是指 Linux Nginx MySQL PHP 这一组合架构&#xff0c;用于部署动态网站环境。 Linux 作为操作系统&#xff0c;提供了稳定、安全和高效的基础平台。…

Swift 中强大的 Key Paths(键路径)机制趣谈(上)

概览 小伙伴们可能不知道&#xff1a;在 Swift 语言中隐藏着大量看似“其貌不扬”实则却让秃头码农们“高世骇俗”&#xff0c;堪称卧虎藏龙的各种秘技。 其中&#xff0c;有一枚“不起眼”的小家伙称之为键路径&#xff08;Key Paths&#xff09;。如若将其善加利用&#xff…

MYSQL函数进阶详解:案例解析(第19天)

系列文章目录 一、MySQL的函数&#xff08;重点&#xff09; 二、MySQL的窗口函数&#xff08;重点&#xff09; 三、MySQL的视图&#xff08;熟悉&#xff09; 四、MySQL的事务&#xff08;熟悉&#xff09; 文章目录 系列文章目录前言一、MySQL的函数1. 聚合函数2. group_c…

Linux基础 - MariaDB 数据库管理系统

目录 零. 简介 一. 安装 二. 基本使用 1. 设置root密码 2. 创建库 3. 创建表 4.添加数据 5. 查看数据 三. 管理表单及数据 四. 数据库的备份及恢复 零. 简介 MariaDB 是一种流行的开源数据库管理系统&#xff0c;它是 MySQL 的一个分支。 MariaDB 保留了与 MySQL 的…

HarmonyOS APP应用开发项目- MCA助手(Day01持续更新中~)

简言&#xff1a; gitee地址&#xff1a;https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5 注&#xff1…

激光粒度分析仪校准步骤详解:提升测量精度的秘诀

在材料科学、环境监测、医药研发等众多领域&#xff0c;激光粒度分析仪以其高精度、高效率的测量性能&#xff0c;成为了不可或缺的测试工具。然而&#xff0c;为了保持其测量结果的准确性和可靠性&#xff0c;定期校准是不可或缺的步骤。 接下来&#xff0c;佰德将为您详细介…

可视化低代码平台之:RayData光启元的震撼作品。

RayData家的可视化作品&#xff0c;贝格前端工场是经常碰到&#xff0c;制作十分的精良&#xff0c;业内很有影响力。他们也有自己的低代码平台&#xff0c;分为了桌面版和网页版&#xff0c;本期分享一下他们的作品。

【单片机毕业设计选题24043】-可旋转式电视支架控制系统设计与实现

系统功能: 系统操作说明&#xff1a; 上电后OLED显示 “欢迎使用电视支架系统请稍后”&#xff0c;两秒后进入正常界面显示 第一页面第一行显示 Mode:Key&#xff0c; 第二行显示 TV:Middle 短按B5按键可控制步进电机左转&#xff0c; 第二行显示 TV:Left 后正常显示 TV:…