JWT全面理解

????????

目錄

一、JWT是什么

1、身份認證(最核心用途)

2、信息交換

3、授權控制

二、JWT的核心價值

三、如何理解JWT的結構和工作原理

1、三部分結構解析

2、核心工作流程

四、JWT的使用步驟

1、添加依賴

2、添加配置文件

3、創建實體類

4、創建JWT工具類

5、創建JWT認證攔截器

7、配置攔截器和Redis

8、創建服務層

9、創建控制器

五、核心實現

六、核心知識點的回答

1、生成token時如何設置過期時間

2、JWT有哪些安全隱患?如何解決

3、JWT 和 Session 的區別是什么??


JWT是一種基于JSON的輕量級身份認證與信息交換標準,廣泛應用于前后端分離、分布式系統、跨服務通信等場景。它通過數字簽名保證信息的完整性和可靠性,核心價值在于解決了傳統認證方案(如 Session)在跨域、分布式架構下的局限性。

一、JWT是什么

????????JWT 的本質是一串經過加密簽名的 JSON 格式字符串,用于在客戶端和服務器之間安全地傳遞 “聲明”(Claims,即用戶身份、權限等信息)。其核心作用可概括為三類:

1、身份認證(最核心用途)

????????解決 “用戶是誰” 的問題,替代傳統的 Session 認證,流程如下:

  • 用戶通過賬號密碼登錄,服務器驗證通過后,生成包含用戶唯一標識(如 user_id)、過期時間等信息的 JWT;
  • 服務器將 JWT 直接返回給客戶端(無需存儲在服務器);
  • 后續客戶端發起請求時,在 HTTP 頭(如 Authorization: Bearer <JWT>)中攜帶 JWT
  • 服務器接收請求后,驗證 JWT 的簽名和有效性(如是否過期、是否被篡改),驗證通過即可確認用戶身份,無需查詢數據庫或緩存。
2、信息交換

????????解決 “安全傳遞數據” 的問題。由于 JWT 帶有數字簽名,接收方可以通過簽名驗證信息是否來自合法發送方,且未被篡改。

????????分布式系統中服務間通信(如微服務 A 向微服務 B 傳遞用戶權限信息)、跨組織數據交換(如第三方登錄后,平臺間傳遞用戶基本信息)。

3、授權控制

????????解決 “用戶能做什么” 的問題。可在 JWT 中嵌入用戶權限信息(如 role: admin、permissions: ["read", "write"]),服務器驗證 JWT 后,直接從載荷中讀取權限,無需額外查詢權限數據庫。

????????后臺管理系統中,根據 JWT 中的 role 字段判斷用戶是否有權訪問某接口(如僅管理員可調用 “刪除用戶” 接口)。

二、JWT的核心價值

對比傳統的 Session 認證(服務器存儲用戶會話,客戶端保存 Session ID),JWT 的價值主要體現在以下 4 點:

特性

JWT 方案

傳統 Session 方案

價值體現

無狀態(Stateless)

服務器不存儲任何會話信息,僅通過 JWT 驗證身份

服務器需存儲 Session(內存 / 數據庫 / Redis)

減輕服務器存儲壓力,支持高并發;無需考慮 Session 同步(分布式系統友好)

跨域 / 跨服務

基于 HTTP 頭傳遞,支持跨域名、跨服務通信

依賴 Cookie,受 “同源策略” 限制,跨域需額外配置

適配前后端分離(前端部署在 CDN,后端在另一域名)、微服務架構

輕量化

字符串格式,體積小,傳輸速度快

需攜帶 Session ID,且服務器需查詢 Session 詳情

減少網絡傳輸開銷,提升接口響應速度(尤其移動端弱網場景)

自包含(Self-contained)

載荷中包含用戶核心信息(如 ID、權限)

僅存儲 Session ID,需查詢數據庫獲取用戶信息

減少數據庫查詢次數(驗證身份時無需查庫),提升系統性能

三、如何理解JWT的結構和工作原理

????????JWT 由三部分組成,用英文句號(.)分隔,格式為 Header.Payload.Signature,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

