【Spring】深入理解 Spring 事務及其傳播機制

文章目錄

  • 一、Spring 事務是什么
  • 二、Spring 中事務的實現方法
    • 2.1 Spring 編程式事務(手動)
      • 2.1.1 編程式事務的使用演示
      • 2.1.2 編程式事務存在的問題
    • 2.2 Spring 聲明式事務(自動)
      • 2.2.1 @Transactional 作用范圍
      • 2.2.2 @Transactional 參數說明
      • 2.2.3 @Transactional 捕獲異常時回滾失效問題
      • 2.4.4 @Transactional 工作原理
    • 2.3 Spring 事務失效場景
  • 三、事務的隔離級別
    • 3.1 事務的特性回顧
    • 3.2 MySQL 的事務隔離級別
    • 3.3 Spring 事務的隔離級別
  • 四、Spring 事務的傳播機制
    • 4.1 為什么需要事務傳播機制
    • 4.2 事務傳播機制的分類
    • 4.3 Spring 事務傳播機制使用案例


一、Spring 事務是什么

在 Spring 框架中,事務(Transaction)是一種用于管理數據庫操作的機制,旨在確保數據的一致性、可靠性和完整性。事務可以將一組數據庫操作(如插入、更新、刪除等)視為一個單獨的執行單元,要么全部成功地執行,要么全部回滾。這樣可以確保數據庫在任何時候都保持一致的狀態,即使在發生故障或錯誤時也能保持數據的完整性。

Spring 框架通過提供事務管理功能,使開發者能夠更輕松地管理事務的邊界。Spring 主要提供了兩種主要的事務管理方式:

  1. 編程式事務管理:通過編寫代碼顯式地管理事務的開始、提交和回滾操作。這種方式提供了更大的靈活性,但也需要更多的代碼維護。

  2. 聲明式事務管理:通過在配置中聲明事務的行為,由 Spring 框架自動處理事務的邊界,減少了開發者的工作量,并提高了代碼的可維護性。

二、Spring 中事務的實現方法

2.1 Spring 編程式事務(手動)

2.1.1 編程式事務的使用演示

在 Spring 中,編程式事務管理是一種手動控制事務邊界的方式,與 MySQL 操作事務的方法類似,它涉及三個重要的操作步驟:

  1. 開啟事務(獲取事務):首先需要通過獲取事務管理器(例如 DataSourceTransactionManager)來獲取一個事務,從而開始一個新的事務。事務管理器是用于管理事務的核心組件。

  2. 提交事務:一旦一組數據庫操作成功執行,并且希望將這些更改永久保存到數據庫中,就可以調用事務對象的提交方法。這將使得事務中的所有操作都被應用到數據庫。

  3. 回滾事務:如果在事務處理過程中發生錯誤或某種條件不滿足,就可以調用事務對象的回滾方法,從而撤銷事務中的所有操作,回到事務開始前的狀態。

在 Spring Boot 中,可以利用內置的事務管理器 DataSourceTransactionManager 來獲取事務,提交或回滾事務。此外,TransactionDefinition 是用來定義事務的屬性的,當獲取事務時需要將 TransactionDefinition 傳遞進DataSourceTransactionManager以獲取一個事務狀態 TransactionStatus

例如,下面的代碼演示了編程式事務:

@RestController
@RequestMapping("/user")
public class UserController {// 編程式事務@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate UserService userService;@RequestMapping("/del")public int delById(@RequestParam("id") Integer id) {if (id == null || id < 0) return 0;// 1. 開啟事務TransactionStatus transactionStatus = null;int res = 0;try {transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);// 2. 業務操作 —— 刪除用戶res = userService.delById(id);System.out.println("刪除: " + res);// 3. 提交、回滾事務// 提交事務dataSourceTransactionManager.commit(transactionStatus);} catch (Exception e) {e.printStackTrace();// 回滾事務if (transactionStatus != null) {dataSourceTransactionManager.rollback(transactionStatus);}}return res;}
}

