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

Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解

Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解

2025.5.21-23:11今天在学习黑马点评时突然发现用的是与苍穹外卖jwt不一样的登录方式-Session,于是就想记录一下这两种方式有什么不同

在实际开发中,登录认证是后端最基础也是最重要的模块之一。常见的实现方式主要有两种:Session 登录JWT(JSON Web Token)登录

下面将从原理、使用场景、优缺点、代码结构等角度,来对比这两种方案,然后给出 Spring Boot 中的实际应用建议,帮助在实际项目中做出合理选择。

一、登录认证基本流程

无论是 JWT 还是 Session,登录的本质流程都是:

  1. 用户发送用户名和密码;
  2. 后端验证成功后,生成认证信息;
  3. 后端将认证信息返回给客户端;
  4. 客户端携带认证信息访问受保护接口;
  5. 后端验证该认证信息是否合法。

二、Session 登录机制

1. 原理说明

  • 用户第一次登录成功后,服务器创建一个 Session,并在服务器内存或 Redis 中保存用户信息;
  • 同时将 Session ID 写入到浏览器的 Cookie 中;
  • 用户每次请求都会自动携带该 Cookie,服务器根据 Session ID 获取用户信息。
    在这里插入图片描述

2. 代码实现示例

登录接口:
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO, HttpSession session) {User user = userService.login(loginDTO);session.setAttribute("user", user);return Result.success();
}
拦截器判断是否登录:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {Object user = request.getSession().getAttribute("user");if (user == null) {response.setStatus(401);return false;}return true;
}

三、JWT 登录机制

1. 原理说明

  • 用户登录成功后,服务器签发一个加密的 JWT Token;
  • 客户端将 Token 保存在 LocalStorage 或 Cookie;
  • 每次请求都将 Token 放在 Authorization 请求头中;
  • 服务器解析并验证 Token,从中读取用户信息。
    在这里插入图片描述

2. JWT Token 的组成

JWT 一般由三部分组成:

Header.Payload.Signature

例如:

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiJsaTIzIn0.sD_Kpdi2M...

3. JWT 登录代码示例

登录生成 Token:
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {User user = userService.login(loginDTO);String token = JwtUtil.generateToken(user); // 自定义工具类生成 tokenreturn Result.success(token);
}
前端请求携带 Token:
GET /user/info HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
拦截器验证 Token:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("Authorization");Claims claims = JwtUtil.parseToken(token);if (claims == null) {response.setStatus(401);return false;}return true;
}

在这里插入图片描述

四、Session vs JWT 对比总结

特性SessionJWT
存储位置服务端(内存/Redis)客户端(LocalStorage/Cookie)
状态性有状态无状态
跨域支持不友好(需处理 Cookie)友好
性能频繁读写服务端存储只需签名验证
安全性较高(信息在服务端)中等(需防止 Token 泄露)
适用场景传统 Web 应用前后端分离、微服务、移动端

五、实战项目推荐

在实际项目中,建议根据以下场景选择:

  • 中小型 Web 应用:推荐使用 Session,实现简单,安全性高;
  • 前后端分离项目:推荐使用 JWT,无状态,跨域友好;
  • 大型系统:考虑 JWT + Session 混合使用,结合两者优势。

六、JWT 常见安全建议

  1. 设置过期时间(exp),避免 token 永久有效;
  2. 使用 HTTPS,防止 Token 被中间人截获;
  3. 配合 Refresh Token 实现续签;
  4. 用户登出时将 Token 加入 Redis 黑名单;
  5. Token 不应包含敏感信息(如密码、身份证号等)。

七、总结

Session 和 JWT 各有优缺点,选择时需根据项目实际情况权衡:

  • Session 适合传统 Web 应用,安全性高,实现简单;
  • JWT 适合前后端分离、微服务架构,无状态,扩展性强。

在实际开发中,还可以结合两者的优势,实现更灵活、安全的认证方案。

八、登录超时控制

1. Session 登录的过期控制

# application.yml 中配置 Session 失效时间(单位分钟)
server:servlet:session:timeout: 30

Session 登录通常依赖浏览器 Cookie,每次请求自动续期,适合长期在线场景。

2. JWT 的过期控制

JWT 自带 exp 字段,在生成 Token 时设置过期时间:

// JwtUtil 生成 Token 示例
public static String generateToken(User user) {Date now = new Date();Date expireDate = new Date(now.getTime() + EXPIRE_TIME); // 设置过期时间return Jwts.builder().setHeaderParam("typ", "JWT").setSubject(user.getId().toString()).setIssuedAt(now).setExpiration(expireDate).claim("username", user.getUsername()).signWith(SignatureAlgorithm.HS512, SECRET) // 签名加密.compact();
}

九、JWT 的刷新机制(Refresh Token)