eyJ1c2VyX2lkIjoiMTIzIiwidXNlcm5hbWUiOiJ6aGFuZ3NhbiIsImV4cCI6MTY4OTAxNjQwMH0.

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1、三部分結構解析
  • Header(頭部):聲明 JWT 的類型(typ,固定為 JWT)和使用的簽名算法(alg,如 HS256 哈希算法、RS256 非對稱加密算法)。格式是JSON字符串,是可逆的,僅編碼而非加密。
  • Payload(載荷):存儲核心 “聲明”(用戶信息、過期時間等)。JSON 字符串,同樣經過 Base64 編碼(可逆!不要存儲密碼、手機號等敏感信息)。
  • Signature(簽名):保證 JWT 不被篡改,是 JWT 安全性的核心。拼接編碼后的 Header 和 Payload,使用 Header 中聲明的算法(如 HS256),結合服務器端的密鑰(Secret) 對拼接字符串進行加密,得到簽名。
2、核心工作流程
  • 簽發:用戶登錄成功 → 服務器根據用戶信息構建 Payload → 結合 Header 密鑰生成 Signature → 拼接三部分得到 JWT 并返回給客戶端;
  • 存儲:客戶端將 JWT 存儲在 localStorage、sessionStorage 或 Cookie 中;
  • 攜帶:客戶端發起請求時,在 Authorization 頭中攜帶 JWT(Bearer <JWT>);
  • 驗證:服務器解析 JWT → 驗證簽名(防篡改)→ 檢查過期時間(exp)→ 提取用戶信息 → 處理業務邏輯。

四、JWT的使用步驟

例如我現在實現用戶登錄的功能,我要通過JWT進行安全認證的步驟如下:

1、添加依賴
 <dependencies><!-- Spring Boot Web 依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- JWT 工具庫 --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!-- Redis 依賴 (用于存儲刷新令牌) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Lombok 簡化代碼 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>