這段代碼展示了如何通過編程式事務管理在Spring Boot中處理用戶刪除操作。編程式事務允許我們在代碼中明確地控制事務的邊界,以及在需要時手動提交或回滾事務。

2.1.2 編程式事務存在的問題

通過上面的示例代碼可以發現,編程式事務雖然提供了更大的靈活性,但也存在一些問題和挑戰:

  1. 代碼冗余和可讀性差: 編程式事務需要在代碼中顯式地添加事務管理的邏輯,導致代碼變得冗余且難以維護。每次需要使用事務的地方都需要重復編寫事務開啟、提交和回滾的代碼,降低了代碼的可讀性。

  2. 事務邊界控制復雜: 開發者需要手動管理事務的邊界,確保事務的開始、提交和回滾都在正確的位置。這可能會導致遺漏事務管理的代碼,從而影響數據的一致性。

  3. 事務傳播和嵌套問題: 在涉及多個方法調用的場景中,手動控制事務的傳播和嵌套關系可能變得復雜。需要開發者確保事務在各個方法間正確傳播,同時處理好嵌套事務的問題。

  4. 異常處理繁瑣: 編程式事務需要在異常處理時手動進行回滾操作,如果異常處理不當,事務可能無法正確回滾,導致數據不一致。

  5. 可維護性差: 隨著項目的發展,業務邏輯可能會變得更加復雜,可能需要頻繁地修改事務管理的代碼。這會增加代碼維護的難度,可能導致錯誤的引入。

  6. 不利于橫向擴展: 編程式事務難以支持橫向擴展,因為事務管理的代碼緊耦合在業務邏輯中,擴展時可能需要修改大量代碼。

相比之下,聲明式事務管理通過在方法上添加注解或在配置文件中進行聲明,使事務管理與業務邏輯分離,提供了更好的代碼組織和可維護性。聲明式事務可以在切面中自動處理事務的開始、提交和回滾,從而減輕了開發者的工作負擔。

所以,大多數情況下,建議使用聲明式事務管理來處理事務,特別是在簡化事務邏輯和提高代碼可讀性方面更加有效。

2.2 Spring 聲明式事務(自動)

聲明式事務的實現非常簡單,只需要在需要的方法上添加 @Transactional 注解就可以輕松實現,無需手動開啟或提交事務。

  • 當進入被注解的方法時,Spring 會自動開啟一個事務。
  • 方法執行完成后,如果沒有拋出未捕獲的異常,事務會自動提交,保證數據的一致性。
  • 然而,如果方法在執行過程中發生了未經處理的異常,事務會自動回滾,以確保數據庫的完整性和一致性。

這種方式大大簡化了事務管理的編碼,減少了手動處理事務的繁瑣操作,提高了代碼的可讀性和可維護性。例如下面的代碼實現:

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;// 聲明式事務@RequestMapping("/del")@Transactionalpublic int delById(Integer id) {if (id == null || id < 0) return 0;int result = userService.delById(id);return result;}
}

在這個示例中,delById 方法使用了 @Transactional 注解,表示該方法需要受到聲明式事務的管理。在這個方法內部,首先檢查了傳入的 id,如果為負數則直接返回結果。然后,調用了 userService.delById(id) 方法,刪除了指定用戶。在方法結束時,事務會自動提交。

同時,如果在執行過程中發生了未處理的異常,事務將會自動回滾,以保持數據庫的一致性。這種方式簡化了事務管理,提高了代碼的可讀性和可維護性。

2.2.1 @Transactional 作用范圍

@Transactional 注解可以被用來修飾方法或類:

  • 當修飾方法時:需要注意它只能應用到 public 訪問修飾符的方法上,否則注解不會生效。通常推薦在方法級別使用 @Transactional

  • 當修飾類時:表示該注解對于類中所有的 public 方法都會生效。如果在類級別添加了 @Transactional,那么該類中所有的公共方法都將自動應用事務管理。

