Spring MVC 父子容器深度解析:原理、實戰與優化

1. 父子容器的定義與設計初衷

一句話總結:父子容器的核心價值在于解耦 Web 層與業務層,實現職責分離與上下文隔離。

1.1 父子容器的層次關系

Spring MVC 中,容器分為兩類:

  • 父容器(Root ApplicationContext):由 ContextLoaderListener 創建,主要存放 Service、DAO、事務管理器、數據源 等業務相關 Bean。

  • 子容器(WebApplicationContext):由 DispatcherServlet 創建,主要存放 Controller、HandlerMapping、ViewResolver 等 Web 層相關 Bean。

層級關系描述(文字版流程圖)

  1. Tomcat 啟動,ContextLoaderListener 初始化父容器。

  2. 父容器加載全局 Bean(數據源、事務管理器、業務 Service)。

  3. DispatcherServlet 初始化子容器,并將父容器引用傳遞給它。

  4. 子容器加載 Web 層 Bean(Controller、ViewResolver)。

  5. Bean 查找規則:先找子容器 → 找不到再去父容器


1.2 生命周期差異

特性父容器(Root)子容器(Web)
創建時機Web 容器啟動時每個 DispatcherServlet 啟動時
銷毀時機Web 容器關閉時對應 Servlet 銷毀時
Bean 作用域全局共享僅限當前 Servlet
常見存放對象Service、DAO、事務管理器Controller、視圖解析器、攔截器


1.3 單容器 vs 父子容器

對比維度單容器架構父子容器架構
隔離性無隔離,所有 Bean 混在一個容器里Web 層與業務層隔離,減少耦合
可維護性項目大時配置混亂分層清晰,職責明確
啟動效率啟動慢(所有 Bean 一起加載)可按 Servlet 粒度啟動部分 Web 層
適用場景小型單體應用中大型單體應用,多個 Web 模塊共享業務層


1.4 為什么要隔離 Web 層與業務層(業務場景)

場景:一個訂單管理系統,有兩個模塊:

  • PC 端訂單管理(/pc/order

  • 移動端訂單管理(/mobile/order

如果使用 父子容器

  • 訂單 Service、DAO、事務管理器放在 父容器,PC 和移動端的 Controller 可以共享它們。

  • 兩個模塊的 Controller、攔截器、視圖配置放在 不同的子容器,互不干擾。


1.5 示例代碼:XML 版父子容器

web.xml

<!-- 父容器配置 -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/root-context.xml</param-value>
</context-param>
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- 子容器配置 -->
<servlet><servlet-name>spring-mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>spring-mvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

root-context.xml(父容器)

<context:component-scan base-package="com.example.service, com.example.dao" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>

servlet-context.xml(子容器)

<context:component-scan base-package="com.example.web" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/" /><property name="suffix" value=".jsp" />
</bean>

2. 父子容器的實現原理

一句話總結:父子容器通過 WebApplicationContext 的層級結構和 Bean 查找鏈實現單向依賴。


2.1 ContextLoaderListener(父容器)加載流程

源碼入口:ContextLoaderListenercontextInitialized()initWebApplicationContext()

流程

  1. 創建 WebApplicationContext 實例(默認 XmlWebApplicationContext)。

  2. contextConfigLocation 讀取父容器配置文件。

  3. 調用 refresh() 完成 Bean 加載和初始化。

  4. 將父容器放入 ServletContext,供子容器引用。

簡化源碼(偽代碼):

public WebApplicationContext initWebApplicationContext(ServletContext sc) {WebApplicationContext wac = createWebApplicationContext(sc);configureAndRefresh(wac);sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);return wac;
}

2.2 DispatcherServlet(子容器)加載流程

源碼入口:DispatcherServletinitServletBean()initWebApplicationContext()

流程

  1. 創建子容器 WebApplicationContext

  2. contextConfigLocation 讀取子容器配置文件。

  3. 調用 setParent() 將父容器引用傳入。

  4. 調用 refresh() 初始化 Web 層 Bean。

簡化源碼(偽代碼):

protected WebApplicationContext initWebApplicationContext() {WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = createWebApplicationContext(parent);configureAndRefresh(wac);return wac;
}

2.3 Bean 查找機制

WebApplicationContext 繼承自 ApplicationContext,其 getBean() 查找規則:

  1. 先在當前容器查找 Bean。

  2. 如果找不到且有父容器,則向父容器遞歸查找。

  3. 找不到則拋出 NoSuchBeanDefinitionException

    Bean getBean(String name) {if (this.containsBean(name)) {return this.getLocalBean(name);} else if (this.parent != null) {return this.parent.getBean(name);} else {throw new NoSuchBeanDefinitionException(name);}
    }
    

2.4 子容器訪問父容器 Bean(示例)

Service(父容器)

@Service
public class OrderService {public void createOrder() {System.out.println("訂單創建成功");}
}

Controller(子容器)

@Controller
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/create")public String createOrder() {orderService.createOrder();return "success";}
}