2、添加配置文件
spring:redis:host: localhostport: 6379# JWT配置
jwt:secret: your-secret-key-1234567890-abcdefg # 密鑰,生產環境要復雜且保密access-token-expire: 3600000  # 訪問令牌過期時間(毫秒),1小時refresh-token-expire: 604800000  # 刷新令牌過期時間(毫秒),7天
3、創建實體類
package com.example.jwtdemo.entity;import lombok.Data;@Data
public class Result<T> {private int code; // 狀態碼:200成功,401未授權,500服務器錯誤等private String message; // 提示信息private T data; // 響應數據// 成功返回public static <T> Result<T> success(T data) {Result<T> result = new Result<>();result.setCode(200);result.setMessage("成功");result.setData(data);return result;}// 失敗返回public static <T> Result<T> error(int code, String message) {Result<T> result = new Result<>();result.setCode(code);result.setMessage(message);return result;}
}
package com.example.jwtdemo.entity;import lombok.Data;@Data
public class TokenDTO {private String accessToken; // 訪問令牌private String refreshToken; // 刷新令牌
}
package com.example.jwtdemo.entity;import lombok.Data;@Data
public class User {private Integer id;private String username;private String password;private String role; // 角色,如"USER"或"ADMIN"
}
4、創建JWT工具類
package com.example.jwtdemo.util;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;
import java.util.function.Function;@Component
public class JwtUtil {@Value("${jwt.secret}")private String secretKey;@Value("${jwt.access-token-expire}")private long accessTokenExpire;@Value("${jwt.refresh-token-expire}")private long refreshTokenExpire;// 從令牌中獲取用戶名public String getUsernameFromToken(String token) {return getClaimFromToken(token, Claims::getSubject);}// 從令牌中獲取過期時間public Date getExpirationDateFromToken(String token) {return getClaimFromToken(token, Claims::getExpiration);}// 從令牌中獲取自定義聲明public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {final Claims claims = getAllClaimsFromToken(token);return claimsResolver.apply(claims);}// 解析令牌,獲取所有聲明private Claims getAllClaimsFromToken(String token) {return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();}// 檢查令牌是否過期private Boolean isTokenExpired(String token) {final Date expiration = getExpirationDateFromToken(token);return expiration.before(new Date());}// 生成訪問令牌public String generateAccessToken(String username, String role) {Map<String, Object> claims = new HashMap<>();claims.put("role", role); // 存儲角色信息return doGenerateToken(claims, username, accessTokenExpire);}// 生成刷新令牌public String generateRefreshToken(String username) {return doGenerateToken(new HashMap<>(), username, refreshTokenExpire);}// 實際生成令牌的方法private String doGenerateToken(Map<String, Object> claims, String subject, long expiration) {return Jwts.builder().setClaims(claims).setSubject(subject) // 用戶名作為主題.setIssuedAt(new Date(System.currentTimeMillis())) // 簽發時間.setExpiration(new Date(System.currentTimeMillis() + expiration)) // 過期時間.signWith(SignatureAlgorithm.HS512, secretKey) // 簽名算法和密鑰.compact();}// 驗證令牌public Boolean validateToken(String token, String username) {final String tokenUsername = getUsernameFromToken(token);return (tokenUsername.equals(username) && !isTokenExpired(token));}
}
5、創建JWT認證攔截器
package com.example.jwtdemo.config;import com.example.jwtdemo.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class JwtInterceptor implements HandlerInterceptor {@Autowiredprivate JwtUtil jwtUtil;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 從請求頭中獲取令牌String authorizationHeader = request.getHeader("Authorization");// 檢查令牌是否存在且格式正確if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("未提供有效的令牌");return false;}// 提取令牌(去掉"Bearer "前綴)String token = authorizationHeader.substring(7);try {// 從令牌中獲取用戶名String username = jwtUtil.getUsernameFromToken(token);// 驗證令牌if (!jwtUtil.validateToken(token, username)) {throw new Exception("令牌無效");}// 令牌有效,將用戶名存入請求屬性,供后續使用request.setAttribute("username", username);return true;} catch (Exception e) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("令牌驗證失敗:" + e.getMessage());return false;}}
}
7、配置攔截器和Redis
package com.example.jwtdemo.config;import org.springframework.context.annotation.Bean;
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 WebConfig implements WebMvcConfigurer {// 注冊JWT攔截器@Beanpublic JwtInterceptor jwtInterceptor() {return new JwtInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 配置攔截器應用的路徑registry.addInterceptor(jwtInterceptor()).addPathPatterns("/api/**") // 攔截/api/**路徑的請求.excludePathPatterns("/api/login") // 不攔截登錄接口.excludePathPatterns("/api/refresh-token"); // 不攔截刷新令牌接口}
}
8、創建服務層
package com.example.jwtdemo.service;import com.example.jwtdemo.entity.TokenDTO;
import com.example.jwtdemo.entity.User;public interface UserService {// 用戶登錄TokenDTO login(String username, String password);// 刷新訪問令牌String refreshToken(String refreshToken);// 注銷登錄void logout(String username);// 根據用戶名獲取用戶信息User getUserByUsername(String username);
}
package com.example.jwtdemo.service.impl;import com.example.jwtdemo.entity.TokenDTO;
import com.example.jwtdemo.entity.User;
import com.example.jwtdemo.service.UserService;
import com.example.jwtdemo.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate JwtUtil jwtUtil;@Autowiredprivate StringRedisTemplate redisTemplate;// 模擬數據庫中的用戶private static final User mockUser = new User();static {mockUser.setId(1);mockUser.setUsername("admin");mockUser.setPassword("123456");mockUser.setRole("ADMIN");}@Overridepublic TokenDTO login(String username, String password) {// 驗證用戶名密碼(實際項目中應查詢數據庫)if (!mockUser.getUsername().equals(username) || !mockUser.getPassword().equals(password)) {throw new RuntimeException("用戶名或密碼錯誤");}// 生成令牌String accessToken = jwtUtil.generateAccessToken(username, mockUser.getRole());String refreshToken = jwtUtil.generateRefreshToken(username);// 將刷新令牌存入Redis,設置過期時間redisTemplate.opsForValue().set("refresh_token:" + username, refreshToken, 7, TimeUnit.DAYS);TokenDTO tokenDTO = new TokenDTO();tokenDTO.setAccessToken(accessToken);tokenDTO.setRefreshToken(refreshToken);return tokenDTO;}@Overridepublic String refreshToken(String refreshToken) {try {// 從刷新令牌中獲取用戶名String username = jwtUtil.getUsernameFromToken(refreshToken);// 驗證刷新令牌是否有效if (!jwtUtil.validateToken(refreshToken, username)) {throw new RuntimeException("刷新令牌無效");}// 檢查Redis中是否存在該刷新令牌String storedToken = redisTemplate.opsForValue().get("refresh_token:" + username);if (storedToken == null || !storedToken.equals(refreshToken)) {throw new RuntimeException("刷新令牌已過期或已被注銷");}// 生成新的訪問令牌User user = getUserByUsername(username);return jwtUtil.generateAccessToken(username, user.getRole());} catch (Exception e) {throw new RuntimeException("刷新令牌失敗:" + e.getMessage());}}@Overridepublic void logout(String username) {// 從Redis中刪除刷新令牌redisTemplate.delete("refresh_token:" + username);}@Overridepublic User getUserByUsername(String username) {// 實際項目中應查詢數據庫if (mockUser.getUsername().equals(username)) {return mockUser;}throw new RuntimeException("用戶不存在");}
}
9、創建控制器
package com.example.jwtdemo.controller;import com.example.jwtdemo.entity.Result;
import com.example.jwtdemo.entity.TokenDTO;
import com.example.jwtdemo.entity.User;
import com.example.jwtdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;@RestController
@RequestMapping("/api")
public class UserController {@Autowiredprivate UserService userService;// 登錄接口@PostMapping("/login")public Result<TokenDTO> login(@RequestParam String username, @RequestParam String password) {try {TokenDTO tokenDTO = userService.login(username, password);return Result.success(tokenDTO);} catch (Exception e) {return Result.error(401, e.getMessage());}}// 刷新令牌接口@PostMapping("/refresh-token")public Result<String> refreshToken(@RequestParam String refreshToken) {try {String newAccessToken = userService.refreshToken(refreshToken);return Result.success(newAccessToken);} catch (Exception e) {return Result.error(401, e.getMessage());}}// 注銷接口@PostMapping("/logout")public Result<Void> logout(HttpServletRequest request) {try {String username = (String) request.getAttribute("username");userService.logout(username);return Result.success(null);} catch (Exception e) {return Result.error(500, e.getMessage());}}// 獲取用戶信息接口(需要認證)@GetMapping("/user/info")public Result<User> getUserInfo(HttpServletRequest request) {try {String username = (String) request.getAttribute("username");User user = userService.getUserByUsername(username);// 出于安全考慮,清除密碼信息user.setPassword(null);return Result.success(user);} catch (Exception e) {return Result.error(500, e.getMessage());}}
}

