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);}@Beanpublic RestTemplate restTemplate(){return new RestTemplate();} // 这个是远程调用需要的工具 后面就不用这个了
}

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

image.png

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

image.pngimage.png

拷贝相关文件

image.png

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

接口文档配置

knife4j:enable: trueopenapi:title: 黑马商城购物车管理接口文档description: "黑马商城购物车管理接口文档"email: zhanghuyi@itcast.cnconcat: 虎哥url: https://www.itcast.cnversion: v1.0.0group:default:group-name: defaultapi-rule: packageapi-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 {@Beanpublic 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-slimmkdir -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.获取商品idSet<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 {@Beanpublic 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.mzph.cn/bicheng/39478.shtml

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

相关文章

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《面向电网调峰的电动汽车聚合商多层级实时控制策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

通过docker overlay2 目录名查找占用磁盘空间最大的容器名和容器ID

有时候经常会有个别容器占用磁盘空间特别大&#xff0c; 这个时候就需要通过docker overlay2 目录名查找占用磁盘空间最大的容器名和容器ID&#xff1a; 1、 首先进入到 /var/lib/docker/overlay2 目录下,查看谁占用的较多 [rootPPS-97-8-ALI-HD1H overlay2]# cd /var/lib/doc…

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

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

独一无二的设计模式——单例模式(python实现)

1. 引言 大家好&#xff0c;今天我们来聊聊设计模式中的“独一无二”——单例模式。想象一下&#xff0c;我们在开发一个复杂的软件系统&#xff0c;需要一个全局唯一的配置管理器&#xff0c;或者一个统一的日志记录器&#xff1b;如果每次使用这些功能都要创建新的实例&…

IDEA中Maven的配置

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

MySQL/SqlServer 跨服务器 增删改查(CRUD) 的一种方法

前言&#xff1a;主要是利用SqlServer 的链接服务器功能 1.准备一台 SqlServer Server&#xff0c;服务如下图&#xff1a; 这台服务器专门用于 链接服务器 IP&#xff1a;10.x.x.3 和数据源服务器&#xff08;10.x.x.5&#xff09; 在一个局域网 1.1 版本 是 2017 2.在 10.…

吴晓波:企业出海的最佳时间窗口只有5-10年,中国企业如何把握出海机遇?

鼓励企业参与绿色“一带一路”建设&#xff0c;带动先进的环保技术、装备、产能走出去。 出海计划&#xff01;马来西亚水环境项目国际考察暨2024中马水务合作论坛

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

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

网络爬虫基础知识

文章目录 网络爬虫基础知识爬虫的定义爬虫的工作流程常用技术和工具爬虫的应用1. 抓取天气信息2. 抓取新闻标题3. 抓取股票价格4. 抓取商品价格5. 抓取博客文章标题 网络爬虫基础知识 爬虫的定义 网络爬虫&#xff08;Web Crawler 或 Spider&#xff09;是一种自动化程序&…

Librechat快速部署指南

引言 Github的开源免费程序里&#xff0c;Librechat作为AI对话使用&#xff0c;现阶段可谓是最佳选择&#xff0c;配合聚合API >>进行使用&#xff0c;能够保证成本最低&#xff0c;自由度最高&#xff0c;私密性最强&#xff0c;功能丰富且界面美观&#xff0c;如此以来…

【黑龙江等保测评是如何评估的?】

黑龙江地区的等级评定&#xff0c;是根据国家有关的法律、法规、规范的规定&#xff0c;对该信息系统的安全性进行评价的。评估的具体程序和方法包括&#xff1a; 1.评价对象与范围的界定&#xff1a;一是要明确评价的目的与要求&#xff0c;二是要按照特定的要求来确定评价的…

MIX OTP——依赖项和总体项目

在本章中&#xff0c;我们将讨论如何管理 Mix 中的依赖项。 我们的 kv 应用程序已经完成&#xff0c;现在是时候实现处理我们在第一章中定义的请求的服务器了&#xff1a; 但是&#xff0c;我们不会向 kv 应用程序添加更多代码&#xff0c;而是将 TCP 服务器构建为另一个应用程…

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

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

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

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

Linux:文件系统与日志分析

一、block与inode 1.1、概述 文件是存储在硬盘上的&#xff0c;硬盘的最小存储单位叫做“扇区”(sector)&#xff0c;每个扇区存储512字节。 一般连续八个扇区组成一个"块”(block)&#xff0c;一个块是4K大小&#xff0c;是文件存取的最小单位。 文件数据包括实际数据…

linux 环境报错:Peer reports incompatible or unsupported protocol version

出现问题的原因&#xff1a; curl 不兼容或不支持的协议版本。 解决方案&#xff1a; yum update -y nss curl libcurl如此继续之前的操作即可。

(九)绘制彩色三角形

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

我爱服务器——LVM实战学习

后来呀&#xff0c;天亮之前毕业后踏入服务器领域了。。。。。。 LVM&#xff08;Logical Volume Manager&#xff09;是一个高级的磁盘管理框架&#xff0c;它允许用户将多个物理硬盘组合成一个逻辑卷&#xff0c;从而提供更大的存储空间、更高的灵活性和更好的数据管理能力。…

Eclipse + GDB + J-Link 的单片机程序调试实践

Eclipse GDB J-Link 的调试实践 本文介绍如何创建Eclipse的调试配置&#xff0c;如何控制调试过程&#xff0c;如何查看修改各种变量。 对 Eclipse 的要求 所用 Eclipse 应当安装了 Eclipse Embedded CDT 插件。从 https://www.eclipse.org/downloads/packages/ 下载 Ecli…

C++ 快速行进方法(二维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 假设给你一个将一个区域与另一个区域分开的界面,以及告诉你如何移动界面上每个点的速度F。下图中,黑色曲线将内部深蓝色与外部浅蓝色分开,黑色曲线的每个点都给出了速度F。此外,假设速度F始终为正,即前端始终向…