为了避免用户频繁登录,可以实现 Refresh Token 机制:

  1. 登录时生成两个 Token:AccessToken(短过期)和 RefreshToken(长过期);
  2. AccessToken 过期后,使用 RefreshToken 重新获取 AccessToken;
  3. RefreshToken 也过期时,才需要用户重新登录。
// 登录接口返回两个 Token
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {User user = userService.login(loginDTO);String accessToken = JwtUtil.generateAccessToken(user);String refreshToken = JwtUtil.generateRefreshToken(user);Map<String, String> tokens = new HashMap<>();tokens.put("accessToken", accessToken);tokens.put("refreshToken", refreshToken);return Result.success(tokens);
}// 刷新 Token 接口
@PostMapping("/refreshToken")
public Result refreshToken(@RequestBody RefreshTokenDTO dto) {// 验证 RefreshToken 有效性Claims claims = JwtUtil.parseRefreshToken(dto.getRefreshToken());if (claims == null) {return Result.error("登录已过期,请重新登录");}// 重新生成 AccessTokenUser user = userService.getById(Long.valueOf(claims.getSubject()));String accessToken = JwtUtil.generateAccessToken(user);return Result.success(accessToken);
}

十、登出与 Redis 黑名单机制

JWT 本身无法主动失效,但可以通过 Redis 黑名单实现:

// 登出接口
@PostMapping("/logout")
public Result logout(HttpServletRequest request) {String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7);// 解析 Token 获取过期时间Claims claims = JwtUtil.parseToken(token);if (claims != null) {Date expireDate = claims.getExpiration();long expireSeconds = (expireDate.getTime() - System.currentTimeMillis()) / 1000;// 将 Token 加入 Redis 黑名单,直到过期redisTemplate.opsForValue().set("jwt:blacklist:" + token, "invalid", expireSeconds, TimeUnit.SECONDS);}}return Result.success();
}// 拦截器中检查黑名单
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7);// 检查黑名单if (redisTemplate.hasKey("jwt:blacklist:" + token)) {response.setStatus(401);return false;}// 验证 TokenClaims claims = JwtUtil.parseToken(token);if (claims == null) {response.setStatus(401);return false;}// 将用户信息存入请求request.setAttribute("userId", claims.getSubject());}return true;
}

十一、实际开发中推荐的 JWT 完整实现流程图

用户登录请求
│
▼
后端验证用户名密码
│
▼
验证成功
│
├─┬─ 生成 AccessToken(含用户 ID、角色等)
│ │
│ ├─ 生成 RefreshToken(与用户 ID 绑定)
│ │
│ └─ 将 RefreshToken 存入 Redis(设置过期时间)
│
▼
返回 AccessToken 和 RefreshToken 给前端
│
▼
前端保存 Token(如 LocalStorage)
│
▼
前端每次请求携带 AccessToken(放在 Header)
│
▼
后端拦截器验证 AccessToken
│
├─ 验证失败 ──┐
│             │
│             ▼
│      返回 401 未授权
│             │
│             ▼
│  前端使用 RefreshToken 请求新 AccessToken
│             │
│             ▼
│  后端验证 RefreshToken
│             │
│     ┌───────┴───────┐
│     │               │
│  有效              无效
│     │               │
│     ▼               ▼
│  生成新 Token     用户重新登录
│     │
│     ▼
返回新 AccessToken

十二、附录:JWT 工具类参考实现

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;@Component
public class JwtUtil {@Value("${jwt.secret}")private String secret;@Value("${jwt.accessTokenExpireTime}")private long accessTokenExpireTime; // 分钟@Value("${jwt.refreshTokenExpireTime}")private long refreshTokenExpireTime; // 天/*** 生成 Access Token*/public String generateAccessToken(User user) {Map<String, Object> claims = new HashMap<>();claims.put("username", user.getUsername());claims.put("roles", user.getRoles());return generateToken(user.getId().toString(), claims, accessTokenExpireTime * 60 * 1000);}/*** 生成 Refresh Token*/public String generateRefreshToken(User user) {return generateToken(user.getId().toString(), null, refreshTokenExpireTime * 24 * 60 * 60 * 1000);}/*** 生成 Token*/private String generateToken(String subject, Map<String, Object> claims, long expireTime) {Date now = new Date();Date expireDate = new Date(now.getTime() + expireTime);return Jwts.builder().setHeaderParam("typ", "JWT").setClaims(claims).setSubject(subject).setIssuedAt(now).setExpiration(expireDate).signWith(SignatureAlgorithm.HS512, secret).compact();}/*** 解析 Token*/public Claims parseToken(String token) {try {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();} catch (Exception e) {return null;}}/*** 验证 Token 是否过期*/public boolean isTokenExpired(String token) {Claims claims = parseToken(token);if (claims == null) {return true;}Date expiration = claims.getExpiration();return expiration.before(new Date());}
}

十三、JWT 与 Session 混合使用的实践方案