五、核心實現

1、登錄流程:用戶提交用戶名密碼 → 驗證通過 → 生成 accessToken 和 refreshToken → 返回給客戶端
2、認證流程:客戶端請求帶 accessToken → 攔截器驗證 token → 驗證通過則允許訪問
3、令牌刷新:accessToken 過期 → 用 refreshToken 獲取新的 accessToken → 避免重新登錄
4、安全機制:

  • 密碼驗證確保用戶身份
  • 令牌簽名防止篡改
  • 短期 accessToken 減少泄露風險
  • refreshToken 存儲在 Redis 中便于注銷

六、核心知識點的回答

1、生成token時如何設置過期時間

1.1、直接指定過期時間

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;public class JwtExample {private static final String SECRET_KEY = "your-secret-key";public static String generateToken(String username) {// 直接設置過期時間為 2024-12-31 23:59:59(硬編碼,不推薦)Date expirationDate = new Date(1735689599000L); // 時間戳(毫秒)return Jwts.builder().setSubject(username) // 存儲用戶名.setExpiration(expirationDate) // 設置過期時間.signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 簽名.compact();}
}

1.2、動態計算過期時間

  • 獲取當前時間戳(System.currentTimeMillis());
  • 加上有效期(毫秒單位,如 1 小時 = 3600 * 1000 毫秒);
  • 轉換為 Date 對象傳入 setExpiration()。
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;public class JwtExample {private static final String SECRET_KEY = "your-secret-key";// 有效期:1小時(3600秒 * 1000毫秒)private static final long EXPIRATION_TIME = 3600 * 1000;public static String generateToken(String username) {// 計算過期時間:當前時間 + 有效期Date expirationDate = new Date(System.currentTimeMillis() + EXPIRATION_TIME);return Jwts.builder().setSubject(username) // 存儲用戶名.setIssuedAt(new Date()) // 簽發時間(可選,便于追蹤).setExpiration(expirationDate) // 設置過期時間.signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 簽名算法+密鑰.compact();}
}

1.3、在配置文件中管理過期時間

  • 配置文件
  • 通過@Value注入配置,動態生成過期時間
    jwt:secret: your-secret-keyaccess-token-expire: 3600000  # 訪問令牌有效期:1小時(毫秒)refresh-token-expire: 604800000  # 刷新令牌有效期:7天(毫秒)
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    import java.util.Date;@Component
    public class JwtUtil {@Value("${jwt.secret}")private String secretKey;@Value("${jwt.access-token-expire}")private long accessTokenExpire; // 從配置文件注入有效期(毫秒)// 生成訪問令牌(短期有效)public String generateAccessToken(String username) {Date expirationDate = new Date(System.currentTimeMillis() + accessTokenExpire);return Jwts.builder().setSubject(username).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS256, secretKey).compact();}
    }
    2、JWT有哪些安全隱患?如何解決
  • 隱患 1:Payload 可解碼,泄露非敏感信息(如用戶名);解決:不存儲敏感信息,僅存用戶 ID 等非敏感標識。
  • 隱患 2:令牌泄露后可被惡意使用(無法主動吊銷);解決:短期有效期 + 刷新令牌機制 + 令牌黑名單(Redis)。
  • 隱患 3:密鑰泄露導致令牌可偽造;解決:密鑰通過環境變量存儲,定期更換;使用 RS256 非對稱加密(私鑰簽名,公鑰驗證)。
  • 隱患 4:傳輸過程中被劫持;解決:全程使用 HTTPS 加密傳輸。
3、JWT 和 Session 的區別是什么?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95987.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95987.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95987.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

量子文件傳輸系統:簡單高效的文件分享解決方案

&#x1f310; 在線體驗地址&#xff1a;https://share-file.narutogis.com/ &#x1f4e4; 項目概述 量子文件傳輸系統是一款基于Python Flask開發的高效文件管理與分享工具&#xff0c;致力于提供簡單、安全、可靠的文件傳輸解決方案。系統支持用戶管理、文件上傳下載、自動…

基于 GitHub Actions 的零成本自動化部署:把 Vite/Vue3 項目一鍵發布到 GitHub Pages 的完整實戰

1. 實現自動化部署1.1. 創建 vue 項目# 1. 安裝/確認 Node.js&#xff08;>14&#xff09; node -v # 推薦 20.x# 2. 創建項目&#xff08;交互式&#xff0c;選 Vue3 Router 等&#xff09; npm init vuelatest github-actions-demo # 創建vite項目 # 或&#xff1a;v…

minio 文件批量下載

MinIO 批量下載功能說明 1. 功能描述 前端勾選多個對象文件后&#xff0c;一次性將這些對象從 MinIO 拉取并打包成 ZIP&#xff0c;通過瀏覽器直接下載。整體特性&#xff1a; 支持跨桶批量下載&#xff08;不同 bucket 的對象可同時下載&#xff09;。服務端采用流式壓縮邊…

機器學習11——特征選擇與稀疏學習

上一章&#xff1a;機器學習10——降維與度量學習 下一章&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備[TOC] 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到…

整理python快速構建數據可視化前端的Dash庫

一.Dash框架# 導入 Dash 相關庫 import dash from dash import dcc, html # dcc 是 Dash 核心組件庫&#xff0c;html 是 HTML 組件庫 from typing import Generic# 創建一個 Dash 應用實例 app dash.Dash(__name__)# 定義應用的布局 app.layout html.Div(children[# 添加一…

RNN循環神經網絡(一):基礎RNN結構、雙向RNN

RNN循環神經網絡 什么是循環神經網絡&#xff1f; 循環神經網絡&#xff08;Recurrent Neural Network, RNN&#xff09;是一類專門用于處理序列數據的神經網絡架構。與傳統的前饋神經網絡不同&#xff0c;RNN具有"記憶"能力&#xff0c;能夠捕捉數據中的時間依賴關系…

#C語言——刷題攻略:牛客編程入門訓練(十):攻克 循環控制(二),輕松拿捏!

&#x1f31f;菜鳥主頁&#xff1a;晨非辰的主頁 &#x1f440;學習專欄&#xff1a;《C語言刷題合集》 &#x1f4aa;學習階段&#xff1a;C語言方向初學者 ?名言欣賞&#xff1a;"代碼行數決定你的下限&#xff0c;算法思維決定你的上限。" 目錄 1. BC82 乘法表…

daily notes[16]

文章目錄意大利語單詞 **“bello”**一、核心含義二、變形規則&#xff1a;最重要的部分1. 當 “bello” 位于 **名詞前面** 時2. 當 “bello” 位于 **名詞后面** 或 **動詞后面** 時三、用法總結與對比四、其他用法和常見表達references意大利語單詞 “bello” 融合了 指示形…

【知識庫】計算機二級python操作題(二)

文章目錄基本操作題1基本操作題2基本操作題3簡單應用題1簡單應用題2綜合應用題1基本操作題1考生文件夾下存在一個文件PY101.py&#xff0c;請寫代碼替換橫線&#xff0c;不修改其他代碼&#xff0c;實現以下功能&#xff0c;隨機選擇一個手機品牌屏幕輸出。 # 請在...處使用一行…

Nginx 服務用戶與防盜鏈配置

目錄 Nginx 服務用戶與防盜鏈配置 1. 隱藏版本號 1.1 配置方法 1.2 生效與驗證 2. 修改當前程序賬號 2.1 操作步驟 3. 緩存時間 3.1 配置方法 3.2 說明 4. 日志分割 4.1 實現方式&#xff08;腳本自動分割&#xff09; 5. 連接超時時間 5.1 核心超時指令&#xff0…

域格4G模塊通信協議之HTTP(三):下載大文件的兩種方式

域格ASR系列模塊支持HTTP下載大文件&#xff0c;本文將提供兩種方式。一、直接通過URC上報數據基礎操作核心指令說明配置說明響應說明應用示例注意點二、HTTP Range分段下載核心指令說明注意點一、直接通過URC上報數據 若文件體積適中&#xff0c;且需要 MCU 即時處理數據&…

Android 圖片 OOM 防護機制設計:大圖加載、內存復用與多級緩存

1. 為什么圖片加載總讓 Android 開發抓狂? 圖片是 Android 應用中不可或缺的元素,從用戶頭像到高清壁紙,從商品詳情頁到動態表情包,圖片無處不在。然而,圖片加載是內存管理的雷區,稍不留神就可能觸發臭名昭著的 OutOfMemoryError(OOM)。為啥圖片這么“吃內存”?原因很…

9月9日

TCP 服務器端#include <myhead.h> #define SER_PORT 8888 //服務器端口號 #define SER_IP "192.168.108.179" //服務器IP地址 int main(int argc, const char *argv[]) {//創建一個用于連接的套接字文件描述符int sfd socket(AF_INET, SOCK_STRE…

Docker生產部署

目錄 一、準備工作&#xff1a;理解 Docker 與 Spring Boot 的關系 1. Docker 是什么&#xff1f; 2. Spring Boot 為什么適合 Docker&#xff1f; 二、編寫Dockerfile 三、配置管理 掛載外部配置文件 四、用 docker-compose 編排多服務 一、準備工作&#xff1a;理解 Do…

ARM 基礎(3)

ARM匯編與C語言函數的相互調用及參數傳遞匯編調用C函數參數傳遞規則 前4個參數通過寄存器 R0-R3 傳遞&#xff0c;超出部分從右向左壓棧。32位返回值存于 R0&#xff0c;64位整數用 R0 和 R1&#xff0c;浮點數通過 S0/D0 返回。示例&#xff1a;ARM匯編調用C函數.global _star…

OpenCV計算機視覺筆記合集

參考課程&#xff1a; 【黑馬程序員 OpenCV入門教程】 [https://www.bilibili.com/video/BV1Fo4y1d7JL] ZZHow(ZZHow1024) 學習路線 基本的圖像處理方法&#xff1a;幾何變換&#xff0c;形態學變換&#xff0c;圖像平滑&#xff0c;直方圖操作&#xff0c;模板匹配&#…

Mybatis-12 第三方緩存-EhCache

配置文檔 Ehcache配置文件ehcache.xml Java Ehcache緩存的timeToIdleSeconds和timeToLiveSeconds區別 基本介紹 1.EhCache是一個純Java的緩存框架&#xff0c;具有快速、精干等特點 2.MyBatis有自己默認的二級緩存&#xff08;前面我們已經使用過了&#xff09;&#xff0c;…

元器件--電容器

文章目錄一、技術理論??1、電容定義??2、定義式??3、單位換算??4、電容作用??5、電容特性二、組成結構??1、極板&#xff08;電極&#xff09;??????2、介質&#xff08;絕緣層&#xff09;????3、引線&#xff08;電極引出端&#xff09;????4、封裝…

【Leetcode hot 100】146.LRU緩存

問題鏈接 146.LRU緩存 問題描述 請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類&#xff1a; LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存中&#xff0c;則返回關…