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

登录的几种方式

使用Session完成登录

1. 手机号发送验证码

逻辑步骤:
  1. 校验手机号格式是否正确。
  2. 生成验证码(例如使用Hutool工具类)。
  3. 将手机号和验证码存入Session。
  4. 返回验证码发送成功的响应。

2. 用户登录逻辑

逻辑步骤:
  1. 从Session中获取存储的手机号和验证码。
  2. 校验前端传来的手机号和验证码是否与Session中一致。
  3. 如果一致,根据手机号查询用户是否存在。
    • 如果不存在,创建新用户并随机生成用户名。
  4. 将用户信息存入Session。
package com.hmdp.service.impl;import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpSession;import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** <p>* 服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail("手机号格式错误");}// 生成验证码String code = RandomUtil.randomNumbers(6);// 保存验证码到Sessionsession.setAttribute("code",code);session.setAttribute("phone",phone);//TODO 发送验证码 需要调用第三方log.debug("发送验证码成功,验证码{}",code);// 返回成功return Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute("phone"))) {return Result.fail("手机号和之前的不同");}// 校验码不一致,报错if (!session.getAttribute("code").equals(loginForm.getCode())) {return Result.fail("验证码不正确");}// 一致,根据手机号查询用户User user = query().eq("phone", loginForm.getPhone()).one();if (user==null) {// 用户不存在 创建新的用户 保存用户到数据库,保存用户到Sessionuser = createUserWithPhone(loginForm.getPhone());}// 用户存在,直接保存用户到Sessionsession.setAttribute("user",user);return Result.ok();}private User createUserWithPhone(String phone) {User user = new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;}
}

3. 登录校验拦截器

逻辑步骤:
  1. 拦截所有需要登录验证的请求。
  2. 检查Session中是否存在user对象。
  3. 如果不存在,返回未登录的错误信息;否则将user信息转换为只含有id,昵称和头像地址的类之后(保护用户隐私信息)存入TreadLocal当中,并且放行。
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object user = request.getSession().getAttribute("user");if (user == null) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("未登录,请先登录");return false;}// 将用户信息存入 ThreadLocal // 为了保护用户的隐私需要专门设置一个类只存储用户的昵id,称和头像地址UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);UserContext.setUser(userDTO );return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理 ThreadLocal 防止内存泄漏UserContext.clear();}
}

 UserContext 工具类:

public class UserContext {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();}
}

还需要在MvcConfig当中配置拦截器

package com.hmdp.config;import com.hmdp.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","/blog/hot","/shop/**","/shop-type/**","/voucher/**").order(0);}
}

session 在服务器端有默认的时长(过期时间),这是由服务器配置决定的。默认情况下,Session 的有效期会受到服务器设置的影响,而无需手动设置时长。如果需要自定义时长,可以进行配置。 (默认值

在大多数 Servlet 容器(如 Tomcat、Jetty)中,Session 的默认超时时间是 30分钟

这个时间表示,如果用户在 30 分钟内没有访问服务器,Session 会被销毁。)

基于Redis代替Session登录

问题Session 是存储在服务器内存中的,默认情况下每个服务器实例维护自己的 Session 数据。在分布式系统中,不同的请求可能被分配到不同的服务器实例,从而导致无法访问原始 Session。 

虽然 Session 使用方便,但在分布式、高并发、跨平台场景下,其缺点可能带来较大的限制。因此,很多现代应用倾向于采用 无状态认证(如 JWT) 或集中式存储方案(如 Redis)来代替传统的 Session。选择方案时需要根据业务需求、系统架构和可接受的复杂性权衡决定。

1. 手机号发送验证码

逻辑:
  • 校验手机号是否规范。
  • 使用 Hutool 工具生成验证码。
  • 将验证码存入 Redis,设置过期时间为 2 分钟。

2. 用户登录逻辑

逻辑:
  1. 从 Redis 获取验证码,并与前端提交的验证码比对。
  2. 根据手机号查询用户,不存在则创建新用户。
  3. 生成登录令牌(token),将用户信息转换为 Hash 并存入 Redis,设置有效期为 30 分钟。
  4. 返回 token 给前端。
package com.hmdp.service.impl;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpSession;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** <p>* 服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
@Slf4j
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {final private StringRedisTemplate stringRedisTemplate;@Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail("手机号格式错误");}// 生成验证码String code = RandomUtil.randomNumbers(6);/*// 保存验证码到Sessionsession.setAttribute("code",code);session.setAttribute("phone",phone);*/// 存储到Redis中stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);//TODO 发送验证码 需要调用第三方log.debug("发送验证码成功,验证码{}",code);// 返回成功return Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {/*// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute("phone"))) {return Result.fail("手机号和之前的不同");}// 校验码不一致,报错if (!session.getAttribute("code").equals(loginForm.getCode())) {return Result.fail("验证码不正确");}*///String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + loginForm.getPhone());if(code == null || ! code.equals(loginForm.getCode())){return Result.fail("验证码不正确或者手机号错误");}// 一致,根据手机号查询用户User user = query().eq("phone", loginForm.getPhone()).one();if (user==null) {// 用户不存在 创建新的用户 保存用户到数据库,保存用户到Sessionuser = createUserWithPhone(loginForm.getPhone());}// 用户存在,直接保存用户到Session
//        session.setAttribute("user",user);// 保存到Redis中 以hash模式存储// 随机生成一个token作为登录令牌String token  = UUID.randomUUID().toString(true);// 将User对象转为UserDTO 再以token为key,Hash形式存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);// 将userDTO转换为mapMap<String, Object> Usermap = BeanUtil.beanToMap(userDTO,new HashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)-> fieldValue.toString()));stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY +token,Usermap);// 设置有效期stringRedisTemplate.expire(LOGIN_USER_KEY+token,LOGIN_USER_TTL,TimeUnit.MINUTES);// 返回tokenreturn Result.ok(token);}private User createUserWithPhone(String phone) {User user = new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;}
}