2.5 深入源碼:refresh() 方法調用鏈

refresh() 是 Spring 容器啟動的核心方法,父子容器初始化時都會調用它。無論是 ContextLoaderListener 還是 DispatcherServlet,最終都會走到這里。

核心流程(文字版調用鏈)

  1. prepareRefresh() — 準備環境變量、校驗配置文件、記錄啟動時間。

  2. obtainFreshBeanFactory() — 創建或刷新 BeanFactory 實例(DefaultListableBeanFactory)。

  3. prepareBeanFactory(beanFactory) — 注冊默認的 BeanPostProcessor、環境變量、依賴解析器等。

  4. postProcessBeanFactory(beanFactory) — 模板方法,允許子類擴展(如 AbstractRefreshableWebApplicationContext 會在這里注冊 Web 相關 Bean)。

  5. invokeBeanFactoryPostProcessors(beanFactory) — 執行 BeanFactoryPostProcessor(如 ConfigurationClassPostProcessor 解析 @Configuration@ComponentScan)。

  6. registerBeanPostProcessors(beanFactory) — 注冊所有 BeanPostProcessor(AOP、@Autowired 等依賴注入的關鍵)。

  7. initMessageSource() — 初始化國際化資源。

  8. initApplicationEventMulticaster() — 初始化事件廣播器。

  9. onRefresh() — 模板方法,Spring MVC 子容器會在這里初始化 HandlerMappingHandlerAdapter 等。

  10. registerListeners() — 注冊所有事件監聽器。

  11. finishBeanFactoryInitialization(beanFactory) — 實例化所有非懶加載單例 Bean。

  12. finishRefresh() — 發布 ContextRefreshedEvent 事件,標記容器啟動完成。

關鍵源碼(簡化版)

public void refresh() {synchronized (this.startupShutdownMonitor) {prepareRefresh();ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory);registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh(); // Web 容器在這里啟動 MVC 組件registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}
}

2.6 父子容器的 BeanFactory 關系

  • 父容器:DefaultListableBeanFactory

  • 子容器:DefaultListableBeanFactory,但 parentBeanFactory 指向父容器的 BeanFactory

  • 這種設計保證了 子容器可以訪問父容器 Bean,但父容器無法訪問子容器 Bean。

關系示意(文字版)

Parent BeanFactory (Service, DAO, TransactionManager)↑
Child BeanFactory (Controller, HandlerMapping, ViewResolver)

2.7 業務場景中的 refresh() 應用

假設我們有以下結構:

  • 父容器:DataSourceConfig(數據源)、TransactionConfig(事務管理器)

  • 子容器:WebMvcConfig(Controller、ViewResolver)

啟動時:

  1. ContextLoaderListener 調用 refresh() 完成父容器初始化,數據源和事務管理器就緒。

  2. DispatcherServlet 調用 refresh() 初始化子容器,Controller 中通過 @Autowired 獲取 Service。

  3. 由于子容器的 BeanFactory parentBeanFactory = 父容器的 BeanFactory,Controller 可以直接注入 Service。


2.8 示例:驗證父子容器 Bean 訪問規則