一般來說,推薦將 @Transactional 注解應用在方法級別,以便更精確地控制事務的范圍,從而避免不必要的事務開銷。如果類中的所有方法都需要事務管理,那么將注解應用在類級別是一個更方便的選擇。

2.2.2 @Transactional 參數說明

通過查看 @Transactional 的源碼,可以發現它支持多個參數,用來配置事務的行為。

以下是對其中參數說明:

參數名稱類型默認值描述
valueString“”事務管理器的名稱,與 transactionManager 等效。
transactionManagerString“”事務管理器的名稱,與 value 等效。
labelString[]空數組事務標簽,暫無具體用途。
propagationPropagationPropagation.REQUIRED事務的傳播行為,默認為 REQUIRED。
isolationIsolationIsolation.DEFAULT事務的隔離級別,默認為數據庫默認隔離級別。
timeoutint-1事務的超時時間,單位為秒。-1 表示沒有超時限制。
timeoutStringString“”事務的超時時間的字符串表示,與 timeout 等效。
readOnlybooleanfalse是否將事務設置為只讀,默認為 false。
rollbackForClass<? extends Throwable>[]空數組觸發回滾的異常類型。
rollbackForClassNameString[]空數組觸發回滾的異常類型的類名字符串。
noRollbackForClass<? extends Throwable>[]空數組不觸發回滾的異常類型。
noRollbackForClassNameString[]空數組不觸發回滾的異常類型的類名字符串。

這些參數提供了對事務行為的靈活配置,可以根據具體業務需求來調整事務的傳播、隔離、超時和回滾策略等。

2.2.3 @Transactional 捕獲異常時回滾失效問題

針對于上述的實例代碼,現在代碼中間模擬實現一個異常,觀察會出現什么情況:

@RequestMapping("/del")
@Transactional
public int delById(Integer id) {if (id == null || id < 0) return 0;int result = userService.delById(id);System.out.println(result);try {int num = 10 / 0;} catch (Exception e) {// 如果直接處理異常,則不會回滾e.printStackTrace();}return result;
}

通過瀏覽器訪問,發現服務器成功捕獲了異常:

但是事務卻沒有回滾,對應的用戶數據還是被刪除了:

其原因在于:

在異常處理中直接捕獲了異常并進行了處理,從而導致事務回滾失效。默認情況下,@Transactional 注解會在方法內拋出 RuntimeException 及其子類異常時觸發事務回滾。然而,當自己在 catch 塊內捕獲異常并處理時,Spring 無法感知到異常,從而無法觸發事務回滾。

解決方法:

對于這個問題的解決方法大致可以分為兩種:

  1. 將捕獲的異常再次拋出:
e.printStackTrace();
throw e;

這種方法通過重新拋出異常,使得 Spring 能夠捕獲異常并觸發事務回滾。在異常發生后,事務將被回滾,確保之前的數據庫操作不會生效,從而保持數據的一致性。

  1. 使用 TransactionAspectSupport 手動回滾事務:
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

這種方法利用了 Spring 提供的 TransactionAspectSupport 類來手動設置事務回滾狀態。在捕獲異常后,通過調用 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),可以將當前事務設置為回滾狀態,從而達到回滾事務的效果。這種方法更加靈活,可以在需要的時候手動控制事務的回滾。

無論選擇哪種方法,都可以在異常發生時觸發事務回滾,保障數據的完整性和一致性。選擇哪種方法取決于具體的代碼邏輯和需求。

2.4.4 @Transactional 工作原理

@Transactional 注解的工作原理基于 Spring AOP(面向切面編程)和事務管理器。它利用了 Spring 框架的代理機制來實現事務管理。

當一個被 @Transactional 注解修飾的方法被調用時,Spring 會創建一個代理對象來包裝這個方法。代理對象會在方法執行之前和之后添加事務管理的邏輯,以確保事務的開始、提交和回滾。這個過程是通過 AOP 技術實現的。