3. 登录拦截器

逻辑:
  1. 从请求头中获取 token
  2. 使用 token 从 Redis 获取用户信息。
  3. 如果用户信息为空,拦截请求。
  4. 将用户信息保存到 ThreadLocal
  5. 刷新 token 的有效期。

 但是如果我们还是只在登录的拦截器当中刷新token的有效值,那么就只会在局部范围内保证token有效。而不是全局范围内,保证用户的token不会过期。

所以我们需要加一层 加一层拦截器(RefreshTokenInterceptor),虽然说是拦截器,但是他不进行拦截操作,拦截操作还是有LoginInterceptor进行拦截。

什么只在 LoginInterceptor 中刷新 token 不够?

局限性

LoginInterceptor 只对需要登录的接口进行拦截。如果用户只访问公开页面或非登录接口(如 /home/shop 等),这些请求不会经过 LoginInterceptor,导致 token 无法刷新。

如果用户长时间浏览公开页面后访问需要登录的页面,可能因 token 过期被迫重新登录,影响用户体验。

全局活跃性保证

用户访问任何页面都应该被视为活跃状态,无论页面是否需要登录,都需要刷新 token 的有效期。单独依赖 LoginInterceptor 只能保证在局部范围(需要登录的接口)内刷新 token

为什么需要 RefreshTokenInterceptor?

  • RefreshTokenInterceptor 的目的是在全局范围内检测 token 并刷新其有效期。
  • 它负责在所有请求(无论是否需要登录)中检查 token,并且将用户保存到TreadLocal当中,但不进行登录状态的校验。
  • 真正的拦截操作(判断用户是否登录)仍由 LoginInterceptor 执行。(LoginInterceptor 可以查看ThreadLocal中是否存在user就可以判断是否登录了)

RefreshTokenInterceptor的代码: 

