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

07.自定义子容器

1.使用监听器传入自定义的子容器

//监听器
public class addWebApplicationContextListener implements ServletContextListener {// 子容器在ServletContext中的唯一标识(全局常量,避免写错)public static final String MVC_CONTEXT_KEY = "SPRING_MVC_CONTEXT";public void contextInitialized(ServletContextEvent sce) {XmlWebApplicationContext mvcContext = null;try {// 创建xml型Web容器(适配传统xml配置)mvcContext = new XmlWebApplicationContext();// 指定子容器的配置文件(resources根目录下的spring-mvc.xml)mvcContext.setConfigLocation("classpath:spring-mvc.xml");// 关联ServletContextmvcContext.setServletContext(sce.getServletContext());// 刷新容器(核心,触发Bean扫描、初始化)mvcContext.refresh();// 将子容器绑定到ServletContext供DispatcherServlet获取sce.getServletContext().setAttribute(MVC_CONTEXT_KEY, mvcContext);} catch (Exception e) { // 捕获异常,避免监听器静默失败e.printStackTrace();throw new RuntimeException("创建Spring MVC子容器失败:" + e.getMessage(), e);}}
}

2.版本一:自定义DispatcherServlet版本:重写FrameworkServlet里的initWebApplicationContext方法

public class CustomDispatcherServlet extends DispatcherServlet {// 自定义标记,确保onRefresh仅执行一次private boolean onRefreshInvoked = false;// 国家之间同步锁,保证onRefresh执行时线程安全private final Object customOnRefreshLock = new Object();protected WebApplicationContext initWebApplicationContext() {// 自定义查找根容器,由ContextLoaderListener创建,否则为nullWebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext mvcContext = null;// 核心:从ServletContext获取监听器创建的子容器mvcContext = (WebApplicationContext) getServletContext().getAttribute(容器唯一标识);// 非空校验,子容器为null直接抛出异常if (mvcContext == null) throw new RuntimeException("获取子容器失败!请检查监听器是否注册");// 为子容器绑定父容器if (mvcContext instanceof XmlWebApplicationContext) {XmlApplicationContext xmlContext = (XmlApplicationContext) mvcContext;if (xmlContext.getParent() == null) xmlContext.setParent(rootContext);}// 调用onRefresh初始化MVC核心组件if (!onRefreshInvoked) synchronized (this.customOnRefreshLock) {onRefresh(mvcContext); // 触发HandlerMapping等组件初始化onRefreshInvoked = true;}// 将子容器绑定到ServletContext供Spring MVC内部全局获取String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX + getServletName();getServletContext().setAttribute(attrName, mvcContext);// 返回有效容器供DispatcherServlet使用return mvcContext;}
}

3.版本二:自定义DispatcherServlet版本2:重写init(ServletConfig config)

public class CustomDispatcherServlet2 extends DispatcherServlet {private WebApplicationContext mvcContext;@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("=====自定义DispatcherServlet初始化");mvcContext = (WebApplicationContext) config.getServletContext().getAttribute(addWebApplicationContextListener.MVC_CONTEXT_KEY);if (mvcContext == null) {new ServletException("获取子容器失败");}System.out.println("获取子容器成功"+mvcContext.getId());super.init(config);//重点,保存ServletConfig对象}@Overrideprotected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {return mvcContext;}//这个方法不用重写,重写它只是为了增强一个日日志功能@Overrideprotected void initStrategies(ApplicationContext context) {super.initStrategies(context); System.out.println("初始化完成,使用子容器");}
}

没有重写 initWebApplicationContext ,会默认调用 findWebApplicationContext() ,从 ServletContext 查找子容器,但是该方法是按照固定的Key( FrameworkServlet.SERVLET_CONTEXT_PREFIX + Servlet名称去找子容器 ),大概率会返回 null ,故而肯定会进入 createWebApplicationContext 方法,返回自定义的子容器。

http://www.jsqmd.com/news/58769/

相关文章:

  • cjw_蓝桥杯python基础学习系列一—_语言基础
  • 从硬盘I/O到网络传输:Kafka与RocketMQ读写模型及零拷贝技术深度对比
  • 测试飞书一面
  • 华三无线集中转发模式配置
  • 技术总监亲述:工作授权不是甩锅,掌握这8步让团队战斗力提升300%
  • AI人工智能:分享技术干货
  • 在AI快速落地的时代,洞察真实需求成为关键——某开源个人发布平台用户需求分析
  • 深入解析:逻辑门(Logic Gate)是什么?
  • 关于Proteus在编译时提示Failed to set firmware property.的问题
  • Linux中级の备份服务Rsync
  • 2025冷却塔厂家实力排行榜:无锡科巨以高效节能技术引领,六家高潜力本土品牌深度解析
  • 2025.12.2
  • EndNote.2025 中文版安装激活教程
  • CF1660E-Matrix and Shifts
  • c++实验四
  • 牛客网周赛120
  • 在数字时代寻找内心的宁静
  • kubernetes集群中怎么强制删除处于Terminating的namespace资源
  • 检查路径深度
  • chrome driver下载地址
  • 成群结队 - 冲刺总结
  • 从 Pandas 转向 Polars:新手常见的10 个问题与优化建议
  • 二进制兼容
  • 【C语言】选择结构和循环结构的进阶 - 指南
  • 从原型到生产:大型语言模型实践指南
  • 成群结队--冲刺计划
  • 第五天敏捷冲刺
  • Java进阶 多线程
  • Java进阶网络编程,UDP,TCP通信
  • CCPC郑州站 笨蛋题 II