// 父容器中的 Bean
@Service
public class ProductService {public String getProductName() {return "MacBook Pro";}
}// 子容器中的 Bean
@Controller
public class ProductController {@Autowiredprivate ProductService productService; // 直接注入父容器的 Bean@RequestMapping("/product")@ResponseBodypublic String product() {return productService.getProductName();}
}

如果你嘗試在 父容器的 Bean 中注入子容器的 Controller,會報錯:

@Service
public class InvalidService {@Autowiredprivate ProductController controller; // ? NoSuchBeanDefinitionException
}

3. 父子容器的配置實踐

一句話總結:父子容器配置的核心是職責分層與包路徑隔離,確保 Web 層和業務層的 Bean 不會相互污染。


3.1 基于 XML 的配置

3.1.1 web.xml 配置

<!-- 父容器配置(業務層) -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/root-context.xml</param-value>
</context-param>
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- 子容器配置(Web 層) -->
<servlet><servlet-name>spring-mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>spring-mvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

解析

  • contextConfigLocation(父容器)會被 ContextLoaderListenerinitWebApplicationContext() 中讀取,然后傳給 refresh() 去加載配置。

  • DispatcherServlet 自己的 contextConfigLocation 也是在 initWebApplicationContext() 里讀取,并調用 refresh() 初始化子容器。


3.1.2 父容器配置(root-context.xml)

<context:component-scan base-package="com.example.service, com.example.dao" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/demo"/><property name="username" value="root"/><property name="password" value="123456"/>
</bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>

3.1.3 子容器配置(servlet-context.xml)

<context:component-scan base-package="com.example.web" /><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"/><property name="suffix" value=".jsp"/>
</bean>

3.2 基于 Java Config 的配置

3.2.1 父容器配置

@Configuration
@ComponentScan(basePackages = {"com.example.service", "com.example.dao"}
)
public class RootConfig {@Beanpublic DataSource dataSource() {BasicDataSource ds = new BasicDataSource();ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/demo");ds.setUsername("root");ds.setPassword("123456");return ds;}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

3.2.2 子容器配置

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.web"},excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Service.class // 排除業務層)
)
public class WebConfig implements WebMvcConfigurer {@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver vr = new InternalResourceViewResolver();vr.setPrefix("/WEB-INF/views/");vr.setSuffix(".jsp");return vr;}
}

3.3 包隔離策略

為了確保父子容器的 Bean 空間不沖突,建議:

  1. 業務層包路徑com.example.service, com.example.dao

  2. Web 層包路徑com.example.web

  3. 父容器的 @ComponentScan 不要掃描 com.example.web

  4. 子容器的 @ComponentScan 使用 excludeFilters 排除業務層包


3.4 業務場景示例

場景:PC 端和移動端共用業務邏輯,但 UI 層不同。

  • 父容器放:OrderService, ProductService

  • PC 子容器放:PcOrderController

  • Mobile 子容器放:MobileOrderController

好處:

  • 兩個子容器都能調用相同的 OrderService

  • 修改 PC 端 Controller 不會影響移動端 Controller

  • 啟動時可以單獨加載一個子容器進行測試

4. 父子容器的應用場景與局限性

一句話總結:父子容器非常適合中大型單體應用的分層管理,但在微服務場景中可能會被替代。


4.1 典型應用場景

場景 1:多個 Web 模塊共享業務邏輯

假設一個企業系統有:

  • 后臺管理模塊(/admin)

  • 前臺門戶模塊(/portal)

父容器

  • UserService

  • ProductService

  • DataSource

  • TransactionManager

子容器

  • admin 子容器:AdminControllerAdminInterceptor

  • portal 子容器:PortalControllerPortalInterceptor

好處:

  • Service 和 DAO 只加載一次,節省內存

  • 控制器互不干擾,職責分離