package com.hmdp.Interceptor;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;
import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;@RequiredArgsConstructor
public class RefreshTokenInterceptor implements HandlerInterceptor {final StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 从请求头当中获取tokenString token = request.getHeader("authorization");//如果 string token =  "" ;  这个 token != null,而是 长度为0。所以不可以直接用 == nullif (StrUtil.isBlankIfStr(token)) {response.setStatus(401);return true;}String key = LOGIN_USER_KEY + token;// 从Redis获取用户Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);// 判断userMapif (userMap.isEmpty()) {response.setStatus(401);return true;}// 将userMap转换为BeanUserDTO userDTO= BeanUtil.fillBeanWithMap(userMap, new UserDTO(),false);
//        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);// 保存到ThreadLocal里面UserHolder.saveUser(userDTO);// 刷新token的有效期stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);return  true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}

LoginInterceptor拦截器代码: 

package com.hmdp.Interceptor;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 判断是否需要拦截也就是TreadLocal当中是否存在user
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {UserDTO userDTO = UserHolder.getUser();if (userDTO == null) {response.setStatus(401);return  false;}// 有用户放行return  true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}

MvcConfig配置 

package com.hmdp.config;import com.hmdp.Interceptor.LoginInterceptor;
import com.hmdp.Interceptor.RefreshTokenInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class MvcConfig implements WebMvcConfigurer {final StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截所有 执行顺序默认都是0,按照添加顺序执行,指定Order,越小越先执行// token刷新拦截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0);// 拦截部分请求registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","blog/hot","/shop/**","/shop-type/**","/voucher/**").order(1);}
}

MvcConfig作为Spring管理的Bean,可以通过构造注入或字段注入获取StringRedisTemplate。由于拦截器实例是手动创建的,MvcConfig需要将StringRedisTemplate显式传递给LoginInterceptor的构造方法。

相关文章:

登录的几种方式

使用Session完成登录 1. 手机号发送验证码 逻辑步骤&#xff1a; 校验手机号格式是否正确。生成验证码&#xff08;例如使用Hutool工具类&#xff09;。将手机号和验证码存入Session。返回验证码发送成功的响应。 2. 用户登录逻辑 逻辑步骤&#xff1a; 从Session中获取存…...

Scala_【5】函数式编程

第五章 函数式编程函数和方法的区别函数声明函数参数可变参数参数默认值 函数至简原则匿名函数高阶函数函数作为值传递函数作为参数传递函数作为返回值 函数闭包&柯里化函数递归控制抽象惰性函数友情链接 函数式编程 面向对象编程 解决问题时&#xff0c;分解对象&#xff…...

解析 World Football Cup 问题及其 Python 实现

问题描述 本文讨论一道关于足球锦标赛排名规则的问题&#xff0c;来自 Berland 足球协会对世界足球规则的调整。题目要求对给定的比赛数据进行计算&#xff0c;并输出能进入淘汰赛阶段的球队列表。以下是规则详细描述。 题目规则 输入格式&#xff1a; 第一行包含一个整数 …...

9.系统学习-卷积神经网络

9.系统学习-卷积神经网络 简介输入层卷积层感受野池化层全连接层代码实现 简介 卷积神经网络是一种用来处理局部和整体相关性的计算网络结构&#xff0c;被应用在图像识别、自然语言处理甚至是语音识别领域&#xff0c;因为图像数据具有显著的局部与整体关系&#xff0c;其在图…...

基于FPGA的出租车里程时间计费器

基于FPGA的出租车里程时间计费器 功能描述一、系统框图二、verilog代码里程增加模块时间增加模块计算价格模块上板视频演示 总结 功能描述 &#xff08;1&#xff09;&#xff1b;里程计费功能&#xff1a;3公里以内起步价8元&#xff0c;超过3公里后每公里2元&#xff0c;其中…...

三甲医院等级评审八维数据分析应用(五)--数据集成与共享篇

一、引言 1.1 研究背景与意义 随着医疗卫生体制改革的不断深化以及信息技术的飞速发展,三甲医院评审作为衡量医院综合实力与服务水平的重要标准,对数据集成与共享提出了更为严苛的要求。在传统医疗模式下,医院内部各业务系统往往各自为政,形成诸多“信息孤岛”,使得数据…...

VUE条件树查询 自定义条件节点

之前实现过的简单的条件树功能如下图&#xff1a; 经过最新客户需求确认&#xff0c;上述条件树还需要再次改造&#xff0c;以满足正常需要&#xff01; 最新暴改后的功能如下红框所示&#xff1a; 页面功能 主页面逻辑代码&#xff1a; <template><div class"…...

什么是打流,怎么用iperf3打流

什么是打流 在网络安全和黑灰产领域&#xff0c;“打流”具有不同的含义&#xff0c;常用于形容通过技术手段制造流量假象或发起流量攻击。 流量攻击&#xff08;DDoS&#xff09;中的“打流”&#xff1a; “打流”指向目标服务器或网络发起 大规模的数据请求&#xff0c;造…...

使用MySQL APT源在Linux上安装MySQL

全新安装MySQL的步骤 以下说明假定您的系统上尚未安装任何版本的MySQL&#xff08;无论是由Oracle还是其他方分发&#xff09; 添加MySQL的Apt源。 将MySQL的APT存储库添加到系统的软件存储库列表中。 1、转到MySQL APT存储库的下载页面MySQL :: Download MySQL APT Reposi…...

redux react-redux @reduxjs/toolkit

redux团队先后推出了redux、react-redux、reduxjs/toolkit&#xff0c;这三个库的api各有不同。本篇文章就来梳理一下当我们需要在项目中集成redux&#xff0c;从直接使用redux&#xff0c;到使用react-redux&#xff0c;再到react-redux和reduxjs/toolkit配合使用&#xff0c;…...

【偏好对齐】通过ORM直接推导出PRM

论文地址&#xff1a;https://arxiv.org/pdf/2412.01981 相关博客 【自然语言处理】【大模型】 ΨPO&#xff1a;一个理解人类偏好学习的统一理论框架 【强化学习】PPO&#xff1a;近端策略优化算法 【偏好对齐】PRM应该奖励单个步骤的正确性吗&#xff1f; 【偏好对齐】通过OR…...

Python与其他编程语言的区别是什么?

Python是一种广泛使用的高级编程语言&#xff0c;以其简洁的语法、强大的库支持和广泛的应用领域而著称。与其他编程语言相比&#xff0c;Python具有许多独特的特点和优势。以下将从多个方面详细探讨Python与其他编程语言的区别&#xff0c;并通过示例进行说明。 一、语法简洁…...

cuda11.6和对应的cudnn(windows)

因为每次不同的torch版本要下对应的cuda&#xff0c;这次刚好在Windows上下好了一个cuda11.6和对应的cudnn&#xff0c;直接放到网盘中&#xff0c;大家有需要对应版本的可以直接下载&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/f153a53830d4 大家自取&#xff0c;c…...

24年无人机行业资讯 | 12.23-12.29

24年无人机行业资讯 | 12.23-12.29 1、 国家发改委新设低空经济司&#xff0c;助力低空经济规范发展2、商务部支持无人机民用国际贸易&#xff0c;强调出口管制与安全并重3、滨州高新区首架无人机成功下线4、 2025第九届世界无人机大会筹备推进会顺利召开5、2024年世界无人机竞…...

uniapp:微信小程序文本长按无法出现复制菜单

一、问题描述 在集成腾讯TUI后&#xff0c;为了能让聊天文本可以复制&#xff0c;对消息组件的样式进行修改&#xff0c;主要是移除下面的user-select属性限制&#xff1a; user-select: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms…...

qml Item详解

1、概述 Item是QML&#xff08;Qt Modeling Language&#xff09;的基础元素&#xff0c;所有其他可视化元素都继承自它。它代表了一个可视化的对象&#xff0c;虽然Item对象本身没有可视外观&#xff0c;但它定义了所有可视项之间通用的属性&#xff0c;比如位置、大小、旋转…...

【Java回顾】Day4 反射机制

反射机制 之前学过一部分&#xff0c;笔记在20250103Java包_网络编程.md里,这里在之前的笔记的基础上做一些补充。 反射&#xff1a;得到class对象后反向获取对象的各种信息。 包 Field 类或接口中的字段(成员变量)&#xff0c;动态访问和修改类的字段 模板 获取Class 对象 …...

【沉默的羔羊心理学】汉尼拔的“移情”游戏:操纵与理解的艺术,精神分析学视角下的角色互动

终极解读《沉默的羔羊》&#xff1a;弗洛伊德精神分析学视角下的深层剖析 关键词 沉默的羔羊弗洛伊德精神分析学角色心理意识与潜意识性别与身份 弗洛伊德精神分析学简介 弗洛伊德的精神分析学是心理学的一个重要分支&#xff0c;主要关注人类行为背后的无意识动机和冲突。…...

[深度学习] 大模型学习1-大语言模型基础知识

大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;是一类基于Transformer架构的深度学习模型&#xff0c;主要用于处理与自然语言相关的各种任务。简单来说&#xff0c;当用户输入文本时&#xff0c;模型会生成相应的回复或结果。它能够完成许多任务&…...

如何解决数据库和缓存不一致的问题

目录 一、Cache-Aside模式&#xff08;旁路缓存模式&#xff09; 二、Write-Through模式&#xff08;写透缓存模式&#xff09; 三、Write-Behind模式&#xff08;写回缓存模式&#xff09; 四、先删除缓存再更新数据库&#xff08;不推荐&#xff0c;存在风险&#xff09;…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...