SpringCloud基础篇

news2024/12/21 18:52:45

文章目录

  • 创建新模块
  • 拷贝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.coloradmin.cn/o/1888045.html

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

相关文章

Webpack: 插件架构之Hook体系

概述 Webpack 之所以能够应对 Web 场景下极度复杂、多样的构建需求&#xff0c;关键就在于其健壮、扩展性极强的插件架构&#xff0c;而插件架构的精髓又在于其灵活多变的 Hook 体系&#xff0c;可以说&#xff0c;只有真正掌握 Hook 底层设计与实现逻辑&#xff0c;深入理解不…

qt 开发笔记堆栈布局的应用

1.概要 画面中有一处位置&#xff0c;有个按钮点击后&#xff0c;这片位置完全换成另一个画面&#xff0c;这中情况特别适合用堆栈布局。 //堆栈布局的应用 #include <QStackedLayout> QStackedLayout *layout new QStackedLayout(this); layout->setCurrentIndex(…

音乐伴奏提取?唱歌剪辑好用的音频人声分离软件!提取步骤很简单!

随着数字技术的飞速发展&#xff0c;音乐制作和编辑领域也迎来了前所未有的变革。其中&#xff0c;音乐伴奏提取和音频人声分离技术更是成为了音乐创作者和音频工程师手中的得力助手。本文将探讨这两项技术的最新进展&#xff0c;并分析6月发布的8款新品软件。 一、音乐伴奏提取…

美术馆预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;展品信息管理&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;美术馆管理&#xff0c;基础数据管理&#xff0c;论坛管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;美术馆&#xff…

Android 换肤之主题换肤

文章目录 Android 换肤之主题换肤概述效果实现代码结构定义属性定义主题在Activity中使用在Fragment中使用工具类 源码下载 Android 换肤之主题换肤 概述 Android 实现应用内换肤的常用方式&#xff08;两种&#xff09;&#xff1a; 通过Theme切换主题&#xff0c;即静态方…

《企业实战分享 · 常用运维中间件》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

【第三版 系统集成项目管理工程师】第5 章 软件工程

持续更新。。。。。。。。。。。。。。。 【第三版】第五章 软件工程 5.1软件工程定义练习 5.2软件需求5.2.1雾求的层次1.业务需求-P2032.用户需求-P2033.系统需求-P203 5.2.2质量功能部署 P2035.2.3需求获取 P2045.2.4需求分析1.结构化分析-P2042.面向对象分析-P207 5.2.5号求…

IDEA中Maven的配置

目录 1. 安装maven 2. 配置环境变量 3. IDEA中配置Maven 4. 配置仓库目录 1. 安装maven 官网下载地址&#xff1a;Maven – Download Apache Maven 下载后&#xff0c;将zip压缩包解压到某个目录即可。 2. 配置环境变量 变量名称随意&#xff0c;通常为M2_HOME&#xff…

DLS平台:运价持续上涨,未来航运市场何去何从?

摘要&#xff1a; 近期&#xff0c;上海出口集装箱结算运价指数&#xff08;SCFIS&#xff09;欧洲航线连续10周上涨&#xff0c;涨幅高达151%。随着多家航运公司宣布涨价&#xff0c;市场供应紧张导致运价居高不下。本文将详细分析当前运价上涨的原因、航运市场的变化及未来运…

精打细算:建设酒吧或小酒馆

开设一家酒吧或小酒馆&#xff0c;不仅仅是一场对美酒的浪漫追求&#xff0c;更是一次深思熟虑的投资决策过程。在这个过程中&#xff0c;选择合适的酿造设备是至关重要的一步&#xff0c;它直接关系到酒吧的运营效率、产品品质乃至最终的盈利能力。本文天泰小编将从多个维度出…

『Z-MeetUP』 6月29日线下活动——跨越Web3基础设施边界

Meetup In Hangzhou ZJUBCA 2024 求是 创新 TIME:2024/06/29 ADD:浙江大学紫金港校区 概述 / OVERVIEW 悠闲午后&#xff0c;感谢大家积极参与此次社区聚会&#xff0c;我们共同探讨了跨越Web3基础设施边界&#xff0c;发掘技术前沿&#xff0c;领略链上生态的无限可能。 让我…

Qt Creator13配置Android开发环境

QT Creator13是目前&#xff08;2024年&#xff09;最新版本&#xff0c;配置Android开发环境有一些不一样&#xff0c;走了一些弯路&#xff0c;记录如下。 1、安装JDK和SDK 下载安装JDK和SDK&#xff0c;建议安装在无空格和中文字符的目录下。 具体安装步骤不再赘述&#…

TongRDS2214手动部署版指引(by lqw+sy)

文章目录 前言准备工作单机版集群版哨兵版多个中心节点配置 前言 由于一些特殊原因&#xff08;例如服务器没有联网&#xff0c;没有办法直接更新和下载unzip指令&#xff0c;从而导致控制台版本安装节点之后&#xff0c;会报file not found的错误&#xff0c;或者使用不了rds…

CQ 社区版2.13.3 | 支持全局开启OTP登录、文本导入功能可独立控制……

又到一月一度的 CloudQuery 发版时间啦&#xff01; 本次版本更新&#xff0c;对多个模块进行了功能的优化和完善&#xff0c;比如将文本导入与 insert 权限脱离使文本导入可单独控制&#xff1b;将工具权限与权限等级脱离&#xff0c;使其能独立授权和提权&#xff1b;操作模…

项目实战--Spring Boot + Minio文件切片上传下载

1.搭建环境 引入项目依赖 <!-- 操作minio的java客户端--> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version> </dependency> <!-- jwt鉴权相应依赖--> &…

初试总分409分,专业课143,西电821专业

非常感谢自己考研409分上岸西安电子科技大学&#xff0c;杭州研究院&#xff0c;专业课143分&#xff0c;跟的研梦&#xff0c;讲课以及答疑还是非常专业的。 821专业课课本总共有四本&#xff0c;都在官网考纲的参考书里写了&#xff0c;不过主要参考其中两本&#xff0c;一本…

机器学习笔记 LightGBM:理解算法背后的数学原理

一、简述 在一次数据科学的比赛中&#xff0c;我有机会使用 LightGBM&#xff0c;这是一种最先进的机器学习算法&#xff0c;它极大地改变了我们处理预测建模任务的方式。我对它在数千个数据点上进行训练的速度感到着迷&#xff0c;同时保持了其他算法难以达到的准确性。LightG…

EasyExcel4导入导出数据(基于MyBatisPlus)

一、POM依赖 <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"><m…

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…