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

微服务实战——登录(普通登录、社交登录、SSO单点登录)

登录

1.1. 用户密码

@PostMapping("/login")public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session){R r = memberFeignService.login(vo);if(r.getCode() == 0){MemberRespVo data = r.getData("data", new TypeReference<MemberRespVo>() {});session.setAttribute("loginUser", data);return "redirect:http://gulimall.com";}else {Map<String, String> errors = new HashMap<>();errors.put("msg", r.getData("msg", new TypeReference<String>(){}));redirectAttributes.addFlashAttribute("errors", errors);return "redirect:http://auth.gulimall.com/login.html";}}@GetMapping("/login.html")public String loginPage(HttpSession session){Object loginUser = session.getAttribute("loginUser");if(loginUser != null){return "redirect:http://gulimall.com";}return "login";}
@Overridepublic MemberEntity login(MemberLoginVo vo) {String loginacct = vo.getLoginacct();String password = vo.getPassword();MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>().eq("username", loginacct).or().eq("mobile", loginacct));BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();if(memberEntity == null){return null;}if (passwordEncoder.matches(password, memberEntity.getPassword())) {return memberEntity;}return null;}

1.2. 社交登录

QQ 、微博、 github 等网站的用户量非常大,别的网站为了简化自我网站的登陆与注册逻辑,引入社交登陆功能;

步骤:

1 )、用户点击 QQ 按钮

2 )、引导跳转到 QQ 授权页

3)、用户主动点击授权,跳回之前网页。

1.2.1. OAuth2.0
  • OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
  • OAuth2.0:对于用户相关的 OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。

  • 官方版流程:

(A )用户打开客户端以后,客户端要求用户给予授权。

(B )用户同意给予客户端授权。

(C )客户端使用上一步获得的授权,向认证服务器申请令牌。

(D )认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E )客户端使用令牌,向资源服务器申请获取资源。

(F )资源服务器确认令牌无误,同意向客户端开放资源。

OAuth2.0流程:

  • 使用Code换取AccessToken,Code只能用一次
  • 同一个用户的accessToken一段时间是不会变化的,即使多次获取
1.2.2. 代码实现

1)、进入微博开放平台

微博组件_微博开放平台

2)、添加社交登录回调接口

认证接口

  • 通过HttpUtils发送请求获取token,并将token等信息交给member服务进行社交登录
  • 若获取token失败或远程调用服务失败,则封装错误信息重新转回登录页

修改“com.cwh.gulimall.auth.feign.MemberFeignService”类,代码如下:

@PostMapping("/member/member/oauth2/login")
public R oauth2Login(@RequestBody SocialUser socialUser);

添加“com.cwh.gulimall.auth.vo.SocialUser”类,代码如下:

package com.cwh.gulimall.auth.vo;import lombok.Data;@Data
public class SocialUser {private String access_token;private String remind_in;private long expires_in;private String uid;private String isRealName;
}

添加“com.cwh.gulimall.auth.vo.MemberResponseVO”类,代码如下:

package com.cwh.gulimall.auth.vo;import lombok.Data;
import lombok.ToString;import java.util.Date;@ToString
@Data
public class MemberResponseVO {private Long id;/*** 会员等级id*/private Long levelId;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 昵称*/private String nickname;/*** 手机号码*/private String mobile;/*** 邮箱*/private String email;/*** 头像*/private String header;/*** 性别*/private Integer gender;/*** 生日*/private Date birth;/*** 所在城市*/private String city;/*** 职业*/private String job;/*** 个性签名*/private String sign;/*** 用户来源*/private Integer sourceType;/*** 积分*/private Integer integration;/*** 成长值*/private Integer growth;/*** 启用状态*/private Integer status;/*** 注册时间*/private Date createTime;private String socialUid;private String accessToken;private long expiresIn;
}

添加“com.cwh.gulimall.auth.controller.Oauth2Controller”类,代码如下:

@Controller
public class OauthController {@Autowiredprivate MemberFeignService memberFeignService;@RequestMapping("/oauth2.0/weibo/success")public String authorize(String code, RedirectAttributes attributes) throws Exception {// 1、使用code换取token,换取成功则继续2,否则重定向至登录页Map<String, String> query = new HashMap<>();query.put("client_id", "2144***074");query.put("client_secret", "ff63a0d8d5*****29a19492817316ab");query.put("grant_type", "authorization_code");query.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");query.put("code", code);// 发送post请求换取tokenHttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<String, String>(), query, new HashMap<String, String>());Map<String, String> errors = new HashMap<>();if (response.getStatusLine().getStatusCode() == 200) {// 2. 调用member远程接口进行oauth登录,登录成功则转发至首页并携带返回用户信息,否则转发至登录页String json = EntityUtils.toString(response.getEntity());SocialUser socialUser = JSON.parseObject(json, new TypeReference<SocialUser>() {});R login = memberFeignService.login(socialUser);// 2.1 远程调用成功,返回首页并携带用户信息if (login.getCode() == 0) {String jsonString = JSON.toJSONString(login.get("memberEntity"));MemberResponseVo memberResponseVo = JSON.parseObject(jsonString, new TypeReference<MemberResponseVo>() {});attributes.addFlashAttribute("user", memberResponseVo);return "redirect:http://gulimall.com";}else {// 2.2 否则返回登录页errors.put("msg", "登录失败,请重试");attributes.addFlashAttribute("errors", errors);return "redirect:http://auth.gulimall.com/login.html";}}else {errors.put("msg", "获得第三方授权失败,请重试");attributes.addFlashAttribute("errors", errors);return "redirect:http://auth.gulimall.com/login.html";}}

登录接口

  • 登录包含两种流程,实际上包括了注册和登录
  • 如果之前未使用该社交账号登录,则使用token调用开放api获取社交账号相关信息,注册并将结果返回
  • 如果之前已经使用该社交账号登录,则更新token并将结果返回

添加“com.cwh.gulimall.member.vo.SocialUser”类,代码如下:

package com.cwh.gulimall.member.vo;import lombok.Data;@Data
public class SocialUser {private String access_token;private String remind_in;private long expires_in;private String uid;private String isRealName;
}
修改“com.cwh.gulimall.member.controller.MemberController”类,代码如下:@PostMapping("/oauth2/login")public R oauth2Login(@RequestBody SocialUser socialUser){MemberEntity entity = memberService.login(socialUser);if (entity != null){return R.ok().setData(entity);}else {return R.error(BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getCode(),BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getMsg());}}

修改gulimall_ums.ums_member表结构,sql如下:

ALTER TABLE `gulimall_ums`.`ums_member` 
ADD COLUMN `social_uid` varchar(255) NULL COMMENT '社交用户id' AFTER `create_time`,
ADD COLUMN `access_token` varchar(255) NULL COMMENT '访问token' AFTER `social_uid`,
ADD COLUMN `expires_in` int NULL COMMENT '过期时间戳' AFTER `access_token`;

修改“com.cwh.gulimall.member.entity.MemberEntity”类,新增三个属性,代码如下:

修改“com.cwh.gulimall.member.service.MemberService”类,代码如下:

MemberEntity login(SocialUser socialUser);

修改“com.cwh.gulimall.member.service.impl.MemberServiceImpl”类,代码如下:

@Override
public MemberEntity login(SocialUser socialUser) {
// 1 根据 uid 判断当前用户是否以前用社交平台登录过系统
MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", socialUser.getUid()));
if (!StringUtils.isEmpty(memberEntity)) {// 说明这个用户之前已经注册过MemberEntity update = new MemberEntity();update.setId(memberEntity.getId());update.setAccessToken(socialUser.getAccess_token());update.setExpiresIn(socialUser.getExpires_in());this.baseMapper.updateById(update);memberEntity.setAccessToken(socialUser.getAccess_token());memberEntity.setExpiresIn(socialUser.getExpires_in());return memberEntity;
} else {// 未找到则注册 根据社交平台的开放接口查询用户的开放信息存储到系统MemberEntity register = new MemberEntity();try {Map<String, String> query = new HashMap<>();query.put("access_token", socialUser.getAccess_token());query.put("uid", socialUser.getUid());HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get", new HashMap<>(), query);if (response.getStatusLine().getStatusCode() == 200) {String json = EntityUtils.toString(response.getEntity());JSONObject jsonObject = JSON.parseObject(json);String name = jsonObject.getString("name");String gender = jsonObject.getString("gender");// ......register.setNickname(name);register.setGender("m".equals(gender) ? 1 : 0);// .....}} catch (Exception e) {log.warn("调用微博接口获取信息异常{}", e);}register.setSocialUid(socialUser.getUid());register.setAccessToken(socialUser.getAccess_token());register.setExpiresIn(socialUser.getExpires_in());this.baseMapper.insert(register);return register;
}

小结

Oauth2.0 ;授权通过后,使用 code 换取 access_token ,然后去访问任何开放 API

1 )、 code 用后即毁

2 )、 access_token 在几天内是一样的

3 )、 uid 永久固定

