JS JSON.stringify介紹(JS序列化、JSON字符串 )(遍歷輸入值的所有可枚舉屬性,將其轉換為文本表示)緩存序列化、狀態管理與時間旅行、replacer

文章目錄

  • JSON.stringify 全解析
    • 1. 基本概念
    • 2. 序列化原理
      • 1. 對于原始類型,直接轉換為對應的字符串表示
      • 2. 對于對象和數組,遞歸處理其每個屬性或元素
      • 3. 應用特殊規則處理日期、函數、Symbol 等特殊類型
      • 4. 檢測并防止循環引用
      • 5. 應用 replacer 函數或數組進行自定義轉換
      • 代碼示例
    • 3. 為什么需要序列化
      • 3.1 數據傳輸需求
      • 3.2 數據持久化
      • 3.3 數據復制
      • 3.4 跨語言通信
    • 4. 語法結構
      • 4.1 參數詳解
    • 5. 基礎用法示例
    • 6. 特殊數據類型處理
      • 6.1 原始數據類型
      • 6.2 復雜對象處理
        • 注意:默認情況下,Map、Set、RegExp 等這些特殊對象類型被轉換為空對象 `{}`,這會導致數據完全丟失。
          • 如何正確序列化這些特殊類型:要解決這個問題,需要在序列化前進行特殊處理:
          • 通用解決方案:可以創建一個通用的序列化工具函數,處理所有這些特殊類型:
    • 7. replacer 參數應用
      • 7.1 使用(匿名)函數作為 replacer
      • 7.2 使用數組作為 replacer
    • 8. 處理 toJSON 方法
    • 9. 易犯錯的場景
      • 9.1 循環引用問題
      • 9.2 數據丟失問題
      • 9.3 精度與大數問題
    • 10. 高級應用場景
      • 10.1 深拷貝實現
      • 10.2 緩存序列化
      • 10.3 狀態管理與時間旅行
    • 11. 性能考量
      • 11.1 大數據處理
    • 12. 常見陷阱與解決方案
      • 12.1 處理數值精度問題
      • 12.2 處理特殊字符
    • 13. 序列化的安全問題
    • 14. 與其他序列化方法比較
      • 14.1 JSON.stringify vs 手動序列化
      • 14.2 JSON vs 其他序列化格式
    • 15. 最佳實踐
      • 15.1 序列化前數據清理
      • 15.2 錯誤處理最佳實踐
    • 16. 總結

JSON.stringify 全解析

1. 基本概念

JSON.stringify 是 JavaScript 中的一個核心方法,用于將 JavaScript 對象或值轉換為 JSON 字符串。這個方法對于數據序列化、網絡傳輸和存儲至關重要。

2. 序列化原理

JSON.stringify 的核心原理是遍歷輸入值的所有可枚舉屬性,然后將其轉換為文本表示。這個過程遵循特定的規則和算法:

1. 對于原始類型,直接轉換為對應的字符串表示

2. 對于對象和數組,遞歸處理其每個屬性或元素

3. 應用特殊規則處理日期、函數、Symbol 等特殊類型

4. 檢測并防止循環引用

5. 應用 replacer 函數或數組進行自定義轉換

代碼示例

// 序列化內部過程偽代碼實現
function pseudoStringify(value, replacer, space) {// 檢查循環引用const seen = new WeakSet();function serialize(key, val) {// 應用 replacer 函數(如果提供)if (typeof replacer === 'function') {val = replacer(key, val);}// 根據數據類型處理if (val === null) return 'null';if (val === undefined) return undefined;if (typeof val === 'string') return `"${escapeString(val)}"`;if (typeof val === 'number') return isFinite(val) ? String(val) : 'null';if (typeof val === 'boolean') return String(val);// 檢查對象循環引用if (typeof val === 'object') {if (seen.has(val)) {throw new TypeError('循環引用無法轉換為JSON');}seen.add(val);// 處理數組if (Array.isArray(val)) {// 數組序列化邏輯...}// 處理對象// 對象序列化邏輯...}}return serialize('', value);
}

3. 為什么需要序列化

3.1 數據傳輸需求