具體來說,以下是 @Transactional 注解的工作流程:

  1. 事務代理的創建: Spring 在運行時會為每個被 @Transactional 注解修飾的類創建一個代理對象。這個代理對象會包含事務管理的邏輯。

  2. 方法調用: 當調用一個被 @Transactional 注解修飾的方法時,實際上是通過代理對象來調用。

  3. 事務切面的觸發: 在代理對象中,事務切面會在方法執行前后被觸發。在方法執行前,切面會開啟一個事務;在方法執行后,切面會根據方法的執行情況決定是提交事務還是回滾事務。

  4. 事務管理器的使用: 切面會通過事務管理器來控制事務。事務管理器負責實際的事務管理操作,如開啟、提交和回滾事務。

  5. 事務控制: 如果方法正常執行完畢,切面會通知事務管理器提交事務。如果方法在執行過程中拋出異常,切面會通知事務管理器回滾事務。

總體來說,@Transactional 注解的工作原理是通過代理和切面來實現事務管理,將事務的控制與業務邏輯分離,使代碼更加模塊化和可維護。這也是聲明式事務管理的核心機制之一。

2.3 Spring 事務失效場景

在某些情況下,Spring 中的事務可能會失效,導致事務不生效或不按預期執行。以下是一些可能導致事務失效的場景:

  1. public 修飾的方法: 默認情況下,@Transactional 注解只對 public 訪問修飾符的方法起作用。如果你在非 public 方法上添加了 @Transactional 注解,事務可能不會生效。

  2. timeout 超時: 如果事務執行的時間超過了設置的 timeout 值,事務可能會被強制回滾。這可能會導致事務不按預期執行,特別是當事務需要執行較長時間的操作時。

  3. 代碼中有 try/catch 如果在方法內部捕獲并處理了異常,Spring 將無法感知到異常,從而無法觸發事務回滾。這可能導致事務在異常發生時不會回滾。

  4. 調用類內部帶有 @Transactional 的方法: 當一個類內部的方法被調用時,它的 @Transactional 注解可能不會生效。這是因為 Spring 默認使用基于代理的事務管理,直接在類內部調用方法不會經過代理,從而事務管理可能不會生效。

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;public int del(Integer id){return delById(id);}// 聲明式事務@RequestMapping("/del")@Transactionalpublic int delById(Integer id) {if (id == null || id < 0) return 0;int result = userService.delById(id);return result;}
}
  1. 數據庫不支持事務: 如果你的數據庫不支持事務,例如使用了某些特殊的數據庫引擎,事務可能無法正常工作。在這種情況下,應該確保使用支持事務的數據庫引擎。

三、事務的隔離級別

3.1 事務的特性回顧

在數據庫中,事務具有以下四個重要的特性,通常被稱為 ACID 特性:

  1. 原子性(Atomicity): 事務被視為一個不可分割的操作單元,要么全部執行成功,要么全部失敗回滾。

  2. 一致性(Consistency): 事務使數據庫從一個一致的狀態轉變到另一個一致的狀態,保證數據的完整性和一致性。

  3. 隔離性(Isolation): 并發執行的事務之間應該互不影響,每個事務都感覺自己在獨立地操作數據。

  4. 持久性(Durability): 一旦事務提交,其對數據庫的修改就應該是永久性的,即使發生系統崩潰也不應該丟失。

3.2 MySQL 的事務隔離級別