場景 2:多 DispatcherServlet 的多語言站點

  • /en/* → English 子容器

  • /cn/* → Chinese 子容器

  • 公共業務邏輯放在父容器


4.2 事務管理器必須放在父容器的原因

原因:事務管理器通常會在 Service 層通過 @Transactional 生效,而 @Transactional 的底層依賴于 AOP 代理,代理對象的生成需要在 業務 Bean 初始化階段完成。
如果事務管理器放在子容器:

  1. 父容器初始化 Service 時找不到事務管理器 Bean(因為父容器無法向下訪問子容器)。

  2. 事務增強器 BeanFactoryTransactionAttributeSourceAdvisor 無法正常創建代理對象,導致事務失效。

簡化源碼片段(事務增強器注冊過程):

public class ProxyTransactionManagementConfiguration {@Beanpublic BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(...) {// 需要獲取事務管理器 Bean}
}

因為這個 Bean 注冊發生在父容器 refresh() 階段,所以事務管理器必須提前在父容器中準備好。


4.3 常見問題

問題 1:Bean 覆蓋

如果父子容器中有相同名稱的 Bean,子容器會優先返回自己的 Bean。

// 父容器
@Bean("productService")
public ProductService productServiceV1() { ... }// 子容器
@Bean("productService")
public ProductService productServiceV2() { ... }

結果:Controller 注入的是子容器版本。

解決方法:

  • 使用 @Primary 明確優先級

  • 或者使用 @Qualifier 指定 Bean 名稱


問題 2:依賴沖突

  • 子容器中掃描到的 Bean 如果引用了父容器不存在的依賴,會導致啟動失敗。

  • 避免在 Service 層直接引用 Controller


4.4 在微服務架構中的適用性

  • 在微服務(如 Spring Boot + Spring Cloud)中,每個服務本質上都是一個獨立的 ApplicationContext,父子容器的概念意義不大。

  • 替代方案:

    • 通過 API Gateway 和 Feign Client 進行模塊解耦

    • 使用共享依賴庫(JAR)來復用業務邏輯


4.5 示例:父容器中的事務管理器配置

RootConfig.java

@Configuration
@ComponentScan(basePackages = {"com.example.service", "com.example.dao"})
@EnableTransactionManagement
public class RootConfig {@Beanpublic DataSource dataSource() {BasicDataSource ds = new BasicDataSource();ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/demo");ds.setUsername("root");ds.setPassword("123456");return ds;}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

OrderService.java

@Service
public class OrderService {@Transactionalpublic void createOrder() {System.out.println("事務開始:創建訂單");// 數據庫操作...}
}

OrderController.java

@Controller
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/order")@ResponseBodypublic String order() {orderService.createOrder(); // 事務生效return "success";}
}

5. 父子容器的進階優化


5.1 使用 WebApplicationInitializer 手動創建父子容器

Spring MVC 默認是通過 ContextLoaderListener 創建父容器,再由 DispatcherServlet 創建子容器。
我們可以用 Java Config 全程替代 XML,并且手動精確控制父子容器的關系。

示例代碼

public class MyWebAppInitializer implements WebApplicationInitializer {@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {// 1. 創建父容器AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();rootContext.register(RootConfig.class);servletContext.addListener(new ContextLoaderListener(rootContext));// 2. 創建子容器(DispatcherServlet 專用)AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();mvcContext.register(WebMvcConfig.class);ServletRegistration.Dynamic dispatcher =servletContext.addServlet("dispatcher", new DispatcherServlet(mvcContext));dispatcher.setLoadOnStartup(1);dispatcher.addMapping("/");}
}

核心好處

  • 父子容器的邊界由你自己定義

  • 可以注冊多個 DispatcherServlet,每個都有獨立的子容器

  • 可以在父容器創建前做預處理(如動態加載配置文件)


5.2 父子容器 Bean 沖突優化

在開發中,父子容器如果不加規則,很容易出現 Bean 名稱沖突問題。

解決策略

  1. 命名空間法

    • 父容器所有 Bean 以 core* 開頭

    • 子容器 Bean 以 web* 開頭
      這樣在注入時幾乎不會沖突

  2. @Primary
    標記優先被注入的 Bean

    @Bean
    @Primary
    public ProductService newProductService() { ... }
    
  3. @Qualifier
    明確注入指定 Bean 名稱


5.3 事務與 AOP 跨容器優化

當事務涉及多個子容器的 Controller 時,有兩個注意點:

  • 事務必須放在父容器

    • 否則子容器 Controller 調用父容器 Service 時可能找不到事務增強器

  • AOP 切面建議也放在父容器

    • 避免每個子容器重復創建切面 Bean

示例:切面放在父容器

@Aspect
@Component
public class LogAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore() {System.out.println("調用 Service 前記錄日志");}
}

5.4 Spring Boot 中的父子容器簡化策略

Spring Boot 雖然默認是單容器,但仍然可以模擬父子容器:

  • 父容器:SpringApplicationBuilder 的第一個 sources()

  • 子容器:child() 方法

示例:Boot 模擬父子容器

new SpringApplicationBuilder(ParentConfig.class).child(WebConfig.class).run(args);

這樣可以在 Boot 項目中仍然使用父子容器分層結構,但更輕量。


5.5 性能與維護建議

  • 性能優化

    • 父容器只加載一次,不要放和 Web 強綁定的 Bean

    • 子容器盡量只掃描 Controller、攔截器等 Web 組件

  • 維護優化

    • 清晰標注哪些類屬于父容器、哪些屬于子容器

    • 在多模塊項目中,將父容器 Bean 放到獨立的 core 模塊,子容器 Bean 放到 web 模塊

6. 父子容器的源碼解析


6.1 創建父容器:ContextLoaderListener

當 Web 容器啟動時,ContextLoaderListener 會先調用:

public void contextInitialized(ServletContextEvent event) {initWebApplicationContext(event.getServletContext());
}

這里核心步驟:

  1. 創建 WebApplicationContext(通常是 XmlWebApplicationContextAnnotationConfigWebApplicationContext

  2. 調用 configureAndRefreshWebApplicationContext()

    • 設置配置文件位置

    • 調用 refresh() 初始化所有 Bean


6.2 創建子容器:DispatcherServlet

DispatcherServletinit() 方法中:

this.webApplicationContext = initWebApplicationContext();

initWebApplicationContext() 核心:

  1. 如果沒有傳入外部的 WebApplicationContext,就自己創建一個

  2. 調用 setParent(parentContext) 將父容器傳進來

  3. 調用 refresh() 初始化子容器 Bean


6.3 Bean 查找的向上鏈路

當你在子容器中調用:

ctx.getBean("xxx");

執行流程:

  1. 在子容器的 beanFactory 查找 BeanDefinition

  2. 如果沒找到,就調用:

    if (this.parent != null) {return this.parent.getBean(name, requiredType);
    }
    
  3. 這樣會遞歸向父容器查找,直到頂層容器或拋出異常


6.4 時序圖(簡化版)

[Servlet 容器啟動]↓
ContextLoaderListener -------------------------------| 創建父容器| refresh() 父容器↓
DispatcherServlet -----------------------------------| 創建子容器| setParent(父容器)| refresh() 子容器↓
運行中:getBean() → 子容器→ 父容器→ 祖先容器...

6.5 為什么理解調用鏈很重要

  • 調試問題
    當出現 "NoSuchBeanDefinitionException" 時,你能立刻判斷是子容器沒掃描到,還是父容器沒加載

  • 性能優化
    你知道哪些 Bean 會被多個子容器共享,就應該放到父容器避免重復初始化

  • 擴展能力
    可以自己寫 WebApplicationInitializer 精準控制父子容器的生命周期

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

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

相關文章

AI賦能SEO關鍵詞優化策略

內容概要 人工智能&#xff08;AI&#xff09;技術正深刻改變著搜索引擎優化&#xff08;SEO&#xff09;的實踐方式&#xff0c;尤其在關鍵詞研究這一核心領域帶來了革命性的影響。本文聚焦于AI如何賦能SEO關鍵詞優化策略&#xff0c;系統性地探討其核心價值與應用路徑。我們將…

虛擬機Ubuntu圖形化界面root用戶登錄錯誤

當在 Ubuntu 圖形界面登錄 root 用戶出現錯誤無法進入時 1. 檢查 PAM 配置文件 PAM&#xff08;Pluggable Authentication Modules&#xff0c;可插拔認證模塊&#xff09;負責管理用戶認證相關的策略。圖形登錄界面的 PAM 配置文件通常是 /etc/pam.d/gdm-password 。以管理員權…

【雜談】-逆縮放悖論:為何更多思考會讓AI變“笨“?

逆縮放悖論&#xff1a;為何更多思考會讓AI變"笨"&#xff1f; 文章目錄逆縮放悖論&#xff1a;為何更多思考會讓AI變"笨"&#xff1f;1、解碼逆縮放現象2、AI 推理失效的五大癥結3、AI 推理應對復雜度的策略圖譜4、人工智能評估體系的反思5、人工智能推理…

強制用戶更改WordPress密碼的重要性及實現方法

確保 WordPress 網站的安全性是每位網站管理者的重要任務。在網絡安全日益受到關注的今天&#xff0c;為用戶提供安全、穩定的網絡環境至關重要。而一個有效的方法就是強制用戶定期更改密碼。這篇文章將介紹為什么要強制用戶更改密碼以及如何在 WordPress 中實現這一功能。同時…

計算機基礎速通--數據結構·串的應用

如有問題大概率是我的理解比較片面&#xff0c;歡迎評論區或者私信指正。 友友們&#xff0c;我遇到了一個大問題&#xff0c;技術類的英文面&#xff08;ai應用開發/java后端偏金融方向&#xff09;該如何準備&#xff1f;本人英語就過了個六級&#xff0c;腦闊疼額。友友們有…

05--STL認識(了解)

1. STL概念——標準模板庫 STL(standard template libaray-標準模板庫)&#xff1a;是C標準庫的重要組成部分&#xff0c;不僅是一個可復用的組件庫&#xff0c;而且是一個包羅數據結構與算法的軟件框架。 STL與CPP標準庫的關系&#xff1a; 2. STL的版本 3. STL的組成 4. STL…

VBA經典應用69例應用9:ReDim語句的語法

《VBA經典應用69例》&#xff08;版權10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是專門針對初級、中級學員在學習VBA過程中可能遇到的案例展開&#xff0c;這套教程案例眾多&#xff0c;緊貼“實戰”&#xff0c;并做“戰術總結”&#xff0c;以便…

連鎖店管理系統的庫存跟蹤功能:數字化轉型下的零售運營核心

在連鎖零售行業&#xff0c;庫存管理的效率直接決定著運營成敗。傳統人工庫存管理模式早已難以應對全渠道銷售時代的復雜需求&#xff0c;而連鎖店管理系統的庫存跟蹤功能&#xff0c;正成為解決庫存難題、提升客戶體驗的關鍵武器。本文將深入解析施易德&#xff08;cegid&…

Nestjs框架: 接口安全與響應脫敏實踐 --- 從攔截器到自定義序列化裝飾器

接口安全問題&#xff1a;敏感數據脫敏的必要性 在用戶注冊成功后&#xff0c;若直接將用戶數據&#xff08;如密碼、ID 等&#xff09;返回給前端&#xff0c;存在嚴重的安全風險 為此&#xff0c;需要在接口響應前對數據進行脫敏處理 關鍵點&#xff1a; 敏感字段&#xff…

Python包與虛擬環境工具全景對比:從virtualenv到uv的演進

Python 的開發環境管理一直是綜合性的工程問題。隨著工具和規范的不斷進化&#xff0c;我們看到了從 virtualenv / pip 開始&#xff0c;到 pipenv 和 poetry 的環境一體化&#xff0c;再到 uv 和 hatch 這樣的一體化、高性能新生代工具。 本文將對比這些工具的特點、優勢和選型…

期貨和期權對沖后能盈利嗎?

本文主要介紹期貨和期權對沖后能盈利嗎&#xff1f;期貨和期權作為金融衍生品的兩大核心工具&#xff0c;其組合對沖策略的盈利性取決于市場走勢、策略設計、成本管控及風險對沖效果。對沖的本質是降低風險&#xff0c;但通過合理設計&#xff0c;部分策略可在對沖風險的同時創…

【其他分類】Showrunner AI版的Netflix 互動故事創作平臺 進行動畫生成與微調、角色場景創建

Showrunner是一個AI 驅動的角色場景動畫。視覺風格較為統一&#xff0c;偏向 3D Q 版卡通風格&#xff0c;支持語音對白修改、鏡頭相機切換、動畫角色和場景設置等功能。 論文原文中文翻譯官方地址pdf版 、網頁版pdf版https://www.showrunner.xyz/ 當前的2D 動畫軟件&#xff…

K8s 常見故障案例分析

#作者&#xff1a;程宏斌 文章目錄一、節點故障&#xff08;一&#xff09;節點 NotReady 狀態排查步驟解決方案二、Pod 故障&#xff08;一&#xff09;Pod 一直處于 Pending 狀態排查步驟解決方案&#xff08;二&#xff09;Pod 頻繁重啟故障現象排查步驟解決方案三、控制器故…

半精度權重 及 Phi-3線性層的權重分布

半精度權重 我們可以使用張量的 to() 方法以及適當的類型 torch.float16,將權重轉換為 FP16: torch.manual_seed(11) weights = torch.randn(1000) * .07 weights.min(),

Linux怎么安裝Docker?環境怎么搭建?步驟是什么?如何配置?有哪些注意事項?出現問題怎么排除?

一、Docker簡介與環境準備 1.1 什么是Docker Docker是一個開源的容器化平臺&#xff0c;它使用Linux內核的cgroup&#xff0c;namespace以及OverlayFS類的UnionFS等技術&#xff0c;對進程進行封裝隔離&#xff0c;屬于操作系統層面的虛擬化技術。Docker能夠自動執行重復性任務…

apiSQL網關調優:釋放單節點的最大潛能

前言 在構建高性能、高可用的API服務時&#xff0c;apiSQL 提供了強大的集群部署模式&#xff0c;通過橫向擴展來分散負載、提高吞吐量。然而&#xff0c;在某些場景下&#xff0c;我們同樣需要關注并最大化單個節點的處理能力。當單個 apiSQL 網關節點需要處理高并發請求或承載…

【開源工具】網絡交換機批量配置生成工具開發全解:從原理到實戰(附完整Python源碼)

?? 【開源工具】網絡交換機批量配置生成工具開發全解:從原理到實戰(附完整Python源碼) ?? 個人主頁:創客白澤 - CSDN博客 ?? 系列專欄:??《Python開源項目實戰》 ?? 熱愛不止于代碼,熱情源自每一個靈感閃現的夜晚。愿以開源之火,點亮前行之路。 ?? 希望大家…

【插件式微服務架構系統分享】之 解耦至上:gateway 網關與APISIX 網關的不同分工

【插件式微服務架構系統分享】之解耦至上&#xff1a;gateway 網關與APISIX 網關的不同分工作者&#xff1a;朱元祿一、一個比方 APISIX 就像是一個專業的高速公路收費站&#xff0c;不屬于你公司自己造的路&#xff0c;而是專門為所有車輛&#xff08;流量&#xff09;設計的&…

【感知機】感知機(perceptron)學習算法例題及詳解

感知機( perceptron )是二類分類的線性分類模型&#xff0c;其輸入為實例的特征向量&#xff0c;輸出為實例的類別&#xff0c;取1 和-1二值。感知機對應輸入空間(特征空間)中將實例劃分為正負兩類的分離超平面&#xff0c;是一種判別模型。感知機是神經網絡與支持向量機的基礎…

Linux基礎命令速查:從入門到精通

Linux常用命令指南一、操作系統概述1 . 什么是操作系統&#xff1f;2. 為什么需要操作系統&#xff1f;二、Linux基礎命令1. 目錄與文件操作2. 文件操作命令3. 文件查看命令4. 文本處理命令三、重定向1. 重定向符號四、Linux系統概念1. 文件系統特點2. 路徑規則3. 通配符五、壓…