1.3. SpringSession

1.3.1. Session共享问题
1.3.1.1. session原理

jsessionid相当于银行卡,存在服务器的session相当于存储的现金,每次通过jsessionid取出保存的数据。

问题:但是正常情况下session不可跨域,它有自己的作用范围

1.3.1.2. 分布式下session共享问题

  • 同一个服务,复制多份,session不同步问题
  • 不同服务,session不能共享问题
1.3.2. Session共享问题解决
1.3.2.1. session复制

1.3.2.2. 客户端存储

1.3.2.3. hash一致性

1.3.2.4. 统一存储

1.3.2.5. 不同服务,子域session共享

1.3.3. SpringSession整合redis

通过SpringSession修改session的作用域

1.3.3.1. 环境搭建

gulimall-auth-server模块

pom导入依赖

<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
</dependency>

修改apllication.properties配置

spring.session.store-type=redis

主配置类添加注解@EnableRedisHttpSession

修改“com.cwh.gulimall.auth.GulimallAuthServerApplication”类,代码如下:

@EnableRedisHttpSession
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallAuthServerApplication {public static void main(String[] args) {SpringApplication.run(GulimallAuthServerApplication.class, args);}
}
1.3.3.2. 自定义配置
1.3.4. SpringSession核心原理

核心原理:

1)、@EnableRedisHttpSession导入RedisHttpSessionConfiguration.class配置
1、给容器中添加了一个组件
SessionRepository=》》》 【RedisIndexedSessionRepository】=>redis操作session.session的增删改查的封装类
2、SessionRepositoryFilter=》Filter: session存储过滤器,每个请求过来都必须经过filter
1、创建的时候,就自动从容器中获取到了SessionRepository:
2、原生的request,response都被包装。SessionRepositoryRequestWrapper,SessionRepositoryResponseWrapper
3、以后获取session.request.getSession()
4、wrapperedRequest.getSession();===>SressionRepository中获取到

自动延期。redis中的数据也是有过期时间的

装饰者模式 - SessionRepositoryFilter

  • 原生的获取session时是通过HttpServletRequest获取的
  • 这里对request进行包装,并且重写了包装request的getSession()方法
1.3.5. 页面调整
1.3.5.1. 只要登录成功,缓存有用户数据,再点击登录链接,直接调转到首页;把GulimallWebConfig登录页的映射注释掉

修改“com.cwh.gulimall.auth.controller.LoginController”类,代码如下:

@GetMapping("/login.html")
public String loginPage(HttpSession session){
Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);
if (attribute == null) {//没登录return "login";
} else{return "redirect:http://gulimall.com";
}
}
1.3.5.2. 账号密码方式登录也要显示用户名

正常登录也要显示用户名,返回时也要给他放入用户信息

修改“com.cwh.gulimall.auth.controller.LoginController”类,代码如下:

@PostMapping("/login")
public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session) {log.info("登录请求参数:{}", JSON.toJSONString(vo));//远程登录R r = memberFeignService.login(vo);if (r.getCode() == 0) {MemberResponseVO loginUser = r.getData(new TypeReference<MemberResponseVO>() {});// 成功放到session中session.setAttribute(AuthServerConstant.LOGIN_USER, loginUser);return "redirect:http://gulimall.com";} else {Map<String, String> errors = new HashMap<>();errors.put("msg", r.getData("msg", new TypeReference<String>() {}));redirectAttributes.addFlashAttribute("errors", errors);return "redirect:http://auth.gulimall.com/login.html";}
}
1.3.5.3. 只要登陆成功每个页面都显示用户名

gulimall-search服务页面显示用户名,需要先搭建好SpringSession环境

导入依赖

     <!--整合SpringSession完成session共享问题--><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

修改配置

#配置redis
spring.redis.host=192.168.119.127
spring.redis.port=6379
#session存储格式
spring.session.store-type=redis

加注解

添加SpringSession配置类

@Configuration
public class GulimallSessionConfig {@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setDomainName("gulimall.com");cookieSerializer.setCookieName("GULISESSION");return cookieSerializer;}@Beanpublic RedisSerializer<Object> springSessionDefaultRedisSerializer(){return new GenericJackson2JsonRedisSerializer();}
}

1.4. SSO 单点登录

Single Sign On 一处登陆、处处可用

前置概念

1 )、单点登录业务介绍