MySQL 支持以下四個事務隔離級別,用于控制多個事務之間的相互影響程度:

  1. 讀未提交(Read Uncommitted): 允許一個事務讀取另一個事務尚未提交的數據。這是最低的隔離級別,可能會導致臟讀、不可重復讀和幻讀的問題。

  2. 讀已提交(Read Committed): 允許一個事務只能讀取另一個事務已經提交的數據。這可以避免臟讀,但可能會出現不可重復讀和幻讀的問題。

  3. 可重復讀(Repeatable Read): 保證在同一個事務中多次讀取同樣記錄的結果是一致的,即使其他事務對該記錄進行了修改。這可以避免臟讀和不可重復讀,但可能出現幻讀。

  4. 串行化(Serializable): 最高的隔離級別,確保每個事務都完全獨立運行,避免了臟讀、不可重復讀和幻讀問題,但可能影響并發性能。

以下是事務四個隔離級別對應的臟讀、不可重復讀、幻讀情況:

隔離級別臟讀不可重復讀幻讀
讀未提交
讀已提交×
可重復讀××
串行化×××
  • √ 表示可能出現該問題。
  • × 表示該問題不會出現。

3.3 Spring 事務的隔離級別

Spring 通過 @Transactional 注解中的 isolation 參數來支持不同的事務隔離級別。Isolation的源碼如下:

可以使用這些枚舉值來設置隔離級別:

  • Isolation.DEFAULT:使用數據庫的默認隔離級別。
  • Isolation.READ_UNCOMMITTED:讀未提交。
  • Isolation.READ_COMMITTED:讀已提交。
  • Isolation.REPEATABLE_READ:可重復讀。
  • Isolation.SERIALIZABLE:串行化。

例如,指定 Spring 事務的隔離級別為 DEFAULT

@RequestMapping("/del")
@Transactional(isolation = Isolation.DEFAULT)
public int delById(Integer id) {if (id == null || id < 0) return 0;int result = userService.delById(id);return result;
}

通過選擇合適的事務隔離級別,可以在并發環境中控制事務之間的相互影響程度,從而避免數據不一致的問題。不同的隔離級別在性能和數據一致性方面有不同的權衡,開發人員需要根據具體的業務需求來選擇合適的隔離級別。

四、Spring 事務的傳播機制

4.1 為什么需要事務傳播機制

在復雜的應用場景中,一個事務操作可能會調用多個方法或服務。這些方法可能需要獨立地進行事務管理,但又需要協同工作,以保持數據的一致性和完整性。這時就需要引入事務傳播機制。

事務傳播機制定義了多個事務方法之間如何協同工作,如何共享同一個事務,以及在嵌套事務中如何進行隔離和提交。通過事務傳播機制,可以確保多個事務方法在執行時能夠按照一定的規則進行協調,避免數據不一致的問題。

4.2 事務傳播機制的分類

Spring 定義了七種事務傳播行為,用于控制多個事務方法之間的交互。這些傳播行為可以在 @Transactional 注解中的 propagation 參數中進行設置。以下是這些傳播行為:

  1. REQUIRED(默認): 如果當前存在事務,就加入到當前事務中;如果沒有事務,就創建一個新的事務。這是最常用的傳播行為。

  2. SUPPORTS: 如果當前存在事務,就加入到當前事務中;如果沒有事務,就以非事務方式執行。

  3. MANDATORY: 如果當前存在事務,就加入到當前事務中;如果沒有事務,就拋出異常。

  4. REQUIRES_NEW: 無論當前是否存在事務,都創建一個新的事務。如果當前存在事務,則將當前事務掛起。

  5. NOT_SUPPORTED: 以非事務方式執行,如果當前存在事務,就將當前事務掛起。

  6. NEVER: 以非事務方式執行,如果當前存在事務,就拋出異常。

  7. NESTED: 如果當前存在事務,就在一個嵌套的事務中執行;如果沒有事務,就與 REQUIRED 一樣。

以上 7 種傳播行為,可以根據是否支持當前事務分為以下 3 類:

4.3 Spring 事務傳播機制使用案例

REQUIRED 和 NESTED 傳播機制的事務演示:

控制層 ControllerUserController

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add") // /add?username=lisi&password=123456@Transactional(propagation = Propagation.NESTED)// Transactional(propagation = Propagation.REQUIRED)//@Transactional(propagation = Propagation.REQUIRES_NEW)public int add(@RequestParam("username") String username, @RequestParam("password") String password) {if (null == username || null == password || "".equals(username) || "".equals(password)) {return 0;}int result = 0;// 用戶添加操作UserInfo user = new UserInfo();user.setUsername(username);user.setPassword(password);result = userService.add(user);try {int num = 10 / 0; // 加入事務:外部事務回滾,內部事務也會回滾} catch (Exception e) {e.printStackTrace();TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
}

服務層ServiceUserService

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate LogService logService;public int delById(Integer id){return userMapper.delById(id);}@Transactional(propagation = Propagation.NESTED)// Transactional(propagation = Propagation.REQUIRED)//@Transactional(propagation = Propagation.REQUIRES_NEW)public int add(UserInfo user){// 添加用戶信息int addUserResult = userMapper.add(user);System.out.println("添加用戶結果:" + addUserResult);//添加日志信息Log log = new Log();log.setMessage("添加用戶信息");logService.add(log);return addUserResult;}
}

服務層ServiceLogService

@Service
public class LogService {@Autowiredprivate LogMapper logMapper;@Transactional(propagation = Propagation.NESTED)// Transactional(propagation = Propagation.REQUIRED)//@Transactional(propagation = Propagation.REQUIRES_NEW)public int add(Log log){int result =  logMapper.add(log);System.out.println("添加日志結果:" + result);// 模擬異常情況try {int num = 10 / 0;} catch (Exception e) {// 加入事務:內部事務回滾,外部事務也會回滾,并且會拋異常// 嵌套事務:內部事務回滾,不影響外部事務e.printStackTrace();TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
}

在事務傳播機制中,REQUIREDNESTED 是兩種不同的傳播行為,它們在事務的嵌套、回滾以及對外部事務的影響等方面有所不同。通過上面代碼的演示,可以得出 REQUIREDNESTED 之間的主要區別如下:

  1. 嵌套性質:

    • REQUIRED:內部方法與外部方法共享同一個事務,內部方法的事務操作是外部方法事務的一部分。
    • NESTED:內部方法創建一個嵌套事務,它是外部事務的子事務,具有獨立的事務狀態,內部事務的回滾不會影響外部事務。
  2. 回滾行為:

    • REQUIRED:如果內部方法拋出異常或設置回滾,會導致整個外部事務回滾,包括內部方法和外部方法的操作。
    • NESTED:如果內部方法拋出異常或設置回滾,只會回滾內部事務,而外部事務仍然可以繼續執行。
  3. 影響外部事務:

    • REQUIRED:內部方法的事務操作會影響外部事務的狀態,內部方法回滾會導致外部事務回滾。
    • NESTED:內部方法的事務操作不會影響外部事務的狀態,內部方法回滾不會影響外部事務的提交或回滾。
  4. 支持性:

    • REQUIRED:較為常用,適用于將多個方法的操作作為一個整體進行事務管理的情況。
    • NESTED:在某些數據庫中不支持,需要數據庫支持保存點(Savepoint)的功能。

總的來說,REQUIRED 適用于需要將多個方法的操作作為一個整體事務管理的情況,而 NESTED 適用于需要在內部方法中創建嵌套事務的情況,保持內部事務的獨立性,不影響外部事務。選擇使用哪種傳播行為取決于業務需求和數據庫的支持情況。

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

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

相關文章

騰訊云GPU服務器GN7實例NVIDIA T4 GPU卡

騰訊云GPU服務器GN7實例搭載1顆 NVIDIA T4 GPU&#xff0c;8核32G配置&#xff0c;系統盤為100G 高性能云硬盤&#xff0c;自帶5M公網帶寬&#xff0c;系統鏡像可選Linux和Windows&#xff0c;地域可選廣州/上海/北京/新加坡/南京/重慶/成都/首爾/中國香港/德國/東京/曼谷/硅谷…

