1.短信登录
1.0 问题记录
1.0.1 redis 重复 token 问题
每次用户登录时,后端会创建一个新的 token 并存入 Redis,但之前登录的 token 还没有过期。这可能会导致以下问题:
- 1. Redis 中存在大量未过期但实际已不使用的 token
- 2. 同一用户可能有多个有效 token
- 3. 资源浪费和潜在的安全风险
原因:
Logout 时会清除 token,但平常关闭服务时并没有点击退出登录导致 token 积累....
1.1 session 实现登录流程
1.1.1 发送验证码:
用户在提交手机号后,会校验手机号是否合法,如果不合法,则要求用户重新输入手机号
如果手机号合法,后台此时生成对应的验证码,同时将验证码进行保存,然后再通过短信的方式将验证码发送给用户
1.1.2 短信验证码登录、注册:
用户将验证码和手机号进行输入,后台从 session 中拿到当前验证码,然后和用户输入的验证码进行校验,如果不一致,则无法通过校验,如果一致,则后台根据手机号查询用户,如果用户不存在,则为用户创建账号信息,保存到数据库,无论是否存在,都会将用户信息保存到 session 中,方便后续获得当前登录信息
1.1.3 校验登录状态:
用户在请求时候,会从 cookie 中携带者 sessionId 到后台,后台通过 sessionId 从 session 中拿到用户信息,如果没有 session 信息,则进行拦截,如果有 session 信息,则将用户信息保存到 threadLocal 中,并且放行
1.2 登录拦截功能
1.2.1 Tomcat 运行原理
- 当用户发起请求时,会访问我们像 tomcat 注册的端口,任何程序想要运行,都需要有一个线程对当前端口号进行监听,tomcat 也不例外
- 当监听线程知道用户想要和 tomcat 连接连接时,那会由监听线程创建 socket 连接,socket 都是成对出现的
- 用户通过 socket 像互相传递数据,当 tomcat 端的 socket 接受到数据后,此时监听线程会从 tomcat 的线程池中取出一个线程执行用户请求
- 在我们的服务部署到 tomcat 后,线程会找到用户想要访问的工程,然后用这个线程转发到工程中的 controller,service,dao 中,并且访问对应的 DB
- 在用户执行完请求后,再统一返回,再找到 tomcat 端的 socket,再将数据写回到用户端的 socket,完成请求和响应
通过以上讲解,我们可以得知 每个用户其实对应都是去找 tomcat 线程池中的一个线程来完成工作的,使用完成后再进行回收,既然每个请求都是独立的,所以在每个用户去访问我们的工程时,我们可以使用 threadlocal 来做到线程隔离,每个线程操作自己的一份数据
- 请求接收阶段
- Acceptor 线程:Tomcat 启动时,会创建 1-2 个 Acceptor 线程(非监听线程),负责监听服务器端口(如 8080),接受客户端 TCP 连接请求。
- Socket 配对:当客户端发起请求时,Acceptor 线程会创建一个 Socket 连接(客户端 Socket 与服务端 Socket 成对出现)。
- I/O 事件处理
- Poller 线程:Acceptor 将连接交给 Poller 线程(基于 NIO 模式),Poller 通过 Selector 监听 Socket 的读写事件(如 HTTP 请求数据到达)。
- 事件触发:当 Socket 有数据可读时,Poller 线程会将请求封装成任务,提交到工作线程池。
- 业务处理阶段
- Worker 线程池:Tomcat 从线程池中分配一个工作线程(Worker)处理请求:
- 解析 HTTP 协议,生成HttpServletRequest和HttpServletResponse对象。
- 根据 URL 匹配部署的 Web 应用(Context)、Servlet 路径(Wrapper)。
- 依次经过 Filter 链,最终调用目标 Servlet(或 Spring MVC 的 DispatcherServlet)。
- 执行业务逻辑(Controller→Service→DAO→DB),生成响应数据。
- Worker 线程池:Tomcat 从线程池中分配一个工作线程(Worker)处理请求:
- 响应返回
- Worker 线程将响应数据写入 Socket 输出流,通过 TCP 返回客户端。
- 线程释放回线程池,完成一次请求-响应周期。
1.2.2 ThreadLocal
如果小伙伴们看过 threadLocal 的源码,你会发现在 threadLocal 中,无论是他的 put 方法和他的 get 方法,都是先从获得当前用户的线程,然后从线程中取出线程的成员变量 map,只要线程不一样,map 就不一样,所以可以通过这种方式来做到线程隔离
ThreadLocal 的线程隔离机制
- 线程独立性:每个 HTTP 请求由独立的 Worker 线程处理,线程之间互不干扰。
- ThreadLocal 原理:
ThreadLocal 为每个线程维护一个独立的变量副本(通过Thread.currentThread().threadLocals存储),实现线程封闭(Thread Confinement)。
// 示例:存储用户会话信息
ThreadLocal<User> currentUser = new ThreadLocal<>();
currentUser.set(user); // 当前线程独享
User user = currentUser.get(); // 仅当前线程可获取
- 典型应用场景:
- 用户会话(Session)管理(如 Spring 的RequestContextHolder)。
- 数据库连接隔离(如 MyBatis 的SqlSession绑定线程)。
- 避免参数透传(如链路追踪的 TraceID)。
关键补充说明
- 1. 线程池配置:Tomcat 的线程池大小(maxThreads)直接影响并发能力,需根据业务特点调整。
- 2. 连接器(Connector):支持 NIO(非阻塞)、APR(高性能)等模式,默认 NIO 适合大多数场景。
- 3. 注意事项:
- ThreadLocal 需手动remove(),否则可能导致内存泄漏(尤其线程池场景)。
- Tomcat 的线程模型是同步阻塞的(Servlet 规范),异步处理需使用 AsyncContext 或 Reactive 编程。
1.2.3 登录拦截
1.3 session 共享问题
每个 tomcat 中都有一份属于自己的 session,假设用户第一次访问第一台 tomcat,并且把自己的信息存放到第一台服务器的 session 中,但是第二次这个用户访问到了第二台 tomcat,那么在第二台服务器上,肯定没有第一台服务器存放的 session,所以此时 整个登录拦截功能就会出现问题,我们能如何解决这个问题呢?早期的方案是 session 拷贝,就是说虽然每个 tomcat 上都有不同的 session,但是每当任意一台服务器的 session 修改时,都会同步给其他的 Tomcat 服务器的 session,这样的话,就可以实现 session 的共享了
但是这种方案具有两个大问题:
- 每台服务器中都有完整的一份 session 数据,服务器压力过大。
- session 拷贝数据时,可能会出现延迟
所以咱们后来采用的方案都是基于 redis 来完成,我们把 session 换成 redis,redis 数据本身就是共享的,就可以避免 session 共享的问题了
- 在 Servlet 规范中,Session 是由容器(如 Tomcat)实现的,核心接口是HttpSession。
- Session 数据默认存储在服务器内存中(ConcurrentHashMap)
- 每个 Tomcat 实例维护自己的 Session 存储
- Session ID 通过 Cookie 或 URL 重写与客户端关联
- 在负载均衡环境下,请求可能被分发到不同服务器
- 无状态的负载均衡器不知道请求关联的 Session 存储在哪个服务器
- 即使有 Session ID,其他服务器也没有对应的 Session 数据
1.3.1 Session 的基本概念
Session(会话)是 Web 开发中用于跟踪用户状态的机制,其核心特点是:
- 服务器端存储:用户数据保存在服务端
- 客户端关联:通过 Session ID(通常通过 Cookie 或 URL 重写)与客户端绑定
- 有状态性:记录用户在一段时间内的交互状态
1.3.2 Session 共享问题的本质
在分布式/集群环境下,Session 共享问题源于状态存储位置与请求路由机制之间的矛盾:
- 1. 存储位置矛盾:
- 传统 Session 存储在单个服务器内存中
- 但集群环境下有多台服务器
- 2. 路由机制矛盾:
- 负载均衡器采用无状态分发(如轮询、随机)
- 但业务需要有状态识别(同一用户的请求应关联相同 Session)
1.3.3 典型问题场景
场景 1:基础负载均衡
用户A → 请求1 → 负载均衡 → 服务器1(创建Session)→ 请求2 → 负载均衡 → 服务器2(无此Session)
结果:用户需要重新登录,状态丢失
场景 2:服务器宕机
用户A → 服务器1(Session存储地)
服务器1崩溃 → 请求被转到服务器2(无Session数据)
结果:用户会话中断
场景 3:水平扩展
原有3台服务器 → 新增第4台服务器
新请求可能被路由到没有历史Session的新服务器
结果:扩展导致会话一致性被破坏
1.3.4 Session 共享的四大核心挑战
- 1. 数据一致性:
- 如何保证所有服务器看到的 Session 数据一致
- 特别是并发修改时的数据同步
- 2. 实时性要求:
- Session 变更需要及时传播到所有节点
- 平衡一致性与性能的关系
- 3. 故障恢复:
- 单个节点故障不应影响整体可用性
- 新节点应能快速获取已有 Session 数据
- 4. 扩展性:
- 解决方案不应成为系统扩展的瓶颈
- 支持动态增减节点
1.3.5 主流解决方案对比
方案 1:粘滞会话(Sticky Session)
原理:
- 负载均衡器通过特定算法(如 IP 哈希)保证同一用户的请求始终路由到同一服务器
优点:
- 实现简单
- 无需修改应用代码
缺点:
- 失去负载均衡的灵活性
- 节点故障时关联会话丢失
- 不符合 REST 无状态原则
方案 2:Session 复制
原理:
- 所有服务器间同步 Session 变更
- 形成全网状的数据同步
优点:
- 任意节点都可处理请求
- 故障转移平滑
缺点:
- 网络带宽消耗大(O(n²)复杂度)
- 同步延迟可能导致数据不一致
- 不适合大规模集群
方案 3:集中式存储
原理:
- 将会话数据存储在外部集中存储(Redis/Memcached/数据库)
- 所有服务器访问统一数据源
优点:
- 真正解决共享问题
- 良好的扩展性
- 明确的持久化策略
缺点:
- 引入外部依赖
- 网络延迟增加
- 需要处理缓存失效问题
方案 4:客户端存储
原理:
- 将会话数据加密后存储在客户端(Cookie/本地存储)
- 服务端无状态
优点:
- 完全避免服务端存储
- 天然支持扩展
缺点:
- 安全性挑战(需严格加密)
- 数据大小受限
- 每次请求需传输完整会话数据
1.3.6 现代架构的最佳实践
- 1. 无状态优先原则:
- 尽可能减少会话中的状态数据
- 将状态外移到数据库/缓存
- 2. 分层会话设计:
- 高频访问数据:内存缓存
- 重要数据:持久化存储
- 临时状态:客户端存储
- 3. 混合解决方案:
graph TD A[客户端] --> B[负载均衡] B --> C[服务器集群] C --> D[集中式Redis存储] C --> E[本地内存缓存]
- 4. 失效策略:
- 设置合理的 TTL(Time-To-Live)
- 主动清理与被动过期结合
- 考虑分布式锁机制
1.3.7 特殊场景考量
- 1. 微服务架构:
- 每个服务维护自己的"局部会话"
- 通过 JWT 等机制传递用户上下文
- 2. Serverless 环境:
- 强制无状态设计
- 依赖外部存储服务
- 3. 长连接应用:
- WebSocket 连接与 HTTP 会话的映射
- 连接迁移时的状态转移
1.3.8 总结决策树
是否需要会话共享?
├─ 否 → 单机部署或粘滞会话
└─ 是 → 选择集中存储方案├─ 高性能要求 → Redis/Memcached├─ 强一致性要求 → 数据库+缓存└─ 安全敏感 → 客户端存储+加密
理解 Session 共享问题的核心在于认识到有状态服务与无状态扩展之间的本质矛盾。现代分布式系统通常采用"尽量无状态,必要时集中存储"的折中方案,在一致性与可用性之间取得平衡。
1.4 redis 解决共享问题
1.4.1 设计 KEY 的结构
首先我们要思考一下利用 redis 来存储数据,那么到底使用哪种结构呢?
由于存入的数据比较简单,我们可以考虑使用 String,或者是使用哈希,如下图
如果使用 String,同学们注意他的 value,多占用一点空间
如果使用哈希,则他的 value 中只会存储他数据本身,如果不是特别在意内存,其实使用 String 就可以啦。
从优化的角度讲使用 Hash 比较好。
1.4.2 设计 KEY 的细节
所以我们可以使用 String 结构,就是一个简单的 key,value 键值对的方式,但是关于 key 的处理,session 他是每个用户都有自己的 session,但是 redis 的 key 是共享的,咱们就不能使用 code 了
在设计这个 key 的时候,我们之前讲过需要满足两点
- 1. key 要具有唯一性
- 2. key 要方便携带
如果我们采用 phone:手机号这样的数据来存储当然是可以的,但是如果把这样的敏感数据存储到 redis 中并且从页面中带过来毕竟不太合适,所以我们在后台生成一个随机串 token,然后让前端带来这个 token 就能完成我们的整体逻辑了
1.4.3 整体访问流程
- 当注册完成后
- 用户去登录会去校验用户提交的手机号和验证码
- 是否一致,如果一致,则根据手机号查询用户信息
- 不存在则新建
- 最后将用户数据保存到 redis,并且生成 token 作为 redis 的 key
- 当我们校验用户是否登录时
- 会去携带着 token 进行访问
- 从 redis 中取出 token 对应的 value,判断是否存在这个数据
- 如果没有则拦截,如果存在则将其保存到 threadLocal 中,并且放行
1.5 解决状态登录刷新问题
在这个方案中,他确实可以使用对应路径的拦截,同时刷新登录 token 令牌的存活时间,但是现在这个拦截器他只是拦截需要被拦截的路径,假设当前用户访问了一些不需要拦截的路径,那么这个拦截器就不会生效,所以此时令牌刷新的动作实际上就不会执行,所以这个方案他是存在问题的
优化方案:
既然之前的拦截器无法对不需要拦截的路径生效,那么我们可以添加一个拦截器,在第一个拦截器中拦截所有的路径,把第二个拦截器做的事情放入到第一个拦截器中,同时刷新令牌,因为第一个拦截器有了 threadLocal 的数据,所以此时第二个拦截器只需要判断拦截器中的 user 对象是否存在即可,完成整体刷新功能。
RefreshTokenInterceptor:
不管用户访问那个路径都会被拦截,判断 token 是否有效
- 无效则放行给 LoginInterceptor 拦截器
- 判断路径是否为必须登录
- 是则拦截请求,校验 ThredLocal 中是否有信息,无则返回 401,有则放行
- 不是则放行
- 判断路径是否为必须登录
- 有效则将信息放入 ThreadLocal 并刷新 token 有效期
- 在拦截器中配置 order()来控制先后,越小优先级越高
1.6 退出登录功能
@PostMapping("/logout")
public Result logout(@RequestHeader(value = "authorization") String token) {return userService.logout(token);
}
@Override
public Result logout(String token) {// 1.删除Redis中的tokenString tokenKey = LOGIN_USER_KEY + token;stringRedisTemplate.delete(tokenKey);// 2.清除ThreadLocal中的用户UserHolder.removeUser();return Result.ok();
}
1.7 登录业务的实现设计方案
登录业务是几乎所有系统都需要的基础功能,根据您的代码和现代 Web 应用的发展,我为您总结几种常见的登录实现设计方案:
1. 基于 Session 的登录方案
这是传统的登录实现方式:
- 工作原理:
- 用户登录成功后,服务器创建 Session 并生成 SessionID
- SessionID 通过 Cookie 返回给浏览器
- 后续请求会自动携带 Cookie 中的 SessionID
- 服务器通过 SessionID 识别用户身份
- 优点:
- 实现简单,Spring 框架原生支持
- 安全性较高,SessionID 随机生成
- 服务端可控性强
- 缺点:
- 分布式系统中 Session 共享问题
- 服务器需要存储 Session,增加服务器负担
- 跨域请求处理复杂
2. 基于 Token 的登录方案(您当前使用的方案)
- 工作原理:
- 用户登录成功后,服务器生成 Token
- Token 返回给客户端存储(如 localStorage)
- 后续请求在 Header 中携带 Token
- 服务器验证 Token 有效性
- 优点:
- 无状态,适合分布式系统
- 可跨域使用
- 可以在客户端存储,减轻服务器压力
- 缺点:
- 需要自行处理 Token 的生成、验证和过期
- Token 一旦泄露,安全风险较大
- 无法像 Session 那样方便地实现强制登出
3. 基于 JWT(JSON Web Token)的登录方案
- 工作原理:
- 用户登录成功后,服务器生成 JWT
- JWT 包含用户信息、过期时间等,并使用密钥签名
- 客户端存储 JWT 并在请求中携带
- 服务器验证 JWT 签名和有效期
- 优点:
- 完全无状态,服务器不需要存储会话信息
- 包含用户信息,减少数据库查询
- 支持跨域,适合微服务架构
- 缺点:
- Token 无法主动失效,只能等过期
- JWT 体积较大,增加网络传输量
- 敏感信息不宜放在 JWT 中(虽然签名但内容可解码)
4. OAuth 2.0 / 第三方登录
- 工作原理:
- 利用第三方平台(如微信、QQ、GitHub)的用户系统
- 用户授权后获取第三方平台提供的 Token
- 使用 Token 获取用户信息并在本系统创建或关联账号
- 优点:
- 简化用户注册流程
- 提高用户体验,无需记忆新密码
- 可获取第三方平台的用户信息
- 缺点:
- 依赖第三方平台稳定性
- 实现复杂度较高
- 需要处理用户账号关联问题
5. 双因素认证 (2FA)
- 工作原理:
- 除了用户名密码外,还需要第二种验证方式
- 常见的第二因素包括:短信验证码、邮箱验证码、认证器 App 等
- 两种因素都验证通过才允许登录
- 优点:
- 大幅提高安全性
- 可以防止密码泄露导致的账号被盗
- 适合金融、支付等高安全需求场景
- 缺点:
- 增加了用户登录的复杂度
- 需要额外的基础设施(如短信服务)
- 可能影响用户体验
6. 单点登录 (SSO)
- 工作原理:
- 用户只需登录一次,就可以访问多个相关系统
- 通常基于中央认证服务(CAS)或 SAML 协议实现
- 各子系统通过票据或断言验证用户身份
- 优点:
- 提升用户体验,避免重复登录
- 统一的用户管理
- 适合企业内多系统集成场景
- 缺点:
- 实现复杂度高
- 中央认证服务成为单点故障风险
- 安全设计要求高
您当前实现的方案分析
您目前使用的是基于 Token + Redis 的登录方案:
- 1. 用户登录成功后,生成随机 UUID 作为 token
- 2. 将用户信息存储在 Redis 中,key 为LOGIN_USER_KEY + token
- 3. 设置合理的过期时间
- 4. 用户登出时,主动删除 Redis 中的 token
这种方案结合了 Session 和 Token 的优点:
- 像 Token 一样支持分布式系统
- 像 Session 一样可以主动使 token 失效
- 使用 Redis 提高了性能
- 实现相对简单且安全性较高
对于您的点评系统来说,这是一个非常合适的选择。如果未来系统规模扩大,可以考虑向 JWT 或 SSO 方向演进。
相关文章:
1.短信登录
1.0 问题记录 1.0.1 redis 重复 token 问题 每次用户登录时,后端会创建一个新的 token 并存入 Redis,但之前登录的 token 还没有过期。这可能会导致以下问题: 1. Redis 中存在大量未过期但实际已不使用的 token2. 同一用户可能有多个有效 …...
Vue v-model 深度解析:实现原理与高级用法
一、v-model 的本质 v-model 是 Vue 中最常用的指令之一,它本质上是一个语法糖,用于在表单元素和自定义组件上实现双向数据绑定。在 Vue 2.x 和 Vue 3.x 中,v-model 的实现机制有所不同,但核心思想都是简化数据绑定的过程。 1.1…...
Java动态代理超详细解析:三步+内存图(堆栈分析)
0.本文适合谁? 1.刚学Java动态代理,被Proxy、InvocationHandler绕晕的同学 2.想彻底搞懂代理对象在内存中如何工作的开发者 3.需要面试突击动态代理知识的求职 1.动态代理的本质(三步走) 动态代理的核心可以拆解为三个关键…...
MySQL 从入门到精通(六):视图全面详解 —— 虚拟表的灵活运用
在数据库开发中,我们经常需要重复执行复杂的多表查询,或是需要限制用户只能访问特定数据。这时候,MySQL 的 视图(View)就能大显身手。作为一种 “虚拟表”,视图不存储实际数据,却能基于 SQL 查询…...
Linux 下 Java 部署环境搭建与项目部署详细步骤
目录 1. 软件环境准备 1.1 更新软件包库 1.2 安装 OpenJDK 1.3 安装 MySQL 数据库 2. 部署 Web 项目到 Linux 2.1 数据准备和配置 2.2 Maven 打包项目 2.3 上传 Jar 包至云服务器 2.4 启动应用程序 2.5 配置防火墙与端口开放 2.6 访问与验证项目 2.7 进程管理与问题…...
养生:为健康生活添彩
养生是对生活的热爱,是为健康生活注入活力的良方。从饮食、运动到生活习惯,每一个方面都能让我们离健康更近一步。以下是一些实用的养生之道,助你开启健康生活的新旅程。 饮食养生:营养均衡,健康基石 合理的饮食是养…...
Hypermesh四面体网格划分(二)
我们找到“3D-tetramesh”的命令,然后选择“tetra mesh”,以下就是这种四面体网格生成方式的面板。见图1所示。 图1 tetra mesh面板 下面以一个法兰盘的四面体网格划分作为案例,具体介绍基于表面网格的四面体网格生成方式。 首先导入几何模型…...
PySide6 GUI 学习笔记——常用类及控件使用方法(常用类边距QMargins)
文章目录 类概述方法总览使用注意事项简单示例 类概述 QMargins 类用于描述矩形四周边框尺寸,包含左(left)、上(top)、右(right)、下(bottom)四个整型边距值。当所有边距均为0时,isNull() 返回 True。该类支持流式操作和比较运算。 版本信息࿱…...
python笔记和练习----少儿编程课程【阶段二(二)】
第13课 列表元素的查找和删除 知识点 1、删除第一个出现的指定元素 列表.remove(元素) 2.删除末尾元素 列表.pop() 3、清空列表的所有数据 列表.clear() 4、删除指定位置的元素 del 列表[索引] del 关键字本质上是用来 将一个变量从内存中删除…...
Excel里面怎样批量去掉字串包含的标点符号
在Excel中批量去除字符串中的标点符号,可以通过以下几种方法实现: 方法1:使用SUBSTITUTE函数嵌套 适用于已知的特定标点符号(需手动列出): SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1, ",&quo…...
Linux 信号终篇(总结)
前文:本文是对信号从产生到被处理的过程中的概念和原理的总结,如果想了解具体实现,请查看前两篇博客:Linux 信号-CSDN博客、Linux 信号(下篇)-CSDN博客 一、信号的产生 1.1 信号产生的五种条件 ①键盘组…...
Springboot之会话技术
会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器ÿ…...
数字信号处理|| 离散系统的冲激响应和阶跃响应
一、实验目的 (1)加深对离散线性移不变(LSI)系统基本理论的理解,明确差分方程与系统函数之间的关系。 (2)初步了解用MATLAB语言进行离散时间系统研究的基本方法。 (3)掌…...
JVM 数据区域
JVM 数据区域 1 程序计数器 程序计数器(Program Counter Register) ,也有称作为PC寄存器。在汇编语言中,程序计数器是指CPU中的寄存器,它保存的是程序当前执行的指令的地址,当CPU需要执行指令时࿰…...
MRNet 数据集分享
MRNet 数据集分享 包括了2001年1月1日至2012年12月31日期间在斯坦福大学医学中心进行的1370次膝关节MRI检查(平均年龄38.0岁;569例(41.5%)女性患者)。该数据集包含 1,104 (80.6%) 次异常检查,其中319 (23.…...
MCP项目实例 - client sever交互
1. 项目概述 项目目标 构建一个本地智能舆论分析系统。 利用自然语言处理和多工具协作,实现用户查询意图的自动理解。 进行新闻检索、情绪分析、结构化输出和邮件推送。 系统流程 用户查询:用户输入查询请求。 提取关键词:从用户查询中…...
uniapp|实现商品分类与列表数据联动,左侧菜单右侧商品列表(瀑布流、高度自动计算、多端兼容)
基于uniapp实现商品分类与商品列表数据联动,提供完整代码与常见问题解决方案,通过实战案例演示,快速构建商品列表交互,开箱即用。 目录 前言应用场景介绍页面布局与样式整体结构分析左侧菜单样式右侧商品列表样式核心功能实现数据绑定与渲染点击事件交互性能优化图片懒加载…...
1.2.2.1.4 数据安全发展技术发展历程:高级公钥加密方案——同态加密
引言 在密码学领域,有一种技术被图灵奖得主、著名密码学家Oded Goldreich誉为"密码学圣杯",那就是全同态加密(Fully Homomorphic Encryption)。今天我们就来聊聊这个神秘而强大的加密方案是如何从1978年的概念提出&…...
dify插件接入fastmcp示例
文章目录 1. 使用python完成mcp服务1.1 准备环境(python安装fastmcp)1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略(支持 MCP 工具) 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置ÿ…...
从文本到语义:BERT、Faiss 与 Elasticsearch 的协同实践
从文本到语义:BERT、Faiss 与 Elasticsearch 的协同实践 在自然语言处理(NLP)的技术栈中,BERT、Faiss 和 Elasticsearch 是三个具有代表性的工具,它们各自发挥着独特的作用。BERT 负责文本的语义理解,Fais…...
安装或更新 CUDA Toolkit - Ubuntu - RuntimeError
1、问题 执行 pip install flash-attn --no-build-isolation 时,出错: RuntimeError: FlashAttention is only supported on CUDA 11.7 and above. Note: make sure nvcc has a torch.__version__ 2.4.0cu12 执行 nvcc --version 或 nvcc -V&…...
二、Hive安装部署详细过程
Apache Hive 是一个构建在 Hadoop 之上的数据仓库基础设施。它提供了类似 SQL 的查询语言 (称为 HiveQL 或 HQL),让熟悉 SQL 的开发人员和分析师能够轻松地查询和分析存储在 HDFS 或其他兼容存储系统中的大规模数据集。把结构化或半结构化的数据映射成表,…...
常见的降维算法
作业: 自由作业:探索下什么时候用到降维?降维的主要应用?或者让ai给你出题,群里的同学互相学习下。可以考虑对比下在某些特定数据集上t-sne的可视化和pca可视化的区别。 一、什么时候用到降维? 降维通常…...
Spring Boot 中如何启用 MongoDB 事务
在 Spring Boot 中启用和使用 MongoDB 事务主要依赖于以下几个方面: MongoDB 服务器和部署模式: MongoDB 版本 4.0 或更高版本才支持副本集 (Replica Set) 上的多文档 ACID 事务。MongoDB 版本 4.2 或更高版本才支持分片集群 (Sharded Cluster) 上的多文…...
2025年5月15日前 免费考试了! Oracle AI 矢量搜索专业认证
2025年5月5日前 免费考试了! Oracle AI 矢量搜索专业认证 立刻预约吧 文章目录 2025年5月5日前 免费考试了! Oracle AI 矢量搜索专业认证立刻预约吧🔍 探索 AI 向量搜索的强大功能!🎯 学习路径目标Ὦ…...
初等数论--莫比乌斯反演
1. 定义 假设 f ( n ) g ( n ) f(n)\ g(n) f(n) g(n)是定义在正整数上的两个函数 ,且 f ( n ) ∑ d ∣ n g ( d ) ∑ d ∣ n g ( n d ) f(n)\sum_{d|n}g(d)\sum_{d|n}g(\frac{n}{d}) f(n)d∣n∑g(d)d∣n∑g(dn) 那么 g ( n ) ∑ d ∣ n μ ( d ) f ( n d…...
访问者模式(Visitor Pattern)详解
文章目录 1. 访问者模式概述1.1 定义1.2 基本思想2. 访问者模式的结构3. 访问者模式的UML类图4. 访问者模式的工作原理5. Java实现示例5.1 基本实现示例5.2 访问者模式处理复杂对象层次结构5.3 访问者模式在文件系统中的应用6. 访问者模式的优缺点6.1 优点6.2 缺点7. 访问者模式…...
C++ 关联式容器:map,multimap,set,multiset
目录 引言 一、关联式容器概述 1.1 与序列式容器的区别 1.2 底层结构 二、set容器详解set介绍 2.1 set的特性 2.2 set的模板参数 2.3 set的常用接口 2.4 set使用示例 三、map容器详解map介绍 3.1 map的特性 3.2 map的模板参数 3.3 map的常用接口 3.4 map使用示例 …...
Discriminative and domain invariant subspace alignment for visual tasks
用于视觉任务的判别性和域不变子空间对齐 作者:Samaneh Rezaei,Jafar Tahmoresnezhad 文章于2018年12月4日收到,2019年5月24日被接受,2019年6月3日在线发表于Iran Journal of Computer Science期刊,DOI: 10.1007/s42…...
comfyui 如何优雅的从Hugging Face 下载模型,文件夹
如下图所示 使用git 下载整个仓库然后把需要的放到对应的位置...
【C++】 —— 笔试刷题day_27
一、kotori和气球 题目解析 这道题,有n中气球,每一种气球有无数多个;现在我们需要将这些气球摆成一排,但是,如果相邻的气球是相同的就会发生爆炸(也就是说,相同的气球相邻的摆法是不合法的&…...
2025年“深圳杯”数学建模挑战赛C题国奖大佬万字思路助攻
完整版1.5万字论文思路和Python代码下载:https://www.jdmm.cc/file/2712073/ 引言 本题目旨在分析分布式能源 (Distributed Generation, DG) 接入配电网系统后带来的风险。核心风险评估公式为: R P_{loss} \times C_{loss} P_{over} \times C_{over}…...
大模型微调指南之 LLaMA-Factory 篇:一键启动LLaMA系列模型高效微调
文章目录 一、简介二、如何安装2.1 安装2.2 校验 三、开始使用3.1 可视化界面3.2 使用命令行3.2.1 模型微调训练3.2.2 模型合并3.2.3 模型推理3.2.4 模型评估 四、高级功能4.1 分布训练4.2 DeepSpeed4.2.1 单机多卡4.2.2 多机多卡 五、日志分析 一、简介 LLaMA-Factory 是一个…...
游戏引擎学习第268天:合并调试链表与分组
回顾并为今天的内容设定基调 我们正在直播中开发完整的游戏,目前调试系统的开发已接近尾声。这个调试系统的构建过程经历了较长的时间,中间还暂停过一段时间去做硬件渲染路径的开发,并在已有的软件渲染路径基础上进行了扩展。后来我们又回到…...
【Linux系统编程】进程属性--标识符
1.PID 1.1什么是PID? 区分进程的唯一性 1.2如何查看进程? ps ajx | head -1 ; ps ajx | grep myproc 或者ps ajx | head -1 && ps ajx | grep myproc | grep -v grep(过滤掉grep本身这个进程) 1.3进程有哪两种&#…...
React文档-State数据扁平化
1、选择 State 结构 思考一下: 如果渲染列表, 并更新列表数据在下面展示~ state 过去常常是这样复制的: items [{ id: 0, title: pretzels}, ...]selectedItem {id: 0, title: pretzels} 改了之后是这样的:items [{ id: 0, …...
kotlin flow防抖
一 防抖设计 ✅ 1. 点击事件的防抖:用于防止频繁触发逻辑 🎯 适用场景: 用户连续快速点击按钮,可能会导致多次发送网络请求、CAN 指令或反复切换状态等副作用。所以我们通常在点击函数中处理防抖,例如: …...
基础语法(二)
Mysql基础语法(二) Mysql基础语法(二)主要介绍Mysql中稍微进阶一点的内容,会稍微有一些难度(博主个人认为)。学习完基础语法(一)和基础语法(二)之…...
FreeTex v0.2.0:功能升级/支持Mac
概述 FreeTex在发布之后,迎来很多反馈,本次根据主流的反馈建议,又进行一轮小升级,正式发布v0.2.0版本,主要升级点如下: 新增识别结果预览显示 Latex识别结果支持格式化输出 软件体积更小,并移…...
MacOS 用brew 安装、配置、启动Redis
MacOS 用brew 安装、配置、启动Redis 一、安装 brew install redis 二、启动 brew services start redis 三、用命令行检测 set name tom get name...
大型旋转机械信号分解算法模块
大型旋转机械信号分解算法模块,作为信号处理算法工具箱的主要功能模块,可应用于各类关键机械部件(轴承、齿轮、转子、联轴器等)的信号分析、故障探测、趋势劣化评估等,采用全Python语言,以B/S模式ÿ…...
Java 中的数据类型误导点!!!
在 Java 中,数据类型分为两大类:基本类型(Primitive Types) 和 引用类型(Reference Types)。它们的存储方式和行为完全不同。 1. 基本类型 Java 有 8 种基本数据类型,它们直接存储值ÿ…...
Linux--JsonCpp
1.JsonCpp 简介 JsonCpp 是一个用于 C 的 JSON 解析和生成库,支持 JSON 数据的读写、解析和序列化。它提供了简单的 API 来操作 JSON 对象、数组、字符串、数字等类型,是 C 开发中处理 JSON 数据的常用工具。 核心功能与类 JsonCpp 主要包含以下核心类…...
cv_connection (像halcon一样对区域进行打散)
主题: 分享一个自己用opencv写的小方法, 可以像halcon的connection算子一样, 对cv2.threshold得到的region进行打散, 并返回一个打散后的不相连的region的列表。 代码如下 def cv_connection(region):# he的拓扑信息为 后一…...
ConcurrentHashMap和锁
文章目录 JDK1.7的分段锁JDK1.8的volatileCAS synchronized可重入锁公平锁和非公平锁悲观锁和乐观锁 JDK1.7的分段锁 数据结构:数组(大数组 Segment 和小数组 HashEntry)链表 #mermaid-svg-dfSgz5E7tBmTbx14 {font-family:"trebuchet …...
黑马k8s(二)
集群环境搭建 1.环境规划 2.环境搭建-主机安装 主节点: 软件选择选择 基础设施服务器,这样安装系统完毕之后,会有很多软件我们可以直接使用了 系统点开,点一下完成 ip地址的设置:要跟虚拟网络编辑器,Net…...
LeetCode热题100--240.搜索二维矩阵--中等
1. 题目 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例 1: 输入:matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[1…...
python校园新闻发布管理系统
目录 技术栈介绍具体实现截图系统设计研究方法:设计步骤设计流程核心代码部分展示研究方法详细视频演示试验方案论文大纲源码获取/详细视频演示 技术栈介绍 Django-SpringBoot-php-Node.js-flask 本课题的研究方法和研究步骤基本合理,难度适中…...
Spring MVC 视图解析器 (ViewResolver) 如何配置? Spring Boot 是如何自动配置常见视图解析器的?
我们来详细分析一下视图解析器 (ViewResolver) 的配置以及 Spring Boot 是如何自动配置它们的。 视图解析器 (ViewResolver) 是什么? 在 Spring MVC 中,当控制器 (Controller) 方法处理完请求并返回一个逻辑视图名 (String) 时,DispatcherS…...
LeetCode 2918.数组的最小相等和:if-else
【LetMeFly】2918.数组的最小相等和:if-else 力扣题目链接:https://leetcode.cn/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/ 给你两个由正整数和 0 组成的数组 nums1 和 nums2 。 你必须将两个数组中的 所有 0 替换为 严格 正…...