早期单一服务器,用户认证。

缺点:单点性能压力,无法扩展

分布式,SSO(single sign on)模式

多系统

解决 :

  • 用户身份信息独立管理,更好的分布式管理。
  • 可以自己扩展安全策略
  • 跨域不是问题

缺点:

  • 认证服务器访问压力较大。

gitee参考项目:xxl-sso: 一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性;。现已开放源代码,开箱即用。

xxl-sso流程:

  • /xxl-sso-server 登录服务器 8080 ssoserver.com
  • /xxl-sso-web-sample-springboot 项目1 8081 client1.com
  • /xxl-sso-web-sample-springboot 项目2 8082 client2.com
#----------sso----------
127.0.0.1 ssoserver.com
127.0.0.1 client1.com
127.0.0.1 client2.com

核心:三个系统即使域名不一样,想办法给三个系统同步同一个用户的票据;

1)、中央认证服务器;ssoserver.com

2)、其他系统,想要登录去ssoserver.com登录,登录成功跳转回来

3)、只要有一个登录,其他都不用登录

4)、全系统统一一个sso-sessionid;所有系统可能域名都不相同

相关文章:

微服务实战——登录(普通登录、社交登录、SSO单点登录)

登录 1.1. 用户密码 PostMapping("/login")public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session){R r memberFeignService.login(vo);if(r.getCode() 0){MemberRespVo data r.getData("data", new Type…...

windows 安装 ElasticSearch

1、下载安装包 下载地址&#xff1a;https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.14.3-windows-x86_64.zip ElasticSearch 目录结构如下&#xff1a; 2、配置JDK环境 ES比较耗内存&#xff0c;建议虚拟机4G或以上内存&#xff0c;jvm1g以上的内存分…...

Oracle Linux 9 (CentOS Stream 9) 安装 node.js 20

Oracle Linux 的 node 默认版本为 16&#xff0c;运行dnf update也无法改变大版本&#xff0c;还需要进行额外操作1 查看支持的版本 sudo dnf module list nodejs输出如下 Last metadata expiration check: 3:37:22 ago on Fri 11 Oct 2024 09:08:18 PM JST. Oracle Linux 9 Ap…...

【Axure安装包与汉化包附带授权证书】

一、下载Axure安装包与汉化包附带授权证书 1.下载汉化包 【快传】: 点击链接即可保存 2.解压安装包 解压下载好的压缩包&#xff0c;能看到有lang也就是汉化包&#xff0c;AxureRP-Setup-RC.exe 也就是Axure9的安装程序&#xff0c;以及汉化说明和授权码。 二、安装Axure9…...

SSH隧道验证的原理及实现例子

SSH 隧道验证原理详解 **SSH 隧道&#xff08;SSH Tunneling&#xff09;**是通过 SSH 协议将数据在客户端和服务器之间加密传输的一种技术。它可以在不安全的网络上创建一个安全的、加密的通道&#xff0c;用于传输各种数据&#xff0c;例如通过不安全的网络远程登录、传输文…...

[计算机视觉]chapter1

一、什么是计算机视觉 计算机视觉就是用计算机编程,并设计算法来理解在这些图像中有什么。计算机视觉是一门研究如何使机器“看”的科学,更进一步的说,就是是指用摄影机和电脑代替人眼对目标进行识别、跟踪和测量等机器视觉,并进一步做图形处理,使电脑处理成为更适合人眼…...

RTKLIB学习记录【postpos、execses_b、execses_r】

本文主要记录对RTKLIB源码中postpos、execses_b、execses_r 函数的源码解读&#xff0c;不涉及其中的天线、星历等文件读取的内容&#xff0c;且为个人理解&#xff0c;如果有误&#xff0c;欢迎交流讨论。 一、postpos 函数部分 /rxn2rtkp函数 → postpos函数传递参数&#x…...

docker,docker-desktop,docker-compose download

docker docker-compose download 百度网盘获取离线包链接release-notes 参考dockerdocker-composewlspowershell...

C#_带参数的委托进入队列执行

我们经常会遇到一些函数多个地方调用,但是只能单独执行的就需要把它放到队列中执行。 1.创建对应该方法的委托(传参和回参类型需要一致)。 //委托: public delegate void CameraTaskDelegate(byte cs, ref byte[] buffer);//对应函数: public void CameraSettingRead(by…...

【OpenCV】(二)—— 图片读取展示和保存

上一小节中我们成功安装了opencv&#xff0c;我们这次学习使用opencv最基础的功能&#xff0c;读取和展示图片&#xff0c;首先准备一张用于实验的样例图片【cat.jpg】如下&#xff1a; 然后就是创建一个python项目并导入相关依赖 import cv2读取图片 读取图片使用imread方法…...

【花卉识别系统】Python+卷积神经网络算法+人工智能+深度学习+图像识别+算法模型

一、介绍 花朵识别系统。本系统采用Python作为主要编程语言&#xff0c;基于TensorFlow搭建ResNet50卷积神经网络算法模型&#xff0c;并基于前期收集到的5种常见的花朵数据集&#xff08;向日葵、玫瑰、蒲公英、郁金香、菊花&#xff09;进行处理后进行模型训练&#xff0c;最…...

k8s、prometheus、grafana数据采集和展示的链路流程

k8s集群中&#xff0c;容器级别的数据采集是由cAdvisor程序实现 cAdvisor # Container Advisor 容器顾问 cAdvisor程序是kubelet组件的一部分。 每个节点&#xff0c;包括master节点&#xff0c;都有一个kubelet系统服务&#xff0c; kukelet负责管理pod和容…...

sentinel dashboard改造落地设计实现解释(一)-分布式fetcher和metrics存储/搜索

背景 微服务是目前java主流架构,微服务架构技术栈有,服务注册中心,网关,熔断限流,服务同学,配置中心等组件,其中,熔断限流主要3个功能特性,限流,熔断,快速失败。Sentinel是阿里开源的熔断限流组件,sentinel dashboard是演示级别,表现在metrics采集是单机版,metri…...

LabVIEW提高开发效率技巧----时序分析

一、什么是时序分析&#xff1f; 时序分析是优化LabVIEW程序性能的重要步骤。它通过分析程序各个部分的执行时间&#xff0c;帮助开发者找到程序运行中的瓶颈&#xff0c;并进行有针对性的优化。在LabVIEW中&#xff0c;Profile Performance and Memory工具是进行时序分析的关…...

python不用ide也能进行调试

import pdb pdb.set_trace()import pdb 和 pdb.set_trace() 是 Python 中用于调试代码的工具。以下是它们的具体含义和用法&#xff1a; import pdb pdb 是 Python 的内置调试器模块&#xff0c;允许开发者在运行时进行代码调试。 通过 import pdb 语句&#xff0c;你可以引入…...

Django学习笔记之Django基础学习

Django笔记 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录…...

smartctl 设置硬盘的 write-caching

sg3 一、sg3查看缓存状态 您可以使用sg_modes命令来查看SAS盘和SATA盘的缓存状态。例如&#xff0c;要查看/dev/sdb设备的缓存状态&#xff0c;您可以执行以下命令&#xff1a; sg_modes -p 8,0 /dev/sdb 二、sg3关闭机械盘写缓存状态&#xff08;仅适用于SAS盘&#xff09…...

【Spring AI】Java实现类似langchain的向量数据库RAG_原理与具体实践

介绍一下RAG&#xff1a; 检索增强生成&#xff08;RAG&#xff09;是一种技术&#xff0c;它结合了检索模型和生成模型来提高文本生成的质量。通过从企业私有或专有的数据源中检索相关信息&#xff0c;并将这些信息与大型语言模型相结合&#xff0c;RAG能够显著减少模型产生幻…...

linux下使用systemctl设置开机自动运行程序

本文介绍在Linux下&#xff0c;使用systemctl设置开机自动运行程序&#xff0c;实现创建一个systemd服务单元文件&#xff0c;并启用该服务的方法。 1、创建.service文件 在/etc/systemd/system/目录下创建一个以.service结尾的文件&#xff0c;例如myapp.service&#xff1a…...

复位电路的亚稳态

复位导致亚稳态的概念&#xff1a; 同步电路中&#xff0c;输入数据需要与时钟满足setup time和hold time才能进行数据的正常传输&#xff08;数据在这个时间段内必须保持不变&#xff1a;1不能变为0&#xff0c;0也不能变为1&#xff09;&#xff0c;防止亚稳态&#xff1b; …...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态&#xff0c;这是一个可以多选的控件。 二、属性 其实功能大差不差&#xff0c;除了特殊的几个外&#xff0c;与button基本相同&#xff0c;所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...

Appium下载安装配置保姆教程(图文详解)

目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...

Springboot 高校报修与互助平台小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;高校报修与互助平台小程序被用户普遍使用&#xff0c;为…...