安卓純代碼布局開發游戲二:Android Studio開發環境搭建

1.Android Studio下載&#xff1a; Download Android Studio & App Tools - Android Developers 2.安裝 安裝過程非常簡單&#xff0c;找到下載包&#xff0c;一直點Next即可。 3.下載Android SDK 第一次進入Android Studio默認會先下載Android SDK,筆者下載的Android SDK存…

零售行業供應鏈管理核心KPI指標(三)

完美訂單滿足率和退貨率 完美訂單滿足率有三個方面的因素影響&#xff1a;訂單按時、足量、無損交貨。通常情況下零售企業追求線上訂單履行周期慢慢達到行業平均水平&#xff0c;就是交付的速度變快了&#xff0c;這個肯定是一件好事情&#xff0c;趨勢越來越好。 同時&#…

歐拉公式

文章目錄 歐拉公式e歐拉恒等式歐拉公式歐拉公式 推導2步驟1: 使用泰勒級數展開步驟2: 將 i x i x ix 代入 e x e^x ex 復平面上推導歐拉公式步驟1&#xff1a;復平面上的復數表示步驟2&#xff1a;定義復數的指數形式步驟3&#xff1a;求導步驟4&#xff1a;連接兩種形式步驟…

ubuntu安裝opencv4

apt 安裝 sudo apt install libopencv-dev python3-opencvpkg-config查看安裝 sudo apt install pkg-configpkg-config --modversion opencv4pkg-config --libs --cflags opencv4參考 如何在 Ubuntu 20.04 上安裝 OpenCV pkg-config 詳解

spark yarn 開啟動態資源分配

概念 不需要指定并發&#xff0c;只需要指定內存&#xff0c; 程序在運行后會動態調節并發數量&#xff0c;我們只需要設置一個上線即可 在spark 配置文件設置&#xff1a; spark.dynamicAllocation.enabled true spark.shuffle.service.enabled true 準備shuffer jar 將spar…

星際爭霸之小霸王之小蜜蜂(一)

目錄 前言 一、安裝pygame庫 1、pygame庫簡介 2、在windows系統安裝pygame庫 二 、搭建游戲框架 1、創建游戲窗口 2、改變窗口顏色 總結 前言 大家應該都看過或者都聽說過python神書“大蟒蛇”&#xff0c;上面有一個案例是《外星人入侵》&#xff0c;游戲介紹讓我想起了上…

炫酷UI前端效果的CSS生成工具

提升設計人員和前端開發人員的工作 推薦炫酷UI前端效果的CSS生成工具1.Neumorphism2.帶有漸變的圖標3.Interactions4.大型數據庫5.動畫6.Mask7.動畫按鈕8. 自定義形狀分隔線9.背景圖案10. SVG波浪推薦炫酷UI前端效果的CSS生成工具 1.Neumorphism 地址:https://neumorphism.i…

【Nginx17】Nginx學習:目錄索引、字符集與瀏覽器判斷模塊

Nginx學習&#xff1a;目錄索引、字符集與瀏覽器判斷模塊 今天要學習的內容有幾個還是大家比較常見的&#xff0c;所以學習起來也不會特別費勁。對于目錄的默認頁設置大家都不會陌生&#xff0c;字符集的設置也比較常見&#xff0c;而瀏覽器的判斷這一塊&#xff0c;可能有同學…

深入源碼分析kubernetes informer機制(二)Reflector

[閱讀指南] 這是該系列第二篇 基于kubernetes 1.27 stage版本 為了方便閱讀&#xff0c;后續所有代碼均省略了錯誤處理及與關注邏輯無關的部分。 文章目錄 Reflector是什么整體結構工作流程list拉取數據緩存resync操作watch監聽操作 總結 Reflector是什么 reflector在informer…

RocketMQ雙主雙從同步集群部署

