SpringCloud详解,图文码笔记

注意: SpringCloud并 不等于 微服务

1.微服务技术线

在这里插入图片描述
在这里插入图片描述


2.认识微服务

分布式架构

分布式架构: 根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。

优点:

  • 降低服务耦合
  • 有利于服务升级拓展

服务治理

分布式架构的要考虑的问题:

  • 服务拆分粒度如何?
  • 服务集群地址如何维护?
  • 服务之间如何实现远程调用?
  • 服务健康状态如何感知?

微服务

微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
  • 面向服务:微服务对外暴露业务接口
  • 自治:团队独立、技术独立、数据独立、部署独立
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

在这里插入图片描述

微服务结构

微服务这种方案需要技术框架来落地,全球的互联网公司都在积极尝试自己的微服务落地技术。在国内最知名的就是SpringCloud和阿里巴巴的Dubbo

在这里插入图片描述

微服务技术对比

在这里插入图片描述

SpringCloud

  • SpringCloud是目前国内使用最广泛的微服务框架。官网地址: https://spring.io/proiects/spring-cloud
  • SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开

在这里插入图片描述

SpringCloud与SpringBoot的版本兼容关系如下

在这里插入图片描述

服务拆分及远程调用

注意事项

  1. 不同微服务,不要重复开发相同业务

  2. 微服务数据独立,不要访问其它微服务的数据库

3.服务远程调用

提供者与消费者

  • 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
  • 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

bean

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

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

    /**
     * 创建RestTemplate并注入Spring容器
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

demo

public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用 restTemplate,发起 http 请求
        String url = "http://localhost:8081/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到order
        order.setUser(user);
        // 4.返回
        return order;
}

4.Eureka 注册中心

  • 消费者该如何获取服务提供者具体信息?
    • 服务提供者启动时向eureka注册自己的信息
    • eureka保存这些信息
    • 消费者根据服务名称向eureka拉取提供者信息
  • 如果有多个服务提供者,消费者该如何选择?
    • 服务消费者利用负载均衡算法,从服务列表中挑选一个
  • 消费者如何感知服务提供者健康状态?
    • 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
    • eureka会更新记录服务列表信息,心跳不正常会被剔除
    • 消费者就可以拉取到最新的信息

搭建EurekaServer

1.创建项目,引入spring-cloud-starter-netflix-eureka-server的依赖

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

2.编写启动类,添加@EnableEurekaServer注解

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

3.添加application.yml文件,编写下面的配置:

server:
  port: 10800
spring:
  application:
    name: eurekaserver # eureka 服务名称
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka # eureka 服务地址

服务注册

	<!-- eureka客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_goods?useSSL=false
    username: root
    password: blm123
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: orderserver
mybatis:
  type-aliases-package: cn.itcast.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.itcast: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
    # eureka config
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka # eureka 服务地址

服务发现

在order-service完成服务拉取
服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡

  1. 修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:

    	String url = "http://userserver/user/" + order.getUserId();
    
  2. 在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:

    	@Bean
        @LoadBalanced // 负载均衡
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用 restTemplate,发起 http 请求
        String url = "http://userserver/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到order
        order.setUser(user);
        // 4.返回
        return order;
    }

Ribbon 负载均衡

在这里插入图片描述
在这里插入图片描述

1. 改变负载均衡规则

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

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

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

    /**
     * 改变负载均衡规则
     * @return
     */
    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }
}

2.负载均衡规则配置

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则

饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    clients: userserver # 饥饿加载服务名称 (支持list)
    enabled: true # 开启饥饿加载模式

5.Nacos

启动命令:

  • linux(centos): sh startup.sh -m standalone
  • Windows: startup.cmd -m standalone

Nacos笔记

6.Feign

RestTemplate 方式调用存在的问题

先来看我们以前利用RestTemplate发起远程调用的代码:

String url = "http: //userservice/user/" + order.getUserId();
User user = restTemplate.getFor0bject(url,User.class);

存在下面的问题:

  • 代码可读性差,编程体验不统一。
  • 参数复杂URL难以维护

Feign的介绍

Feign是一个声明式的http客户端,官方地址: https://github.com/OpenFeign/feign其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

使用Feign的步骤如下:

  1. 引入依赖:
    Feign是一个声明式的http客户端,官方地址: https://github.com/OpenFeign/feign其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

    <!-- feign 客户端依赖 -->
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 在order-service的启动类添加注解开启Feign的功能: @EnableFeigncients

    @EnableFeigncients
    @MapperScan( "cn.itcast.order.mapper")
    @springBootApplication
    public class 0rderApplicationi
    public static void main( String[ ] args) {
    	SpringApplication.run(OrderApplication.class,args);
    }
    

使用Feign的步骤如下:

3.编写Feign客户端:

@FeignClient("userservice" )
public interface Userclient {
	GetMapping("/ user/{id}")
	User findById(@PathVariable ("id") Long id);
}

主要是基于SpringMVC的注解来声明远程调角的信息,比如:

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值类型:User

自定义Feign的配置

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

在这里插入图片描述

一般我们需要配置的就是日志级别。

配置Feign日志有两种方式:

**方式一︰**配置文件方式

全局生效:

feign:
	client:
		config:
			default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
				loggerLevel: FULL#日志级别

局部生效:

feign:
	client:
		config:
			userservice: #这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置loggerLevel: FULL#日志级别
				config:
					default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
						loggerLevel: FULL#日志级别

方式二: java代码方式,需要先声明一个Bean:

public class FeignclientConfiguration {
	@Bean
	public Logger.Level feignLogLevel(){
		return Logger.Level.BASIC;
	}
}

如果是全局配置,则把它放到@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = FeignclientConfiguration.class)

如果是局部配置,则把它放到@FeignClient这个注解中:

@FeignClient(value = "userservice" , configuration = FeignClientConfiguration.class)

Feign的性能优化

Feign底层的客户端实现:

  • URLConnection: 默认实现,不支持连接池
  • Apache HttpClient:支持连接池
  • OKHttp:支持连接池

因此优化Feign的性能主要包括

  • 使用连接池代替默认的URLConnection
  • 日志级别,最好用basic或none

Feign添加HttpClient的支持

引入依赖:

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

配置连接池:

feign:
	client:
		config:
			default: # default全局的配置
				loggerLevel: BASIC # 日志级别,BASIC就是基本的请和响应信息
	httpclient:
		enabled: true # 开feign对HttpClient的支持
		max-connections: 200 # 最大的连接数
		max-connections-per-route: 50 # 每个路径的最大连接数

Feign的最佳实践

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

在这里插入图片描述

lt is generally not advisable to share an interface between a server and a client. t introduces tight coupling, andalso actually doesn’t work with Spring MVC in its current form (method parameter mapping is not inherited).

通常不建议在服务器和客户端之间共享一个接口。它引入了紧密耦合,并且实际上与当前形式的SpringMVC不兼容(方法参数映射不继承)。

方式二(抽取): 将FeignClient抽取为独立模块,并且把接口有关的POJ0、默认的Feign配置都放到这个模块中,提供给所有消费者使用

在这里插入图片描述

Feign的最佳实践

  1. 让controller和FeignClient继承同一接口
  2. 将FeignClient、PoJo、Feign的默认配置都定义到一个项目中,供所有消费者使用

实现方式二 (抽取FeignClient)

步骤如下:

  1. 首先创建一个module,命名为feign-api,然后引入feign的starter依赖
  2. 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
  3. 在order-service中引入feign-api的依赖
  4. 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
  5. test

当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。

有两种方式解决

​ 方式一:指定FeignClient所在包

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

​ 方式二:指定FeignClient字节码

@EnableFeignClients(clients = {UserClient.class})

7.统一网关Gateway

网关功能:

  • 身份认证和权限校验
  • 服务路由、负载均衡
  • 请求限流

在这里插入图片描述

网关的技术实现

​ 在SpringCloud中网关的实现包括两种:

  • gateway

  • zuul

    Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能

搭建网关服务

在这里插入图片描述

搭建网关服务的步骤:

  1. 创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:

    <!-- 网关依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- nacos服务发现依赖 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  2. 编写路由配置及nacos地址

    server:
    	port: 10010 # 网关端口
    spring:
    	application:
    		name: gateway # 服务名称
    	cloud:
    		nacos:
    			server-addr : localhost:8848 # nacos地址
    		gateway :
    			routes: # 网关路由配置
    				- id: user-service #路由id,自定义,只要唯─即可
    				  # uri: http ://127.0.0.1:8081 #路由的目标地址 http就是固定地址
    				  uri: lb://userservice #路由的目标地址lb就是负载均衡,后面跟服务名称
    				  predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
    				   - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
    

理由配置包括:

  1. 路由id:路由的唯一标示

  2. 路由目标(uri) :路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡

  3. 路由断言( predicates) :判断路由的规则,

  4. 路由过滤器( filters) :对请求或响应做处理

路由断言工厂

Route Predicate Factory

  • 我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件

  • 例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的

  • 像这样的断言工厂在SpringCloudGateway还有十几个

在这里插入图片描述

路由过滤器GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:

案例

给所有进入userservice的请求添加一个请求头

​ 给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

​ 实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器:

spring:
	cloud:
		gateway:
			routes: # 网关路由配置
				- id: user-service
				uri: lb://userserver
				predicates:
					- Path=/user/**
				filters: # 过滤器
					AddRequestHeader=key,value # 添加请求头

默认过滤器

如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:

spring:
	application:
		name: gateway #服务名称
	cloud:
		nacos:
			server-addr: localhost:8848 # nacos地址
		gateway :
			routes: # 网关路由配置
				- id: user-service
				  uri: lb: //userservice
				  predicates:
					- Path=/user/**
				- id: order-service
				  uri: lb: //orderservicepredicates:
					- Paith=/order/**
			default-filters: # 默认过滤器,会对所有的路由请求都生效
				- AddRequestHeader=key, value #添加请求头

全局过滤器GlobalFilter

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。

定义方式是实现GlobalFilter接口。

public interface GlobalFilter {
    /**
    * 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
    * @param exchange请求上下文,里面可以获取Request、Response等信息
    *@param chain用来把请求委托给下一个过滤器
    * @return {@code Mono<Void>}返回标示当前过滤器业务结束
    */
    Mono<Void> filter(ServerWebExchange exchange,6atewayFilterChain chain);
}

实现

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        // 2.获取参数中的 authorization参数
        String auth = params.getFirst("authorization");
        // 3.判断参数值是否等于admin
        if ("admin".equals(auth)) {
            // 4.是,放行
            return chain.filter(exchange);
        }
        // 5.否,拦截
        // 5.1 设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 5.2 拦截请求
        return exchange.getResponse().setComplete();
    }
}

过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

在这里插入图片描述

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
  • 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

跨域问题处理

跨域问题: 浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案: CORS

**网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现: **

spring:
	cloud:
		gateway:
			# ...
			globalcors: # 全局的跨域处理
				add-to-simpLe-urL-handler-mapping: true # 解决options 请求被拦截问题
				corsConfigurations:
					'[/**]' :
						allowedOrigins: # 允许哪些网站的跨域请求
							- "http: / /LocaLhost:8090"
							- "http:/ /www.Leyou.com"
						allowedMethods: # 允许的跨域ajax的请求方式
							- "GET"
							- "POST"
							- "DELETE"
							- "PUT"
							- "OPTIONS"
						allowedHeaders: "*" # 允许在请求中携带的头信息
						allowCredentials: true # 是否允许携带cookie
						maxAge: 360000 # 这次跨域检测的有效期

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

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

相关文章

java方法的引用传递和值传递

1、方法的值参数传递 下面代码&#xff0c;它会在控制台输出什么&#xff1f; public class ArrayTest {public static void main(String[] args) {int number 100;System.out.println(number);change(number);System.out.println(number);}public static void change(int n…

C#开发中方法使用的问题注意

C#开发中&#xff0c;我们在进行方法内嵌时&#xff0c;需要注意方法回传带值时&#xff0c;我们需要对方法回传的值进行一个赋值传递 如下所示 console.WriteLine("请输入你的爱好&#xff1a;"); string aihao Console.ReadLine(); name ChangeData(name);同时在…

element el-cascader获取完整数据

<el-table-column prop"createTime" label"编辑店铺分类"><template slot-scope"scope"><el-cascaderref"cascader"v-model"scope.row.shoptypeone":options"commoditylist"placeholder"请选…

软件工程- 第4章 结构化分析方法

4.1 基本术语 4.2 模型表示 上述场景&#xff1a;旅行社帮旅客订机票&#xff0c;交付给旅客机票和帐单。 旅行社基于旅客的订票单和航空公司的航班目录预定机票&#xff0c;确定航班准备机票&#xff0c;订票成功&#xff0c;机票数据流向客户。费用记账&#xff0c;生成记账…

深入探索C与C++的混合编程

实现混合编程的技术细节 混合使用C和C可能由多种原因驱动。一方面&#xff0c;现有的大量优秀C语言库为特定任务提供了高效的解决方案&#xff0c;将这些库直接应用于C项目中可以节省大量的开发时间和成本。另一方面&#xff0c;C的高级特性如类、模板和异常处理等&#xff0c;…

CSS 零基础入门教程

目录 1. div 和 span2. 什么是CSS&#xff1f;3. CSS 引入方式3.1 内部样式表3.2 外部样式表3.3 行内样式 4. 选择器4.1 标签选择器4.2 类选择器4.3 id 选择器4.4 通配符选择器 5. CSS 基础属性6. 谷歌浏览器调试工具 正文开始。 1. div 和 span 在学习 CSS 之前&#xff0c;…

好玩的仿真过节烟花模拟器程序

好玩的仿真过节烟花模拟器程序&#xff0c;页面上自动放烟花&#xff0c;可以开启喇叭&#xff0c;也可以点击左上角的设置 下载地址 好玩的仿真过节烟花模拟器程序

mfc140u.dll丢失的解决方法,解决mfc140u.dll问题,让程序运行畅通无阻