在一些大型系统中,可能存在不同端口或子系统使用不同的认证方式(如后台管理系统用 Session,移动端用 JWT),这时可以采用 混合认证策略

1. 使用建议

模块建议认证方式
管理后台(单体、Spring MVC)使用 Session(Cookie 自动管理,方便权限控制)
移动端 / 小程序 / H5使用 JWT(无状态认证,跨域安全,适合 API)
多端统一用户体系JWT + Session 混合,并通过 Redis 存储登录状态

2. 核心实现思路

  • 登录成功时,服务端生成 JWT,同时创建一个短 Session,用于后台系统交互;
  • Redis 中统一存储用户 Token 状态,便于管理和失效控制;
  • 拦截器判断请求来源(如是否含 Authorization),自动适配认证方式。

十四、常见问题 FAQ

Q1:JWT 一旦泄露是否会被无限使用?

是的,如果没有设置过期时间或失效机制(如黑名单),Token 会一直有效。所以必须:

  • 设置过期时间;
  • 使用 HTTPS;
  • 实现登出逻辑(Redis 黑名单);

Q2:JWT 是不是比 Session 更安全?

不完全正确。JWT 只是在无状态架构下更合适,但它暴露信息在客户端,若加密不严密,反而更容易被篡改或伪造。而 Session 只存在服务端,反而更隐蔽和安全。

Q3:JWT 必须存放在 LocalStorage 吗?

不一定。也可以存放在:

  • LocalStorage(常见方式,刷新页面不丢失);
  • SessionStorage(更安全,但刷新页面会清空);
  • HttpOnly Cookie(防 XSS,但不支持 JS 访问,需配合后端设置跨域 Cookie);

十六、推荐学习与实践路径

1. 学会使用 Spring MVC + Session 登录机制

在 Spring MVC 项目中,Session 登录是一种传统且有效的认证方式。
登录接口实现
通过 HttpSession 对象将用户信息存入 Session:

@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, HttpSession session) {User user = userService.login(username, password);if (user != null) {session.setAttribute("user", user); // 存入 Sessionreturn "redirect:/home"; // 登录成功跳转}return "login"; // 登录失败返回登录页
}

拦截器验证登录状态
编写拦截器检查 Session 中是否存在用户信息:

@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();User user = (User) session.getAttribute("user");if (user == null) { // 未登录则重定向到登录页response.sendRedirect("/login");return false;}return true; // 已登录,允许访问}
}

注册拦截器
在 Spring MVC 配置类中指定拦截路径(如 /api/**)和排除路径(如 /login):

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**") // 拦截所有 API 接口.excludePathPatterns("/login", "/static/**"); // 排除登录页和静态资源}
}

2. 掌握前后端分离项目中 JWT 的基本使用方式

JWT 工具类实现
生成和解析 Token,包含过期时间和签名加密:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;public class JwtUtil {private static final String SECRET = "your_secret_key_keep_it_secure"; // 密钥(需保密)private static final long EXPIRATION_TIME = 3600000; // 1小时(毫秒)// 生成 Tokenpublic static String generateToken(String username) {Claims claims = Jwts.claims().setSubject(username); // 载荷存储用户标识Date now = new Date();Date expiration = new Date(now.getTime() + EXPIRATION_TIME); // 设置过期时间return Jwts.builder().setClaims(claims).setIssuedAt(now).setExpiration(expiration).signWith(SignatureAlgorithm.HS256, SECRET) // HS256 签名算法.compact();}// 解析 Tokenpublic static Claims parseToken(String token) {try {return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody(); // 成功解析返回载荷} catch (Exception e) {return null; // 解析失败返回 null}}
}

登录接口返回 Token
验证用户信息后生成 Token 并返回给前端:

@PostMapping("/login")
public ResponseEntity<Map<String, String>> login(@RequestBody UserLoginRequest request) {User user = userService.authenticate(request.getUsername(), request.getPassword());if (user != null) {String token = JwtUtil.generateToken(user.getUsername());Map<String, String> result = new HashMap<>();result.put("token", token);return ResponseEntity.ok(result); // 返回 Token}return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null); // 认证失败
}

后端验证 Token
通过拦截器从请求头中获取 Token 并解析验证:

public class JwtInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7); // 去除 "Bearer " 前缀Claims claims = JwtUtil.parseToken(token);if (claims != null) {// 解析成功,将用户信息存入请求(如用户 ID、角色)request.setAttribute("userId", claims.getSubject());return true;}}response.setStatus(HttpStatus.UNAUTHORIZED); // 未认证或 Token 无效return false;}
}

3. 实现 Token 过期 + 刷新机制

双 Token 设计

  • AccessToken:短有效期(如 1 小时),用于接口认证;
  • RefreshToken:长有效期(如 7 天),用于刷新 AccessToken。

登录时返回双 Token

@PostMapping("/login")
public ResponseEntity<Map<String, String>> login(@RequestBody UserLoginRequest request) {User user = userService.authenticate(request.getUsername(), request.getPassword());if (user != null) {String accessToken = JwtUtil.generateToken(user.getUsername(), "access"); // 短过期String refreshToken = JwtUtil.generateToken(user.getUsername(), "refresh"); // 长过期Map<String, String> tokens = new HashMap<>();tokens.put("accessToken", accessToken);tokens.put("refreshToken", refreshToken);return ResponseEntity.ok(tokens);}return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
}

刷新 Token 接口
使用 RefreshToken 生成新的 AccessToken:

@PostMapping("/refresh-token")
public ResponseEntity<Map<String, String>> refreshToken(@RequestHeader("Refresh-Token") String refreshToken) {Claims claims = JwtUtil.parseToken(refreshToken);if (claims != null && "refresh".equals(claims.get("type"))) { // 验证 Token 类型String username = claims.getSubject();String newAccessToken = JwtUtil.generateToken(username, "access"); // 生成新 AccessTokenMap<String, String> result = new HashMap<>();result.put("accessToken", newAccessToken);return ResponseEntity.ok(result);}return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
}

在这里插入图片描述

4. 实现 Redis 黑名单、登录限制、踢出机制

Redis 黑名单
用户登出时将 Token 加入 Redis 黑名单,设置与 Token 剩余有效期一致的过期时间:

@Autowired
private RedisTemplate<String, Object> redisTemplate;// 登出逻辑
public void logout(String token) {Claims claims = JwtUtil.parseToken(token);if (claims != null) {long expireTime = claims.getExpiration().getTime() - System.currentTimeMillis();if (expireTime > 0) {redisTemplate.opsForValue().set("blacklist:" + token, "invalid", expireTime, TimeUnit.MILLISECONDS);}}
}// 拦截器中检查黑名单
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("Authorization");if (redisTemplate.hasKey("blacklist:" + token)) { // 存在于黑名单则拒绝访问response.setStatus(HttpStatus.UNAUTHORIZED);return false;}// 其他验证逻辑...return true;
}

登录频率限制
使用 Redis 记录用户登录次数,限制每分钟最多 5 次尝试:

public boolean checkLoginFrequency(String username) {String key = "login:attempts:" + username;Integer count = (Integer) redisTemplate.opsForValue().get(key);if (count != null && count >= 5) { // 超过限制return false; // 禁止登录}// 次数加 1,设置过期时间 1 分钟redisTemplate.opsForValue().increment(key, 1);redisTemplate.expire(key, 1, TimeUnit.MINUTES);return true;
}

管理员踢出用户
将用户所有有效 Token 加入黑名单(需结合用户 ID 批量操作):

public void kickUser(String userId) {// 查询用户所有有效 Token(需业务系统存储 Token 与用户的映射)List<String> tokens = tokenRepository.findByUserId(userId);tokens.forEach(token -> logout(token)); // 批量加入黑名单
}

5. 掌握 Spring Security 对 JWT 的整合

自定义 JWT 认证过滤器
继承 OncePerRequestFilter,解析 Token 并设置安全上下文:

public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtUtil jwtUtil;public JwtAuthenticationFilter(JwtUtil jwtUtil) {this.jwtUtil = jwtUtil;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7);Claims claims = jwtUtil.parseToken(token);if (claims != null) {String username = claims.getSubject();// 构建认证对象(可添加角色权限)Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));SecurityContextHolder.getContext().setAuthentication(authentication); // 设置安全上下文}}filterChain.doFilter(request, response); // 继续执行后续过滤器}
}

Spring Security 配置
禁用 CSRF,添加 JWT 过滤器并配置权限规则:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final JwtUtil jwtUtil;public SecurityConfig(JwtUtil jwtUtil) {this.jwtUtil = jwtUtil;}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable() // 前后端分离场景禁用 CSRF.authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll() // 允许登录接口.antMatchers("/admin/**").hasRole("ADMIN") // 管理员接口需 ADMIN 角色.anyRequest().authenticated() // 其他接口需认证.and().addFilterBefore(new JwtAuthenticationFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class); // 添加 JWT 过滤器}
}

通过 Spring Security 的整合,可更便捷地实现细粒度权限控制(如 @PreAuthorize 注解)和安全策略管理。

相关文章:

Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解

Spring Boot 登录实现&#xff1a;JWT 与 Session 全面对比与实战讲解 2025.5.21-23:11今天在学习黑马点评时突然发现用的是与苍穹外卖jwt不一样的登录方式-Session&#xff0c;于是就想记录一下这两种方式有什么不同 在实际开发中&#xff0c;登录认证是后端最基础也是最重要…...

vscode离线安装组件工具vsix

1.外网下载vsix 网址为&#xff1a;Open VSX Registry 2.输入需要下载的组件 3.下载组件 4.安装 5.选择安装文件 6.安装完成...

Vue大数据量前端性能优化策略

文章目录 前言Vue大数据量前端性能优化策略1. 虚拟列表的使用方式及优势2. 列表和图表的懒加载技术3. Web Worker 在图表数据预处理中的应用4. 图表渲染优化技巧5. 分批渲染技术实现方法&#xff08;如 requestIdleCallback&#xff09;6. 其他可行的 Vue 层优化策略 前言 Vue…...

Hass-Panel - 开源智能家居控制面板

文章目录 ▎项目介绍&#xff1a;预览图▎主要特性安装部署Docker方式 正式版Home Assistant Addon方式详细安装方式1. Home Assistant 插件安装&#xff08;推荐&#xff09;2. Docker 安装命令功能说明 &#xff1a;3. Docker Compose 安装升级说明Docker Compose 版本升级 功…...

iPaaS集成平台技术选型关注哪些指标?

在数字化转型进程中&#xff0c;企业系统间的数据孤岛问题日益凸显。根据IDC调研&#xff0c;85%的IT决策者将“系统集成效率”列为业务创新的关键瓶颈。iPaaS&#xff08;集成平台即服务&#xff09;凭借其敏捷性、低代码特性和智能化能力&#xff0c;已成为企业构建数字生态的…...

JavaScript性能优化实战(14):跨端JavaScript性能优化

在当今多端开发的时代,JavaScript已经突破了浏览器的界限,广泛应用于移动应用、桌面应用、小程序等各类环境。然而,不同平台的运行时环境存在差异,为JavaScript性能优化带来了新的挑战和思考维度。 目录 React Native性能优化最佳实践Electron应用性能优化策略混合应用中J…...

多通道经颅直流电刺激器产品及解决方案特色解析

前记 团队在多通道经颅直流电刺激这个技术方向&#xff0c;一路深耕。在服务了不少客户之后&#xff0c;为了方便后续的产品和方案推广。我们弄出来了产品和方案两种形态。标准产品是为了给用户演示以及一些常规的实验使用。方案则是为了满足不同方向的科研用户的需求。这两者相…...

Quasar 使用 Pinia 进行状态管理

官方文档&#xff1a;使用 Pinia 进行状态管理 |Quasar 框架 视频教程&#xff1a;quasar框架store-状态管理库pinia介绍_哔哩哔哩_bilibili 使用 Quasar CLI 创建一个新的store quasar new store date --format jsPinia存储模板详解解 基本结构解析 import { defineStore,…...

计算机网络--第一章(下)

1.计算机网络的分层结构 1.1 分层结构 网络体系结构描述的是&#xff0c;计算机网络有几层&#xff0c;有什么功能&#xff0c;用的什么协议。 水平方向的关系&#xff0c; 协议&#xff0c;说的是对等实体间通信需要遵守的规则。用于约束&#xff0c;这个约束的方向是水平的。…...

Veo 3 可以生成视频,并附带配乐

谷歌最新的视频生成 AI 模型 Veo 3 可以创建与其生成的剪辑相配的音频。 周二&#xff0c;在谷歌 I/O 2025 开发者大会上&#xff0c;谷歌发布了 Veo 3。该公司声称&#xff0c;这款产品可以生成音效、背景噪音&#xff0c;甚至对话&#xff0c;为其制作的视频增添配乐。谷歌表…...

数据结构核心知识总结:从基础到应用

数据结构核心知识总结&#xff1a;从基础到应用 数据结构是计算机科学中组织和存储数据的核心方式&#xff0c;直接影响程序的性能和资源利用率。本文系统梳理常见数据结构及其应用场景&#xff0c;帮助读者构建清晰的知识体系。 一、数据结构基础概念 数据结构是数据元素之间…...

Flannel后端为UDP模式下,分析数据包的发送方式(二)

发往 10.244.2.5 的数据包最终会经过物理网卡 enp0s3&#xff0c;尽管路由表直接指定通过 flannel.1 发出。以下以 Markdown 格式详细解释为什么会经过 enp0s3&#xff0c;结合 Kubernetes 和 Flannel UDP 模式的背景。 问题分析 在 Kubernetes 环境中&#xff0c;使用 Flanne…...

超低延迟音视频直播技术的未来发展与创新

引言 音视频直播技术正在深刻改变着我们的生活和工作方式&#xff0c;尤其是在教育、医疗、安防、娱乐等行业。无论是全球性的体育赛事、远程医疗、在线教育&#xff0c;还是智慧安防、智能家居等应用场景&#xff0c;都离不开音视频技术的支持。为了应对越来越高的需求&#x…...

改写视频生产流程!快手SketchVideo开源:通过线稿精准控制动态分镜的AI视频生成方案

Sketch Video 的核心特点 Sketch Video 通过手绘生成动画的形式&#xff0c;将复杂的信息以简洁、有趣的方式展现出来。其核心特点包括&#xff1a; 超强吸引力 Sketch Video 的手绘风格赋予了视频一种质朴而真实的质感&#xff0c;与常见的精致特效视频形成鲜明对比。这种独…...

Circle宣布Circle Payments Network主网上线

据 Circle 官方消息&#xff0c;Circle Payments Network 主网正式上线。该网络是一个基于区块链的支付协调协议&#xff0c;允许银行和支付服务提供商使用公共区块链上的 USDC 进行实时结算。 Circle Payments Network 支持企业对企业供应商支付、跨境汇款、资金管理、企业定期…...

【RabbitMQ】记录 InvalidDefinitionException: Java 8 date/time type

目录 1. 添加必要依赖 2. 配置全局序列化方案&#xff08;推荐&#xff09; 3. 配置RabbitMQ消息转换器 关键点说明 1. 添加必要依赖 首先确保项目中包含JSR-310支持模块&#xff1a; <dependency><groupId>com.fasterxml.jackson.datatype</groupId>&l…...

linux 学习之位图(bitmap)数据结构

bitmap 可以高效地表示大量的布尔值&#xff0c;并且在许多情况下可以提供快速的位操作。 1 定义 enum device_state{DOWN,DOEN_DONE,MAILBOX_READY,MAILBOX_PENDING,STATE_BUILD };DECLARE_BITMAP(state,STATE_BUILD)&#xff1b;相当于》u32 state[BITS_TO_LONGS(4)] BIT…...

CNN手写数字识别/全套源码+注释可直接运行

数据集选择&#xff1a; MNIST数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST)。训练集&#xff08;training set&#xff09;由来自250个不同人手写的数字构成&#xff0c;其中50%是高中学生&#xff0c;50%来自人口普查局&…...

基于springboot+vue网页系统的社区义工服务互动平台(源码+论文+讲解+部署+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统背景 在社会文明程度不断提升、社区治理需求持续深化的大背景下&#xff0c;社区义工服务作为…...

MBSS-T1:基于模型的特定受试者自监督运动校正方法用于鲁棒心脏 T1 mapping|文献速递-深度学习医疗AI最新文献

Title 题目 MBSS-T1: Model-based subject-specific self-supervised motion correction forrobust cardiac T1 mapping MBSS-T1&#xff1a;基于模型的特定受试者自监督运动校正方法用于鲁棒心脏 T1 mapping 01 文献速递介绍 心脏T1定量成像&#xff08;Quantitative Car…...

Google机器学习实践指南(迭代学习机制解析篇)

&#x1f525; Google机器学习(5)-迭代学习机制解析 Google机器学习实战(5)-深入理解模型训练中的迭代优化过程 一、迭代学习概念 ▲ 核心定义&#xff1a; 在训练机器学习模型时&#xff0c;首先对权重和偏差进行初始猜测&#xff0c;然后反复调整这些猜测&#xff0c;直到…...

【时时三省】Python 语言----文件

目录 1,文件打开 2, 文件关闭 3, 文件写入 4, 文件读出 5, 文件定位 6, 文件重命名 7, 复制文件 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,文件打开 file = open(file, mode, buffering, encoding, errors, newline, closefd, opener) 2, 文…...

WPF···

设置启动页 默认最后一个窗口关闭,程序退出,可以设置 修改窗体的icon图标 修改项目exe图标 双击项目名会看到代码 其他 在A窗体点击按钮打开B窗体,在B窗体设置WindowStartupLocation=“CenterOwner” 在A窗体的代码设置 B.Owner = this; B.Show(); B窗体生成在A窗体中间…...

架构图 C4 规范简介

架构图 C4 规范简介 C4&#xff08;Context, Containers, Components, Code&#xff09;是一种用于软件架构可视化的分层建模方法&#xff0c;由 Simon Brown 提出。它通过四个不同层次的抽象来描述软件系统&#xff0c;适用于不同受众&#xff08;如业务人员、架构师、开发人…...

运维Web服务器核心知识与实战指南

一、Web服务器基础概述 &#xff08;一&#xff09;核心定义与功能 Web服务器是互联网的基础设施&#xff0c;负责存储、处理和传输网页内容&#xff0c;通过HTTP/HTTPS协议与客户端交互。其核心功能包括&#xff1a; 请求处理&#xff1a;监听端口&#xff08;默认80/443&a…...

免费建站系统是什么?如何选择免费建站系统?

如今&#xff0c;换互联网成为大家生活中必不可少的一部分。对于普通的个人、一些企业、包括一些事业单位&#xff0c;拥有一个高效实用的网站成为展示、宣传、产品介绍的重要途径。但是对于很多用户来说&#xff0c;对于一些没有建站基础的用户来说&#xff1a;建站是一项高门…...

React---day1

React 它允许我们只需要维护自己的状态&#xff0c;当状态改变时&#xff0c;React可以根据最新的状态去渲染我们的UI界面 开发React必须依赖三个库&#xff1a; eact&#xff1a;包含react所必须的核心代码react-dom&#xff1a;react渲染在不同平台所需要的核心代码babel&…...

赋能智慧党建:远眺科技助力党校可视化系统高效落地

项目背景&#xff1a;智慧党校建设的时代召唤 在数字化浪潮席卷各行各业的今天&#xff0c;传统党校亦面临转型升级的迫切需求。 宁波某地党校&#xff0c;积极响应国家关于推进“智慧党建”的号召&#xff0c;旨在通过引入先进信息技术&#xff0c;打造一个集数据展示、信息…...

解决使用HBuilder X开发时uView组件不生效的问题

1.uni-ui 是一个为 uni-app 开发的 UI 组件库&#xff0c;你可以通过 npm 安装它。 在项目的根目录下打开终端&#xff08;可以通过菜单“工具” > “终端”打开&#xff09;&#xff0c;然后运行以下命令来安装 uni-ui&#xff1a; npm install uview-ui2.安装后&#xff…...

React中 lazy与 Suspense懒加载的组件

MyHead.jsx console.log(MyHead.jsx); function Head() {return <>hello Head</>; } export default Head;懒加载.jsx // 引入 React 的 useState、lazy 和 Suspense API // lazy 用于懒加载组件&#xff0c;Suspense 用于在加载过程中显示 loading 状态 import …...

网络学习-利用reactor实现http请求(六)

一、实现HTTP请求 1、印象里面&#xff0c;总有人说C/C语言不能实现HTTP请求&#xff0c;其实不然。C/C语言完全可以实现HTTP请求。通过对select,poll,epoll等IO多路复用技术的学习以及reactor模式的学习&#xff0c;完全能够实现HTTP请求。 2、webserver 主要解决两个问题 …...

【东枫科技】usrp rfnoc 开发环境搭建

作者 太原市东枫电子科技有限公司 &#xff0c;代理销售 USRP&#xff0c;Nvidia&#xff0c;等产品与技术支持&#xff0c;培训服务。 环境 Ubuntu 20.04 依赖包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …...

RabbitMQ的其中工作模式介绍以及Java的实现

文章目录 前文一、模式介绍1. 简单模式2. 工作队列模式3. 广播模式4. 路由模式5. 通配符模式6. RPC模式7. 发布确认模式 二、代码实现1、简单模式2、工作队列模式生产者消费者消费者 1消费者 2 3、广播模式 (Fanout Mode)生产者消费者 4、路由模式 (Direct Mode)生产者消费者 5…...

Docker 镜像打包到本地

保存镜像 使用 docker save 命令将镜像保存为一个 tar 文件。命令格式如下&#xff1a; docker save [options] IMAGE [IMAGE...]示例&#xff1a;docker save -o centos.tar centos:latest--output 或 -o&#xff1a;将输出保存到指定的文件中。 加载镜像 如果需要在其他机器…...

5分钟搭建智能看板:衡石科技自助式BI工具使用教程

在数据驱动的时代&#xff0c;业务人员需要快速将数据转化为洞察&#xff0c;而非依赖IT团队排队开发报表。衡石科技HENGSHI SENSE的自助式BI工具&#xff0c;通过零代码配置、模板化设计、智能分析三大核心能力&#xff0c;让任何人都能在5分钟内搭建专业级数据看板。本文将手…...

安卓开发用到的设计模式(1)创建型模式

安卓开发用到的设计模式&#xff08;1&#xff09;创建型模式 文章目录 安卓开发用到的设计模式&#xff08;1&#xff09;创建型模式1. 单例模式&#xff08;Singleton Pattern&#xff09;2. 工厂模式&#xff08;Factory Pattern&#xff09;3. 抽象工厂模式&#xff08;Abs…...

Unity3D序列化机制详解

前言 Unity3D的序列化机制是其编辑器与运行时数据管理的核心&#xff0c;理解其工作原理对高效开发至关重要。以下是关键点总结&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀&#xff01; 1. 序列化的作…...

[Harmony]自定义导航栏

1.方案一 CustomNavigationBar import { router } from kit.ArkUI; import { DevicesUtil } from ../utils/DevicesUtil; import { common } from kit.AbilityKit;Component export struct CustomNavigationBar {State private navHeight: number 44State parTitle: string …...

LeetCode117_填充每个结点的下一个右侧结点指针Ⅱ

LeetCode117_填充每个结点的下一个右侧结点指针Ⅱ 标签&#xff1a;#树 #深度优先遍历 #广度优先遍历 #链表 #二叉树Ⅰ. 题目Ⅱ. 示例 0. 个人方法 标签&#xff1a;#树 #深度优先遍历 #广度优先遍历 #链表 #二叉树 Ⅰ. 题目 给定一个二叉树&#xff1a; struct Node {int v…...

Qt enabled + geometry 属性(2)

文章目录 enabled属性可用与禁用的概念API接口代码演示 阐述说明1. 先简单描述下要如何演示出上面两个接口的效果&#xff08;思路&#xff09;2. 事先规范按钮对象的命名3. 定义两个按钮对象的槽函数 动图演示效果4. widget.cpp geometry属性预备知识API接口上下左右移动 ta…...

OpenHarmony外设驱动使用 (十),Sensor

OpenHarmony外设驱动使用 &#xff08;十&#xff09; Sensor 概述 功能简介 Sensor驱动模型屏蔽硬件器件差异&#xff0c;为上层Sensor服务系统提供稳定的Sensor基础能力接口&#xff0c;包括Sensor列表查询、Sensor启停、Sensor订阅及取消订阅&#xff0c;Sensor参数配置等…...

(2025小白全踩坑版)【OpenHarmony】移植 3.1 版本系统到 STM32F407ZG开发板

在上stm32课程&#xff0c;有这样一道要求&#xff1a; 参考了大佬的文章之后&#xff0c;发现出现了liteos_m.mk文件找不到的情况&#xff0c;于是只能另寻他路 VSCode 搭建 STM32 开发环境_vscode stm32仿真-CSDN博客 【OpenHarmony】移植 3.1 版本系统到 STM32_openharm…...

【HTML-4】HTML段落标签:构建内容结构的基础

在网页开发中&#xff0c;段落标签<p>是最基础也是最重要的HTML元素之一。这篇博客将深入探讨段落标签的用法、最佳实践以及相关技术细节。 1. 段落标签的基本用法 HTML段落标签用于定义文本段落&#xff0c;浏览器会自动在段落前后添加一定的空白&#xff08;margin&a…...

深度学习+Flask 打包一个AI模型接口并部署上线

🚀 深度学习 + Flask 打包一个 AI 模型接口并部署上线(实战教程) 深度学习模型训练完毕后,我们该如何部署上线让它“动起来”?本篇带你手把手用 Flask 将训练好的 PyTorch 模型封装成 Web 接口,实现一个轻量、可访问的在线 AI 服务。 🧠 一、为什么要部署模型? 训练…...

C++类与对象(二):六个默认构造函数(二)

在上篇提到了构造函数、拷贝构造函数、析构函数&#xff0c;这篇将会分享剩下默认构造函数&#xff1a;赋值运算符重载、运算符重载。当学习了这些构造函数可以实现一个日期类。 目录 运算符重载 赋值运算符重载 前置 后置 运算符重载 函数名字为&#xff1a;关键字operat…...

HarmonyOS NEXT应用开发实战:玩鸿蒙App客户端开发

之前学习android时候&#xff0c;有一个玩android的客户端项目很火&#xff0c;不但能够学习知识&#xff0c;还能够动手实践&#xff0c;激发学习兴趣。这里作者通过一个完整的实战项目—玩鸿蒙客户端App&#xff0c;一块儿深入学习如何在HarmonyOS平台上开发一个功能丰富且完…...

十六、面向对象底层逻辑-BeanPostProcessor接口设计

一、引言&#xff1a;Bean生命周期的精密控制 在Spring容器的Bean实例化过程中&#xff0c;BeanPostProcessor接口是开发者介入对象初始化阶段的核心扩展点。作为Spring框架最强大的扩展机制之一&#xff0c;该接口提供了对Bean实例化过程的原子级控制能力&#xff0c;支撑了A…...

在线免费图片处理工具-传道软件图片工具

在线免费图片处理工具-传道软件图片工具 在线免费图片处理工具&#xff0c;无需注册与登录&#xff0c;用完即走。 官网链接&#xff1a; https://www.chdaoai.com/image.html 功能有&#xff1a; Favicon图标生成&#xff0c;图片颜色拾取器&#xff0c;屏幕颜色拾取&…...

JS进阶学习04

一、深浅拷贝 1.浅拷贝 首先浅拷贝和深拷贝只针对引用类型 浅拷贝&#xff1a;拷贝的是地址 常见方法&#xff1a; 1. 拷贝对象&#xff1a;Object.assgin() / 展开运算符 {...obj} 拷贝对象 2. 拷贝数组&#xff1a;Array.prototype.concat() 或者 [...arr] >如果是简…...

CSS、SCSS 和 SASS 的语法差异

CSS、SCSS 和 SASS 的语法差异 CSS (Cascading Style Sheets) 标准样式表语言&#xff0c;所有浏览器原生支持语法特点&#xff1a; 使用大括号 {} 包裹规则使用分号 ; 结束声明简单的选择器-属性-值结构 .container {width: 100%;margin: 0 auto; }SCSS (Sassy CSS) CSS的…...