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

论坛项目之用户部分

注册接口

实现思路

1.特殊字段检查(比如性别没有给出需要给出默认值)

2.对比检查两次输入的密码是否一致,不一致报错

3.利用UUID生成随机‘盐’值,并使用密码进行MD5加密后与‘盐’进行拼接,生成加密后的密码

4.创建User对象并在数据库中查询该User对象是否存在,存在则报错

5.补充User对象的其他信息(文章数量、用户状态、用户删除状态、注册时间等)

6.使用insert方法将用户写入数据库,返回方法执行结果

实例代码

Contorller

@PostMapping("/register")
@ApiOperation("注册新用户(普通)的方法")public AppResult register(@RequestParam("username")@NonNull @ApiParam(value = "用户名") String username, @RequestParam("nickname")@NonNull @ApiParam(value = "昵称") String nickname, @RequestParam(value = "gender",required = false)@ApiParam(value = "性别") Byte gender , @RequestParam("password")@NonNull @ApiParam(value = "密码")  String password, @RequestParam("passwordRepeat") @NonNull @ApiParam(value = "确认密码")  String passwordRepeat){//测试数据的有效性if(gender==null||gender<0||gender>2){//如果错误,我们将性别信息进行清空gender=2;}//判断密码和确认密码是否相同if(!password.equals(passwordRepeat)){log.error(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME));}//对密码进行加密String salt = UUIDUtils.UUID_32();String newPassword = MD5Utils.md5Salt(password, salt);//将所有字段信息储存User user = new User();user.setUsername(username);user.setNickname(nickname);user.setGender(gender);user.setPassword(newPassword);user.setSalt(salt);userService.createCommonUser(user);return AppResult.success("用户新增成功!");}

Service

public void createCommonUser(User user) {//空指针排除if(user==null){//日志记录错误信息log.error("输入的用户信息不存在");throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//从数据库中查询是否存在该数据User checkUser = userMapper.selectByUsername(user.getUsername());//存在抛出并记录日志/if(checkUser !=null){//记录日志log.error(ResultCode.FAILED_USER_EXISTS.toString()+"name="+checkUser.getUsername());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode. FAILED_USER_EXISTS));}//不存在则填充并插入数据,之后返回结果//补充结果if(user.getGender()==null) {//设置默认的性别user.setGender((byte) 2);}//设置其他值//设置发帖数量user.setPhoneNum("");user.setArticleCount(0);//设置是否为管理员user.setIsAdmin((byte) 0);//设置状态user.setState((byte) 0);//设置是否删除user.setDeleteState((byte) 0);//设置创建时间Date date = new Date();user.setCreateTime(date);user.setUpdateTime(date);//查看返回结果int result = userMapper.insertSelective(user);log.info("result="+result);if(result!=1){//记录错误日志log.error(ResultCode.FAILED_CREATE.toString());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}//最终记录成功日志log.info("注册用户成功:"+user.getUsername());}

登录接口

实现思路

1.使用@NonNull注解确保账号密码不为空

2.从数据库中查询是否存在该数据,如果不存在直接报错

3.从数据库中取出对应数据的‘盐’值,使用输入用户对应的密码进行MD5加密后使用该‘盐’进行拼接,之后与数据库中的密码进行比对是否相等,不相等直接报错

4.登录成功后建立对应的session,并设置session对应的属性作为我们后续检查是否登录的依据(session.setAttribute(AppConfig.USER_SESSION, loginUser)

实例代码

Controller

  @ApiOperation("登录方法")@PostMapping("/login")public AppResult login(HttpServletRequest request, @ApiParam(value = "用户名") @RequestParam(value = "username")@NonNull String username, @ApiParam(value = "密码")@RequestParam(value = "password")@NonNull String password){//调用service登录方法User loginUser = userService.login(username, password);//存储sessionHttpSession session=request.getSession(true);session.setAttribute(AppConfig.USER_SESSION, loginUser);//返回结果return AppResult.success("登录成功",loginUser);}

Service

 @Overridepublic User login(String username, String password) {//判断账号密码是否为空if(StringUtils.isEmpty(username)&&StringUtils.isEmpty(password)){//打印错误的日志信息log.error(ResultCode.ERROR_IS_NULL.toString());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//从数据库中查询数据User user = selectByUsername(username);if(user==null){//记录日志并抛出异常//数据库中没有该用户记录则直接报错//为了提高数据库的安全性,即使用户不存在,我们也返回账号或密码错误log.error(ResultCode.FAILED_LOGIN.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));}//查询到比对密码String truePassword=user.getPassword();//对密码进行md5加密String repeatPassword= MD5Utils.md5Salt(password, user.getSalt());if(!repeatPassword.equals(truePassword)){//记录错误日志log.error(ResultCode.FAILED_LOGIN.toString());//密码错误返回报错信息throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));}//密码相同登陆成功,返回用户信息log.info("用户登录成功!");return user;}

退出登录接口

实现思路

1.通过HttpServletRequest获取session对象

2.将session对象中将我们此前设置的属性值去除

3.将我们设置的session对象设置无效化(invalidate),并进行页面跳转

实例代码

controller

@ApiOperation("用户退出方法")@GetMapping("/logout")public AppResult logout(HttpServletRequest request){//检查session是否有效HttpSession session = request.getSession(false);if(session==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}//去除sessionObject user = session.getAttribute(AppConfig.USER_SESSION);log.info("用户退出"+user);session.invalidate();//返回结果return AppResult.success("用户退出成功.");}

查看用户信息接口

实现思路

1.根据前端传来的参数中是否包括id来判断当前需要显示的信息是对应文章的作者信息还是当前登录的用户信息

2.如果是当前登录的用户,直接在session中根据键获取对应的值(当前登录的用户),将这个信息直接返回给前端即可

3.如果是对应文章的用户,我们需要根据主键从数据库中查询信息并将该信息返回

实例代码

controller

 @GetMapping("/info")@ApiOperation("展示用户信息的方法")public AppResult userInfo(HttpServletRequest request ,@ApiParam(value = "用户id")@RequestParam(value = "id" ,required = false) Long id){//判断是否存在id//不存在id返回当前登录的用户信息if(id==null){//获取sessionHttpSession session = request.getSession(false);//session为null说明用户未登录if(session==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}User user = (User)session.getAttribute(AppConfig.USER_SESSION);if(user==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}return AppResult.success("用户查询成功!",user);}//存在id返回指定id的用户else{User user = userService.selectByPrimaryKey(id);if(user==null){log.error(ResultCode.FAILED_USER_NOT_EXISTS.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}return AppResult.success("用户查询成功",user);}}

service

  @Overridepublic User selectByPrimaryKey(Long id) {//判断id是否为空if(id==null){log.error(ResultCode.ERROR_IS_NULL.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//调用方法return userMapper.selectByPrimaryKey(id);}

修改用户信息接口

实现思路

1.通过当前session获取当前登录的用户与需要修改信息的用户id进行比对判断是否有权进行信息的修改

2.有权进行休息的修改则调用service进行信息的修改,其中在service中对需要修改的字段进行设置,最后调用mapper对应的selective方法进行数据处理

实例代码

controller

  @ApiOperation("修改用户个人信息的方法!")@PostMapping("/modify")public AppResult modifyInfo (HttpServletRequest request,@ApiParam("用户Id") @RequestParam("id") @NonNull Long id,@ApiParam("性别") @RequestParam(value = "gender", required = false) Byte gender,@ApiParam("昵称") @RequestParam(value = "nickname", required = false) String nickname,@ApiParam("电话号码") @RequestParam(value = "phoneNum", required = false) String phoneNum,@ApiParam("邮箱") @RequestParam(value = "email", required = false) String email,@ApiParam("个人简介") @RequestParam(value = "remark", required = false) String remark) {// 校验if (gender == null&& StringUtils.isEmpty(nickname)&& StringUtils.isEmpty(phoneNum)&& StringUtils.isEmpty(email)&& StringUtils.isEmpty(remark)) {// 参数同时为空时返回错误信息return AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE.toString());}// 校验传入的Id是否为当前登录用户HttpSession session = request.getSession();User user = (User) session.getAttribute(AppConfig.USER_SESSION);if (user.getId() != id) {// 返回错误return AppResult.failed(ResultCode.FAILED_UNAUTHORIZED.toString());}// 调用serviceuserService.modifyInfo(id, gender, nickname, phoneNum, email, remark);// 重新获取用户信息,更新sessionuser = userService.selectByPrimaryKey(id);session.setAttribute(AppConfig.USER_SESSION, user);// 返回结果return AppResult.success();

service

 @Overridepublic void modifyInfo(Long id, Byte gender, String nickname, String phoneNum, String email, String remark) {// 非空校验,id为null 或 其他的参数全部为nullif (id == null || (gender == null&& StringUtils.isEmpty(nickname)&& StringUtils.isEmpty(phoneNum)&& StringUtils.isEmpty(email)&& StringUtils.isEmpty(remark))) {log.warn(ResultCode.ERROR_IS_NULL.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}// 校验用户状态User user = userMapper.selectByPrimaryKey(id);if (user == null || user.getDeleteState() == 1) {log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 构造一个修改对象User updateUser = new User();// 设置IdupdateUser.setId(id);// 设置昵称if (!StringUtils.isEmpty(nickname)) {updateUser.setNickname(nickname);}// 设置电话if (!StringUtils.isEmpty(phoneNum)) {updateUser.setPhoneNum(phoneNum);}// 设置邮箱if (!StringUtils.isEmpty(email)) {updateUser.setEmail(email);}// 个人简介if (!StringUtils.isEmpty(remark)) {updateUser.setRemark(remark);}// 性别if (gender != null && gender >= 0 && gender <= 2) {updateUser.setGender(gender);}// 调用DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {log.warn(ResultCode.ERROR_UPDATE.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_UPDATE));}}

修改密码接口

实现思路

1.通过session获得当前登录的用户,并判断是否有权修改对应id用户的密码(id是否相等)

2.判断输入的新密码和重复密码是否相等

3.进入service通过id从数据库中查看并判断当前用户是否存在

4.获取对应用户的salt并使用md5对输入的原密码加密并与之拼接后再与数据库中的原密码进行比对,判断输入的原密码是否正确

5.上述比对全部通过之后生成新的salt,将密码加密后进行存储

实例代码

controller

@ApiOperation("修改密码的方法")
@PostMapping("/modifyPwd")public AppResult modifyPassword(HttpServletRequest request,@NonNull@RequestParam(value = "id")@ApiParam(value = "用户id") Long id,@NonNull@RequestParam("oldPassword")@ApiParam(value = "用户的旧密码") String oldPassword,@NonNull@RequestParam("newPassword")@ApiParam(value = "新密码") String newPassword,@NonNull @RequestParam("passwordRepeat")@ApiParam(value = "重复密码") String passwordRepeat){//判断当前用户是否登录,没有登录直接报错HttpSession session = request.getSession(false);if(session==null){log.error(ResultCode.USER_NOT_LOG.toString());throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}User loginUser =(User) session.getAttribute(AppConfig.USER_SESSION);if(loginUser==null){log.error(ResultCode.USER_NOT_LOG.toString());throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}//登录之后判断当前用户是否有权修改密码//无权直接报错if(loginUser.getId()!=id){log.error(ResultCode.FAILED_UNAUTHORIZED.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_UNAUTHORIZED));}//判断两次密码是否一致if(!newPassword.equals(passwordRepeat)){//密码不一致进行报错log.error(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME));}//密码一致则进行修改信息userService.modifyPassword(id, oldPassword, newPassword, passwordRepeat);log.info("密码修改成功,"+loginUser.getUsername());return AppResult.success("密码修改成功");}

service

public void modifyPassword(Long id, String oldPassword, String newPassword, String passwordRepeat) {//判断id对应的用户是否存在User checkUser = userMapper.selectByPrimaryKey(id);//用户不存在直接报错if(checkUser==null){//记录错误信息log.error(ResultCode.FAILED_USER_NOT_EXISTS.toString());//进行报错throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}//如果用户存在更新信息//判断原密码和输入的原密码是否相同,不相同直接报错//对输入的密码进行加密String oldSalt = checkUser.getSalt();String realOldPassword = MD5Utils.md5Salt(oldPassword, oldSalt);if(!realOldPassword.equals(checkUser.getPassword())){log.error(ResultCode.FAILED_PASSWORD.toString());//报错throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PASSWORD));}//如果相同继续修改//创建对象并修改User user = new User();//生成加密字符String salt = UUIDUtils.UUID_32();//进行密码加密String realPassword = MD5Utils.md5Salt(newPassword, salt);//将salt存入user.setSalt(salt);user.setPassword(realPassword);user.setId(id);//修改个人信息int result = userMapper.updateByPrimaryKeySelective(user);if(result!=1){log.error(ResultCode.ERROR_UPDATE.toString());AppResult.failed(ResultCode.ERROR_UPDATE);}//生成修改成功的日志log.info("用户密码修改成功!" );}

相关文章:

论坛项目之用户部分

注册接口 实现思路 1.特殊字段检查&#xff08;比如性别没有给出需要给出默认值&#xff09; 2.对比检查两次输入的密码是否一致&#xff0c;不一致报错 3.利用UUID生成随机‘盐’值&#xff0c;并使用密码进行MD5加密后与‘盐’进行拼接&#xff0c;生成加密后的密码 4.创建U…...

golang内存对齐

为什么要内存对齐&#xff1f; CPU访问内存时&#xff0c;以CPU的位数为单位进行访问。 如果访问未对齐的内存&#xff0c;处理器需要做两次内存访问&#xff0c;对齐的内存的访问可能仅需要一次&#xff0c;利用内存对齐后提升读取速度。 golang结构体内存对齐规则 在代码编译…...

【CheatSheet】Python、R、Julia数据科学编程极简入门

《Python、R、Julia数据科学编程极简入门》PDF版&#xff0c;是我和小伙伴一起整理的备忘清单&#xff0c;帮助大家10分钟快速入门数据科学编程。 另外&#xff0c;最近 TIOBE 公布了 2023 年 8 月的编程语言排行榜。 Julia 在本月榜单中实现历史性突破&#xff0c;成功跻身 …...

【golang】怎样判断一个变量的类型?

怎样判断一个变量的类型&#xff1f; package mainimport "fmt"var container []string{"zero", "one", "two"} func main() {container : map[int]string{0: "zero", 1: "one", 2: "two"}fmt.Printf…...

怎么学习AJAX相关技术? - 易智编译EaseEditing

学习AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;相关技术可以让你实现网页的异步数据交互&#xff0c;提升用户体验。以下是一些学习AJAX技术的步骤和资源&#xff1a; HTML、CSS和JavaScript基础&#xff1a; 首先&#xff0c;确保你已经掌握了基本的HTML…...

JDK、JRE、JVM:揭秘Java的关键三者关系

文章目录 JDK&#xff1a;Java开发工具包JRE&#xff1a;Java运行环境JVM&#xff1a;Java虚拟机关系概述 案例示例&#xff1a;Hello World结语 在Java世界中&#xff0c;你可能经常听到JDK、JRE和JVM这几个概念&#xff0c;它们分别代表了Java开发工具包、Java运行环境和Java…...

【reactNative混合安卓开发~使用问题持续更】

reactNative混合安卓开发 reactNative开发移动端reactNative界面开发前端init.bat文件部分组件第三方组件解析1、定义theme主题shopify/restyle&#xff1b;菜单导航react-navigation/drawer、react-navigation/native&#xff1b; RN问题记录1、使用theme.js写的公共组件报错&…...

OCR的发明人是谁?

OCR的发明背景可以追溯到早期计算机科学和图像处理的研究。随着计算机技术的不断发展&#xff0c;人们开始探索如何将印刷体文字转换为机器可读的文本。 OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;的发明涉及多个人的贡献&#xff0c…...

笔记本电脑连上WiFi之后的IP为什么会变?如何让它不变固定住?

笔记本连上WiFi后获取IP地址的过程&#xff0c;通常是通过DHCP (动态主机配置协议) 来完成的。默认情况下&#xff0c;DHCP会根据连接设备和网络状态动态地分配IP地址&#xff0c;因此你会看到IP地址可能经常改变。 如果你希望电脑的IP地址固定&#xff0c;可以尝试设置静态IP…...

【数学建模】--因子分析模型

因子分析有斯皮尔曼在1904年首次提出&#xff0c;其在某种程度上可以被看成时主成分分析的推广和扩展。 因子分析法通过研究变量间的相关稀疏矩阵&#xff0c;把这些变量间错综复杂的关系归结成少数几个综合因子&#xff0c;由于归结出的因子个数少于原始变量的个数&#xff0c…...

RAM不够?CUBEIDE使用CCMRAM

RAM不够&#xff1f;使用CCMRAM 文章目录 RAM不够&#xff1f;使用CCMRAM打开连接LD文件&#xff1a;添加代码添加标识宏使用 打开连接LD文件&#xff1a; 添加代码 在SECTIONS段最后加上下面代码&#xff1a; _siccmram LOADADDR(.ccmram); /* CCM-RAM section * * IMPORTAN…...

npm ERR! code ERESOLVEnpm ERR! ERESOLVE unable to resolve dependency tree

拉取项目到本地 执行 npm install 报错 遇到这个问题首先确认的就是版本是不是太高了&#xff0c;降一下版本。或者通过yarn命令替代npm install命令安装&#xff0c;同理&#xff0c;启动也可以采用yarn dev 启动代替npm run dev 下面教大家用一个NVM工具&#xff0c;这个工…...

使用 prometheus client SDK 暴露指标

目录 1. 使用 prometheus client SDK 暴露指标1.1. How Go exposition works1.2. Adding your own metrics1.3. Other Go client features 2. Golang Application monitoring using Prometheus2.1. Metrics and Labels2.2. Metrics Types2.2.1. Counters:2.2.2. Gauges:2.2.3. …...

Jmeter之BeanShell取出参数进行四则运算,并判断是否正确

首先调用余额接口&#xff0c;使用正则提取响应中的余额字段&#xff0c;记作变量acctBal1做支付交易再次调用余额接口&#xff0c;使用正则提取响应中的余额字段&#xff0c;记作变量acctBal2最后在结果树中可以看到断言错误的信息&#xff0c;断言正确时没有提示以下是beansh…...

PYTHON 斗地主发牌 (简易版)

利用方法&#xff1a; 1. random.randint( ) 随机抽取数字 方法 2.random.sample((抽取范围的参数),(抽取的个数)) 返回的是列表 所以用[0]可以输出里面的元素 import random# 1. 创建牌 # 花色 color ["\u2660", "\u2663", "\u2665", "\…...

CSS文本裁剪

对于单行文本裁剪&#xff1a; span {text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block; } 对于多行文本裁剪&#xff1a; 在文本容器上定义 CSS Flexbox 属性 display: -webkit-box; 定义要显示的文本行数 -webkit-line-clamp: 4; 添加 -webkit-…...

ClickHouse常见的引擎和使用

1.日志引擎 日志引擎特点 1.数据存储在磁盘上 2.写入时将数据追加在文件末尾 3.不支持突变操作 4.不支持索引 5.非原子地写入数据 6.引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作 建表语法示例 CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( …...

构建之法 - 软件工程实践教学:一线教师的13问

福州大学单红老师的软工课程总结 2020春&#xff0c;不一样的学期不一样的软工实践 单红⽼师在总结中&#xff0c;提出了13条疑惑&#xff0c;《构建之法》的作者邹欣⽼师就单红⽼师提出的每⼀条疑惑&#xff0c;给出了⾃⼰的思考&#xff0c;与他进⾏探讨交流。欢迎你也来参与…...

联调 matlab 遇到的一些事儿

记录当时遇到的问题&#xff0c;因为平时不写 matlab&#xff0c;所以没有深入的理解。 版本兼容 当时遇到的第一个问题就是不同版本 matlab 带来的兼容性问题。同时开发使用的是 2021a 版本&#xff0c;而调试时使用的是 2022b 版本。在新版本中某些函数已被弃用&#xff0c…...

时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 1.Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 2.单变量时间序列预测; 3.多指标评价,评价指标包括:R2、MAE、MBE等,代码质量极高…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...