&#x1f388; 作者&#xff1a;互聯網-小啊宇 &#x1f388; 簡介&#xff1a; CSDN 運維領域創作者、阿里云專家博主。目前從事 Kubernetes運維相關工作&#xff0c;擅長Linux系統運維、開源監控軟件維護、Kubernetes容器技術、CI/CD持續集成、自動化運維、開源軟件部署維護…

學習筆記十九:Pod常見的狀態和重啟策略

Pod常見的狀態和重啟策略 常見的pod狀態第一階段&#xff1a;第二階段&#xff1a;擴展&#xff1a; pod重啟策略測試Always重啟策略正常停止容器內的tomcat服務非正常停止容器里的tomcat服務 測試never重啟策略正常停止容器里的tomcat服務非正常停止容器里的tomcat服務 測試On…

Mac安裝opencv后無法導入cv2的解決方法

前提條件&#xff1a;以下兩個插件安裝成功 pip install opencv-python pip install --user opencv-contrib-python 注&#xff1a;直接用pip install opencv-contrib-python如果報錯&#xff0c;就加上“–user" 第一步&#xff1a; 設置–添加python解釋器 第二步&am…

go語言惡意代碼檢測系統--對接前端可視化與算法檢測部分

Malware Detect System 1 產品介紹 惡意代碼檢測系統。 2 產品描述 2.1 產品功能 功能點詳細描述注冊賬號未注冊用戶注冊成為產品用戶&#xff0c;從而具備享有產品各項服務的資格登錄賬號用戶登錄產品&#xff0c;獲得產品提供的各項服務上傳惡意樣本用戶可以將上傳自己的…

uniapp微信小程序消息訂閱快速上手

一、微信公眾平臺小程序開通消息訂閱并設置模板 這邊的模板id和詳細內容后續前后端需要使用 二、uniapp前端 需要是一個button觸發 js&#xff1a; wx.getSetting({success(res){console.log(res)if(res.authSetting[scope.subscribeMessage]){// 業務邏輯}else{uni.request…

智安網絡|深入比較:Sass系統與源碼系統的差異及選擇指南

隨著前端開發的快速發展&#xff0c;開發人員需要使用更高效和靈活的工具來處理樣式表。在這個領域&#xff0c;Sass系統和源碼系統是兩個備受關注的選項。 Sass系統 Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;是一種CSS預處理器&#xff0c;它擴展了CS…

CSS常見單位匯總

像素&#xff08;px&#xff09;&#xff1a; 絕對單位&#xff0c;以屏幕上的實際像素為基準&#xff0c;最常用于具體的尺寸和位置表示。 百分比&#xff08;%&#xff09;&#xff1a; 相對單位&#xff0c;基于父元素的屬性計算大小&#xff0c;如寬度、高度、邊距等。 自適…

@Param詳解

文章目錄 背景什么是ParamParam的使用方法使用方法&#xff1a;遇到的問題及因Param解決了什么問題使用與不使用對比 Param是如何進行映射的總結 背景 最近在開發過程中&#xff0c;在寫mapper接口是在參數前加了Param注解&#xff0c;但是在運行的時候就會報錯&#xff0c;說…

關于游戲盾

游戲盾&#xff08;Game Shield&#xff09;是一種針對游戲行業特點的網絡安全解決方案&#xff0c;主要針對游戲平臺面臨的各種網絡攻擊和安全威脅。以下是一些原因&#xff0c;說明為什么游戲平臺需要加游戲盾&#xff1a; 1. DDoS攻擊&#xff1a;游戲平臺通常容易受到分布式…

深入理解多態:面向對象編程中的靈活性與擴展性

文章目錄 代碼學習-多態什么是多態&#xff1f;多態在代碼中的體現多態的優勢 代碼學習-多態 什么是多態&#xff1f; 多態是面向對象編程中的重要概念之一&#xff0c;它指的是為不同的數據類型的實體提供統一的接口。簡而言之&#xff0c;就是同一個命令在不同的對象上會產…