// 前端發送數據到服務器
async function saveUserData(userData) {try {// 將復雜的 JavaScript 對象轉換為字符串// 因為網絡請求只能傳輸字符串const jsonData = JSON.stringify(userData);const response = await fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json'},body: jsonData // 使用序列化后的JSON字符串});return await response.json();} catch (error) {console.error('數據傳輸失敗:', error);}
}

3.2 數據持久化

// 將應用狀態保存到本地存儲
function saveAppState(state) {// JavaScript對象無法直接存儲,必須轉換為字符串localStorage.setItem('appState', JSON.stringify(state));
}// 從本地存儲恢復應用狀態
function loadAppState() {const savedState = localStorage.getItem('appState');// 將字符串轉回JavaScript對象return savedState ? JSON.parse(savedState) : null;
}

3.3 數據復制

// 深拷貝對象
function deepClone(obj) {// 利用序列化再反序列化實現深拷貝// 序列化會創建全新的字符串表示// 反序列化會基于這個表示創建全新的對象結構return JSON.parse(JSON.stringify(obj));
}

3.4 跨語言通信

JSON 作為一種通用數據格式,實現了不同編程語言和系統之間的數據交換。JavaScript 的 JSON.stringify 和其他語言中的序列化工具產生兼容的輸出格式。

4. 語法結構

JSON.stringify(value[, replacer[, space]])

4.1 參數詳解

  • value: 要轉換的 JavaScript 值,通常是對象或數組
  • replacer: 可選參數,可以是函數或數組,用于自定義轉換過程
  • space: 可選參數,用于美化輸出的 JSON 字符串

5. 基礎用法示例

const data = {name: "張三",age: 30,isActive: true,skills: ["JavaScript", "HTML", "CSS"]
};// 最基本的轉換
const jsonString = JSON.stringify(data);
// 結果: {"name":"張三","age":30,"isActive":true,"skills":["JavaScript","HTML","CSS"]}// 帶縮進的美化輸出
const prettyJson = JSON.stringify(data, null, 2);
// 結果會帶有縮進和換行,更易于閱讀

6. 特殊數據類型處理

6.1 原始數據類型

// 數字轉換
JSON.stringify(42); // "42"// 字符串轉換 - 注意會添加雙引號
JSON.stringify("測試"); // "\"測試\""// 布爾值轉換
JSON.stringify(true); // "true"// null 轉換
JSON.stringify(null); // "null"// undefined、函數和 Symbol 被忽略(對象屬性)或轉為 null(數組元素)
JSON.stringify(undefined); // undefined
JSON.stringify([1, undefined, 2]); // "[1,null,2]"
JSON.stringify({a: undefined}); // "{}"

6.2 復雜對象處理

// 日期對象會被轉換為字符串
const date = new Date();
JSON.stringify(date); // 如:"2023-11-20T08:00:00.000Z"// Map、Set、RegExp 等會被轉為空對象
JSON.stringify(new Map([['key', 'value']])); // "{}"
JSON.stringify(new Set([1, 2, 3])); // "{}"
JSON.stringify(/pattern/); // "{}"// 循環引用會導致錯誤
const obj = {};
obj.self = obj;
// JSON.stringify(obj); // 拋出錯誤: TypeError: Converting circular structure to JSON
注意:默認情況下,Map、Set、RegExp 等這些特殊對象類型被轉換為空對象 {},這會導致數據完全丟失。
如何正確序列化這些特殊類型:要解決這個問題,需要在序列化前進行特殊處理:
// 序列化 Map 對象
function stringifyMap(map) {return JSON.stringify({dataType: 'Map',value: Array.from(map.entries()) // 轉換為二維數組});
}const myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);
const mapJson = stringifyMap(myMap);
// 結果: {"dataType":"Map","value":[["key1","value1"],["key2","value2"]]}// 反序列化回 Map
function parseMap(jsonString) {const obj = JSON.parse(jsonString);if (obj.dataType === 'Map') {return new Map(obj.value);}throw new Error('不是有效的 Map JSON');
}
// 序列化 Set 對象
function stringifySet(set) {return JSON.stringify({dataType: 'Set',value: Array.from(set.values())});
}const mySet = new Set([1, 2, 3, 4]);
const setJson = stringifySet(mySet);
// 結果: {"dataType":"Set","value":[1,2,3,4]}// 反序列化回 Set
function parseSet(jsonString) {const obj = JSON.parse(jsonString);if (obj.dataType === 'Set') {return new Set(obj.value);}throw new Error('不是有效的 Set JSON');
}
// 序列化 RegExp 對象
function stringifyRegExp(regex) {return JSON.stringify({dataType: 'RegExp',source: regex.source,flags: regex.flags});
}const myRegex = /pattern/ig;
const regexJson = stringifyRegExp(myRegex);
// 結果: {"dataType":"RegExp","source":"pattern","flags":"gi"}// 反序列化回 RegExp
function parseRegExp(jsonString) {const obj = JSON.parse(jsonString);if (obj.dataType === 'RegExp') {return new RegExp(obj.source, obj.flags);}throw new Error('不是有效的 RegExp JSON');
}
通用解決方案:可以創建一個通用的序列化工具函數,處理所有這些特殊類型:
function enhancedStringify(obj) {return JSON.stringify(obj, (key, value) => {// 處理 Mapif (value instanceof Map) {return {__type: 'Map',value: Array.from(value.entries())};}// 處理 Setif (value instanceof Set) {return {__type: 'Set',value: Array.from(value.values())};}// 處理 RegExpif (value instanceof RegExp) {return {__type: 'RegExp',source: value.source,flags: value.flags};}return value;});
}function enhancedParse(jsonString) {return JSON.parse(jsonString, (key, value) => {if (value && typeof value === 'object' && value.__type) {switch(value.__type) {case 'Map':return new Map(value.value);case 'Set':return new Set(value.value);case 'RegExp':return new RegExp(value.source, value.flags);default:return value;}}return value;});
}

這樣,就可以正確地序列化和反序列化這些特殊對象類型了,避免數據丟失的問題。

7. replacer 參數應用

7.1 使用(匿名)函數作為 replacer

const user = {name: "李四",password: "secret123", // 敏感信息age: 25,loginTime: new Date()
};// 使用 replacer 函數過濾敏感信息并格式化日期
const secureStringify = JSON.stringify(user, (key, value) => {// 過濾掉密碼字段if (key === "password") return undefined;// 格式化日期對象if (value instanceof Date) {return value.toLocaleDateString("zh-CN");}return value;
});
// 結果中不包含密碼,且日期格式化為本地格式

7.2 使用數組作為 replacer

const completeData = {id: 1001,name: "產品A",price: 299,inventory: 150,description: "這是一個很好的產品",manufacturer: "某公司",createdAt: "2023-10-01"
};// 僅選擇特定字段輸出
const selectedFields = ["id", "name", "price"];
const simpleJson = JSON.stringify(completeData, selectedFields, 2);
// 結果只會包含 id、name 和 price 字段

8. 處理 toJSON 方法

// 自定義對象可以實現 toJSON 方法來控制其 JSON 表示
class Person {constructor(name, age) {this.name = name;this.age = age;this._secretId = "ID12345"; // 私有數據}// 自定義 JSON 轉換toJSON() {return {name: this.name,age: this.age,// 不包含 _secretIdisAdult: this.age >= 18 // 添加計算屬性};}
}const person = new Person("王五", 22);
JSON.stringify(person);
// 結果: {"name":"王五","age":22,"isAdult":true}

9. 易犯錯的場景

9.1 循環引用問題

// 創建循環引用
const team = {name: "開發團隊",members: []
};const member = {name: "開發者",team: team // 引用team對象
};team.members.push(member); // team引用member,形成循環try {// 會拋出錯誤JSON.stringify(team);
} catch (error) {console.error("序列化失敗:", error.message);// 輸出: 序列化失敗: Converting circular structure to JSON
}// 解決方案:使用replacer函數處理循環引用
function handleCircular() {const seen = new WeakSet();return (key, value) => {// 檢測對象類型的循環引用if (typeof value === 'object' && value !== null) {if (seen.has(value)) {return '[循環引用]'; // 或者返回null/undefined來移除此屬性}seen.add(value);}return value;};
}// 使用處理函數
const safeJson = JSON.stringify(team, handleCircular());
// 現在可以安全序列化,循環引用部分會被替換

9.2 數據丟失問題

const data = {id: 1,name: "測試",createdAt: new Date(),       // 會轉為字符串regex: /^test$/,             // 會變成 {}func: function() { return 1; }, // 會被完全忽略symbol: Symbol('sym'),       // 會被完全忽略infinity: Infinity,          // 會變成 nullnan: NaN,                    // 會變成 nullundefined: undefined         // 會被完全忽略
};const jsonString = JSON.stringify(data);
const parsed = JSON.parse(jsonString);console.log(parsed);
// 結果缺少了 func、symbol、undefined
// regex 變成了 {}
// infinity 和 nan 變成了 null
// createdAt 變成了字符串,不再是 Date 對象// 解決方案:在序列化前轉換特殊類型,反序列化后還原
function prepareForJSON(obj) {return Object.entries(obj).reduce((result, [key, value]) => {// 處理函數 - 轉為字符串表示if (typeof value === 'function') {result[key] = `__FUNCTION:${value.toString()}`;}// 處理日期 - 添加標記else if (value instanceof Date) {result[key] = `__DATE:${value.toISOString()}`;}// 處理正則表達式else if (value instanceof RegExp) {result[key] = `__REGEXP:${value.toString()}`;}// 其他情況直接保留else {result[key] = value;}return result;}, {});
}// 反序列化后恢復特殊類型
function restoreFromJSON(obj) {return Object.entries(obj).reduce((result, [key, value]) => {if (typeof value === 'string') {// 還原日期if (value.startsWith('__DATE:')) {result[key] = new Date(value.slice(7));}// 還原正則表達式else if (value.startsWith('__REGEXP:')) {const regexParts = /^__REGEXP:\/(.*)\/([gimuy]*)$/.exec(value);if (regexParts) {result[key] = new RegExp(regexParts[1], regexParts[2]);} else {result[key] = value;}}// 其他情況直接保留else {result[key] = value;}} else {result[key] = value;}return result;}, {});
}

9.3 精度與大數問題

const data = {// JavaScript 數字精度問題decimal: 0.1 + 0.2,  // 結果是 0.30000000000000004// 大整數溢出bigInt: 9007199254740992, // 超出安全整數范圍// BigInt 類型無法直接序列化reallyBig: 9007199254740992n
};const jsonStr = JSON.stringify(data); 
// 會拋出錯誤: BigInt 值無法轉換為 JSON// 解決方案:預處理大數和 BigInt
function handleBigNumbers(obj) {return JSON.stringify(obj, (key, value) => {// 處理 BigIntif (typeof value === 'bigint') {return value.toString() + 'n'; // 添加標記}// 處理大數,確保精度if (typeof value === 'number' && !Number.isSafeInteger(value)) {return value.toString(); // 轉為字符串保存}return value;});
}// 使用處理函數
const safeJsonStr = handleBigNumbers({normalNum: 42,bigNum: 9007199254740992,bigInt: 9007199254740992n
});// 反序列化時恢復
function restoreBigNumbers(jsonStr) {return JSON.parse(jsonStr, (key, value) => {// 還原 BigIntif (typeof value === 'string' && value.endsWith('n')) {return BigInt(value.slice(0, -1));}return value;});
}

10. 高級應用場景

10.1 深拷貝實現

// 使用 JSON 方法實現簡單的深拷貝
// 注意:此方法有局限性,不能處理函數、undefined、Symbol、循環引用等
function simpleDeepClone(obj) {// 先將對象轉為 JSON 字符串const jsonString = JSON.stringify(obj);// 再將 JSON 字符串解析回對象,生成全新的對象結構return JSON.parse(jsonString);
}const original = { info: { name: "原始對象",data: [1, 2, 3] } 
};
const copy = simpleDeepClone(original);
copy.info.name = "副本";
console.log(original.info.name); // "原始對象" - 不受影響

10.2 緩存序列化

// 將復雜數據存儲到 localStorage
function saveToCache(key, data) {try {// 轉換為字符串并存儲localStorage.setItem(key, JSON.stringify(data));return true;} catch (error) {// 可能因為數據過大或其他原因導致存儲失敗console.error("緩存存儲失敗:", error);return false;}
}// 從緩存中讀取數據
function loadFromCache(key) {try {const stored = localStorage.getItem(key);if (stored) {// 解析回 JavaScript 對象return JSON.parse(stored);}return null;} catch (error) {console.error("緩存讀取失敗:", error);return null;}
}

10.3 狀態管理與時間旅行

// Redux 等狀態管理庫使用序列化實現時間旅行調試
class SimpleStore {constructor(initialState = {}) {this.state = initialState;this.history = [];}// 更新狀態dispatch(action) {// 保存當前狀態快照到歷史記錄this.history.push(JSON.stringify(this.state));// 更新狀態(簡化示例)this.state = {...this.state,...action.payload};return this.state;}// 時間旅行 - 回到之前的狀態timeTravel(stepIndex) {if (stepIndex >= 0 && stepIndex < this.history.length) {// 從歷史記錄恢復狀態this.state = JSON.parse(this.history[stepIndex]);return this.state;}return null;}
}

11. 性能考量

11.1 大數據處理

// 處理大型數據集時的分塊處理方法
function processLargeData(data, chunkSize = 1000) {// 分割大型數組為多個小塊const chunks = [];for (let i = 0; i < data.length; i += chunkSize) {chunks.push(data.slice(i, i + chunkSize));}// 逐塊處理const results = [];for (const chunk of chunks) {// 每個塊單獨序列化,避免一次處理過多數據const jsonChunk = JSON.stringify(chunk);// 這里可以進行存儲或傳輸results.push(jsonChunk);}return results;
}

12. 常見陷阱與解決方案

12.1 處理數值精度問題

// JavaScript 中的大數值可能超出 JSON 數值范圍
const bigNumber = 9007199254740992n; // BigInt
// JSON.stringify(bigNumber); // 會拋出錯誤// 解決方案:轉換為字符串處理
const data = {id: "9007199254740992", // 作為字符串存儲normalNumber: 42
};JSON.stringify(data); // 正常工作

12.2 處理特殊字符

// Unicode 字符和轉義字符的處理
const text = "包含特殊字符: \n 換行符 \t 制表符 \u2022 項目符號";// JSON.stringify 會自動處理這些特殊字符
const encoded = JSON.stringify(text);
// 結果: "包含特殊字符: \n 換行符 \t 制表符 ? 項目符號"// 解碼時會正確還原
JSON.parse(encoded); // 原始文本

13. 序列化的安全問題

// 不安全的 JSON 解析
function unsafeParseFromServer(jsonString) {// 永遠不要這樣做!return eval('(' + jsonString + ')');
}// 安全的 JSON 解析
function safeParseFromServer(jsonString) {try {// 使用標準 JSON.parse 方法return JSON.parse(jsonString);} catch (error) {console.error('無效的 JSON 字符串:', error);return null;}
}// 處理不可信數據
function validateAndParse(jsonString) {try {// 1. 使用標準方法解析const data = JSON.parse(jsonString);// 2. 驗證數據結構和類型if (!data || typeof data !== 'object') {throw new Error('數據格式無效');}// 3. 驗證必要字段if (!data.id || typeof data.id !== 'number') {throw new Error('缺少必要字段或類型錯誤');}return data;} catch (error) {console.error('數據驗證失敗:', error);return null;}
}

14. 與其他序列化方法比較

14.1 JSON.stringify vs 手動序列化

// 手動構建 JSON 字符串 - 容易出錯
function manualStringify(obj) {// 這是一個簡化示例,實際情況更復雜let result = '{';const entries = Object.entries(obj);for (let i = 0; i < entries.length; i++) {const [key, value] = entries[i];result += `"${key}":`;if (typeof value === 'string') {result += `"${value}"`;} else if (typeof value === 'number' || typeof value === 'boolean') {result += value;} else if (value === null) {result += 'null';}// 這里省略了數組、對象等復雜類型的處理if (i < entries.length - 1) {result += ',';}}result += '}';return result;
}// JSON.stringify 更可靠、更安全、更全面

14.2 JSON vs 其他序列化格式

// JSON 序列化 - 標準且跨平臺
function serializeJSON(data) {return JSON.stringify(data);// 優點:標準格式,所有語言支持,人類可讀// 缺點:不支持循環引用,不能保留函數和特殊數據類型
}// MessagePack 序列化示例 (需要引入庫)
function serializeMsgPack(data) {// 使用 MessagePack 庫 (msgpack-lite 等)return msgpack.encode(data);// 優點:二進制緊湊,比JSON小,支持更多數據類型// 缺點:需要額外庫,人類不可讀
}// Protocol Buffers 示例 (需要引入庫和定義 schema)
function serializeProtobuf(data) {// 使用 Protocol Buffers 庫和預定義 schemareturn protobuf.encode(data);// 優點:高效緊湊,強類型,適合 RPC// 缺點:需要預定義 schema,設置復雜
}

15. 最佳實踐

15.1 序列化前數據清理

// 序列化前清理數據
function sanitizeForJSON(data) {// 深度復制對象并清理function sanitize(obj, seen = new WeakSet()) {// 處理基本類型if (obj === null || typeof obj !== 'object') {return obj;}// 處理循環引用if (seen.has(obj)) {return "[循環引用]";}seen.add(obj);// 數組處理if (Array.isArray(obj)) {return obj.map(item => sanitize(item, seen));}// 對象處理const result = {};for (const [key, value] of Object.entries(obj)) {// 跳過不需要的屬性if (key.startsWith('_')) continue; // 跳過私有屬性if (typeof value === 'function') continue; // 跳過函數// 處理特殊類型if (value instanceof Date) {result[key] = value.toISOString();} else {result[key] = sanitize(value, seen);}}return result;}return sanitize(data);
}// 使用清理過的數據序列化
const cleanData = sanitizeForJSON(complexData);
const jsonString = JSON.stringify(cleanData);

15.2 錯誤處理最佳實踐

// 健壯的序列化函數
function robustStringify(data) {try {return JSON.stringify(data, (key, value) => {// 處理 BigIntif (typeof value === 'bigint') {return value.toString() + 'n';}// 處理 Error 對象if (value instanceof Error) {return {_error: true,name: value.name,message: value.message,stack: value.stack};}// 處理特殊對象類型if (value instanceof Map || value instanceof Set || value instanceof WeakMap || value instanceof WeakSet) {return {_type: value.constructor.name,value: value instanceof Map ? [...value.entries()] :value instanceof Set ? [...value.values()] : 'Cannot serialize'};}return value;});} catch (error) {console.error('序列化失敗:', error);// 降級處理 - 嘗試去除問題屬性if (error.message.includes('circular structure')) {try {// 使用處理循環引用的方式重試const seen = new WeakSet();return JSON.stringify(data, (key, value) => {if (typeof value === 'object' && value !== null) {if (seen.has(value)) return '[循環引用]';seen.add(value);}return value;});} catch (e) {// 如果還失敗,返回基本信息return JSON.stringify({error: '序列化失敗',reason: error.message});}}// 其他錯誤情況返回錯誤信息return JSON.stringify({error: '序列化失敗',reason: error.message});}
}

16. 總結

JSON.stringify 是處理數據序列化的強大工具,掌握其各種參數和用法能夠有效解決數據處理中的各種問題。序列化是實現數據傳輸、存儲和復制的基礎技術,理解其原理和限制對于開發高效可靠的應用至關重要。

通過合理使用 replacer 和 space 參數,以及理解不同數據類型的處理規則,可以更精確地控制 JSON 輸出。在實際應用中,需要注意特殊數據類型、循環引用、數值精度等潛在問題,采取適當的方法進行處理,避免數據丟失或安全隱患。

隨著Web應用復雜度的提高,掌握高級序列化技巧和最佳實踐變得尤為重要,這不僅能提高應用性能,還能增強數據處理的可靠性和安全性。

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

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

相關文章

SQLite / LiteDB 單文件數據庫為何“清空表后仍占幾 GB”?——原理解析與空間回收實戰

關鍵詞&#xff1a; SQLite、LiteDB、VACUUM、WAL、auto_vacuum、文件瘦身、數據庫維護在嵌入式或桌面、IoT 網關等場景&#xff0c;很多同學都會選擇單文件數據庫&#xff08;SQLite、LiteDB、SQL CE…&#xff09;。 最近群里一位朋友反饋&#xff1a;“我的 test.db 已經把業…

如何加固Web服務器的安全?

Web服務器是用戶和公司聯系的橋梁&#xff0c;Web服務器為用戶交付網頁內容和提供Web應用。正因為Web服務器是面向互聯網的&#xff0c;所以成為了網絡的攻擊經常利用的一個入口。Web 服務器是企業數字化轉型的 “前沿陣地”&#xff0c;其安全性不僅關乎技術層面的穩定運行&am…

MyBatis:配置文件完成增刪改查_添加

1 實現添加操作 編寫接口方法:Mapper接口編寫sql語句&#xff1a;sql映射文件<insert id"add">insert into tb_brand(brand_name,company_name,ordered,description,status)values(#{brandName},#{companyName},#{ordered},#{description},#{status});</ins…

SGLang 推理框架核心組件解析:請求、內存與緩存的協同工作

SGLang 推理框架核心組件解析&#xff1a;請求、內存與緩存的協同工作 在當今大語言模型&#xff08;LLM&#xff09;服務的浪潮中&#xff0c;高效的推理框架是決定服務質量與成本的關鍵。SGLang 作為一個高性能的 LLM 推理和部署庫&#xff0c;其內部精巧的設計確保了高吞吐量…

React學習筆記——Day2打卡

1、React表單控制 1.1 受控綁定 概念&#xff1a;使用React組件的狀態&#xff08;useState&#xff09;控制表單的狀態 完整示例&#xff1a; function App(){/* 1. 準備一個React狀態值 */ const [value, setValue] useState()return (/* 2. 通過value屬性綁定狀態&#x…

用例測試方法5,6:狀態遷移圖和因果圖

狀態遷移圖通過描繪系統的狀態及引起狀態轉換的事件&#xff0c;來表示系統的行為例如&#xff1a;訂機票l向航空公司打電話預定機票—>此時機票信息處于“完成”狀態顧客支付了機票費用后—>機票信息就變為“已支付”狀態旅行當天到達機場后&#xff0c;拿到機票后—>…

linux 腳本解釋

if [ $? -ne 0 ]; thenecho "錯誤: 無法關閉現有 Tomcat 實例&#xff0c;終止啟動流程!" >&2exit 1fi$? 是shell中的特殊變量&#xff0c;表示上一個命令的退出狀態碼-ne 0 表示"不等于0"(在Unix/Linux中&#xff0c;0通常表示成功&#xff0c;非…

Glary Utilities(系統優化工具) v6.20.0.24 專業便攜版

GlaryUtilities 允許你清理系統垃圾文件&#xff0c;無效的注冊表&#xff0c;上網記錄&#xff0c;刪除插件&#xff0c;查找重復文件&#xff0c;優化內存&#xff0c;修理或刪除快捷方式&#xff0c;管理windows啟動程序&#xff0c;卸載軟件&#xff0c;安全刪除文件&#…

VScode鏈接服務器一直卡在下載vscode服務器/scp上傳服務器,無法連接成功

終極方案&#xff08;強力推薦&#xff0c;親測有效&#xff0c;鏈接只需5秒鐘&#xff09;&#xff1a;本地下載復制到mkdir -p ~/.vscode-server/bin/<commit_hash>里面 <commit_hash>可以從幫助->關于里面找到&#xff0c;如下所示 版本: 1.96.2 提交: fa…

基于Spring Boot的農村農產品銷售系統設計與實現

隨著現代農業的快速發展,傳統農產品的銷售模式逐漸暴露出信息閉塞、流通效率低和中間環節多等問題。為了打破這些瓶頸,我基于Spring Boot框架開發了一套農產品銷售系統,旨在構建一座連接農民與消費者之間的數字橋梁,讓優質農產品更高效地直達用戶餐桌。 一、項目背景與目標…

Mysql默認存儲引擎InnoDB和底層數據結構

在黑馬點評項目實戰中&#xff1a;談到了為什么不推薦使用mysql的字段自增作為訂單id傳遞給客戶端&#xff0c;讓我想到了Mysql的??存儲引擎??和??底層數據結構??究竟是什么&#xff1f;它是如何實現自增的&#xff1f;本文主要是深度解析 MySQL 默認存儲引擎 InnoDB 與…

原點安全簽約金網絡數科,共建一體化數據安全防護體系

金網絡正式攜手原點安全&#xff0c;基于原點安全一體化數據安全平臺&#xff08;uDSP&#xff09;&#xff0c;啟動企業數據安全平臺建設項目&#xff0c;圍繞數據資產盤點、敏感數據識別與分類分級、數據訪問權限管控、數據動態脫敏、數據安全審計與風險監測等關鍵能力建設&a…

mix-blend-mode的了解使用

mix-blend-mode 是 CSS 的一個屬性&#xff0c;用于控制元素的內容&#xff08;如文本、圖像、背景等&#xff09;如何與其 父元素 或 背景 進行混合。它類似于圖形設計軟件&#xff08;如 Photoshop&#xff09;中的圖層混合模式&#xff0c;可以實現各種視覺效果&#xff1b;…

vue自定義指令bug

問題描述&#xff1a;頁面加載時&#xff0c;報已下錯誤。同時&#xff0c;頁面數據不顯示環境介紹&#xff1a;已經添加了vue自定義指令permission&#xff0c;實現如下&#xff0c;用以控制元素顯示權限app.directive(permission, (el, binding) > {if (!store.hasPermiss…

Vue3 + WebSocket

Vue3與WebSocket結合能夠很好地滿足實時通訊的需求。通過合理設計和管理WebSocket連接的生命周期&#xff0c;以及實現必要的重連邏輯和心跳檢測機制&#xff0c;可以構建出響應迅速且穩定的實時應用。WebSocketWebSocket允許服務端主動向客戶端發送數據&#xff0c;無需客戶端…

IPSec和HTTPS對比(一)

IPSec&#xff08;Internet Protocol Security&#xff09;是網絡層&#xff08;OSI第3層&#xff09;的加密協議&#xff0c;其核心機制和與HTTPS的區別如下&#xff1a;&#x1f512; ?一、IPSec的核心機制解析??1. 安全封裝結構?┌──────────┬───────…

關于 c、c#、c++ 三者區別

1. 起源與定位語言起源時間開發者定位/特點C1972年Dennis Ritchie面向過程的編程語言&#xff0c;強調底層控制與高效性能C1983年Bjarne Stroustrup在 C 的基礎上加入 面向對象編程&#xff08;OOP&#xff09;C#2000年微軟&#xff08;Microsoft&#xff09;類似 Java&#xf…

項目總體框架(servlet+axios+Mybatis)

項目總體框架 先暫時這樣子&#xff08;后續發現錯誤的話就改&#xff09; com.hope-tieba/ ← 項目根 ├─ .idea/ ← IDEA 工程配置 ├─ src/ │ ├─ main/ │ │ ├─ java/ │ │ │ └─ com/hope/ │ │ …

RestTemplate 實現后端 HTTP 調用詳解

1. 方法簽名解析方法名和返回類型說明了這個方法的業務意圖和數據結構。Override 表示實現接口方法&#xff0c;利于規范開發和自動檢查。Override public List<RobotInfo> listRobots() {這里 RobotInfo 是假設的業務數據結構&#xff0c;實際項目中按你的類名即可。2. …

Python單例模式詳解:從原理到實戰的完整指南

引言 單例模式是軟件設計中最常用的模式之一&#xff0c;它確保一個類只有一個實例&#xff0c;并提供全局訪問點。在Python中&#xff0c;實現單例模式有多種優雅的方式&#xff0c;本文將詳細講解6種主流實現方法&#xff0c;包含完整代碼示例和注釋。 一、模塊級單例&#x…