如果你的电脑丢失了mfc140u.dll文件&#xff0c;那么可能是电脑中的mfc140u.dll文件发成了变化&#xff0c;倒是点找不到mfc140u.dll文件&#xff0c;并运行mfc140u.dll&#xff0c;那么有什么办法可以解mfc140u.dll丢失的问题呢&#xff1f;接了下来就带大脚先了解一下mfc140u…

MySQL学习笔记(一)

1、什么是数据库&#xff1f;什么是数据库管理系统&#xff1f;什么是SQL&#xff1f;他们之间的关系是什么&#xff1f; 数据库&#xff1a;英文单词DataBase&#xff0c;简称DB。按照一定格式存储数据的一些文件的组合。顾名思义&#xff0c;存储数据的仓库&#xff0c;实际…

牛客题霸-SQL入门篇(刷题记录二)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 以下内容是牛客题霸-SQL入门篇剩余的第 21-39 道题目的 SQL 代码答案。 由于涉及到的数据库表较多&#xff0c;因…

网络分层架构(七/四层协议)详解

OSI七层模型和TCP/IP四层模型 业内普遍的分层方式有两种&#xff1a;OSI七层模型 和TCP/IP四层模型。记忆则为 “应表会传网数物” 关于协议&#xff1a; ① OSI七层模型详解 结构名 功能 主要设备 应用层 是最靠近用户的OSI层。用户接口、应用程序。应用层向应用进程展示…

【超图】SuperMap如何使知识图谱与BIM数据的绑定

作者&#xff1a;taco 近两年知识图谱的概念突然大火了起来&#xff0c;随之而来的就是用户的各种需求&#xff0c;你们的知识图谱能干什么呢&#xff1f;知识图谱有哪些应用呢&#xff1f;在结合客户的一些需求&#xff0c;以及自身的一些想法&#xff0c;写下这篇文章。 一、…

【涨薪技术】0到1学会性能测试 —— 参数化关联

前言 上一次推文我们分享了性能测试工作原理、事务、检查点&#xff01;今天给大家带来性能测试参数化&#xff0c;检查点知识&#xff01;后续文章都会系统分享干货&#xff0c;带大家从0到1学会性能测试&#xff0c;另外还有教程等同步资料&#xff0c;文末免费获取~ 01、性…

类和对象-1

文章目录 面向过程和面向对象的概念类的引入访问限定符类的大小this指针 面向过程和面向对象的概念 面向过程是一种按照步骤顺序执行的编程方式&#xff0c;而面向对象则是以对象为中心&#xff0c;将数据和操作封装在一起。在面向对象编程中&#xff0c;可以通过定义类和对象来…

stm32-模拟数字转化器ADC

接线图&#xff1a; #include "stm32f10x.h" // Device header//1: 开启RCC时钟&#xff0c;包括ADC和GPIO的时钟//2&#xff1a;配置GPIO将GPIO配置为模拟输入模式//3&#xff1a;配置多路开关将左边的通道接入到规则组中//4&#xff1a;配置ADC转…

zookeeper安装配置

zookeeper是什么 ZooKeeper是一个分布式的&#xff0c; 开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是 ​​​​​​​Hadoop和Hbase的重要组件。它是一个为​​​​​​​分布式应用提供一致性服务的软件&#xff0c;提供的功能…

redis学习-Set集合类型相关命令及特殊情况分析

目录 1. sadd key value1 value2 ... 2. smembers key 3. sismember key value 4. scard key 5. srem key value1 value2 ... 6. srandmember key num 7. spop key num 8. smove key1 key2 value 9. sdiff key1 key2 key3 ... 10. sinter key1 key2 ... 11. sunion key1 key2 .…

mybatis缓存(学习笔记17)

1、什么是缓存&#xff1a;存在内存中的临时数据 将用户经常查询的数据放在缓存&#xff08;内存&#xff09;中&#xff0c;用户去查询数据就不用从磁盘&#xff08;关系数据库数据文件&#xff09;查询&#xff0c;从缓存中查询&#xff0c;从而提高查询效率&#xff0c;解决…

分析云星空数据用奥威-金蝶BI,快且直观

财务指标计算难&#xff0c;数量太大&#xff0c;报表需求太多&#xff0c;报表根本做不完&#xff1f;如果云星空用户遇到这种情况&#xff0c;建议用奥威-金蝶BI方案。预设分析模型和BI报表&#xff0c;注册、下载并执行方案&#xff0c;立得200多张BI数据可视化分析报表&…

MS16_016 漏洞利用与安全加固

文章目录 环境说明1 MS16_016 简介2 MS16_016 复现过程3 MS16_016 安全加固 环境说明 渗透机操作系统&#xff1a;kali-linux-2024.1-installer-amd64漏洞复现操作系&#xff1a;cn_windows_7_professional_with_sp1_x64_dvd_u_677031 1 MS16_016 简介 MS16_016 漏洞产生的原因…