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

06.Servlet容器

1.在 web.xml 中配置前端处理器

<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup>
容器启动时先初始化load-on-startup值小的 Servlet,
若不配置该标签(或值为负数),则 Servlet 会在第一次被客户端请求时才初始化。
</servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
将所有的请求都交给 DispatcherServlet 处理。
</servlet-mapping>

2.DispatcherServlet 继承链:
DispatcherServlet FrameworkServletHttpServletBeanHttpServletGenericServletServlet

  • GenericServlet 持有 ServletConfig 对象,实现 Servlet 规范,ServletConfig 对象是由 web 容器创建的,而非 DispatcherServlet 自己生成。当 web 容器初始化 DispatcherServlet 时,会先创建 ServletConfig 实例(封装该 Servlet 的配置),再通过init(ServletConfig config)方法(顶层触发)将其注入到 GenericServlet 中。最终持有 ServletConfig 的是 GenericServlet,GenericServlet 实现了init(ServletConfig config),将传入的对象赋值给自己的私有成员(private ServletConfig config),因此,DispatcherServlet 作为子类,会继承这个成员变量,且默认提供无参 init() 方法(重载 init(ServletConfig)),子类可直接重写无参 init() 完成初始化(无需关注 ServletConfig 传递)。

  • HttpServlet针对 HTTP 协议的专用 Servlet 抽象类,核心作用是协议解析与请求分发:

    • 重写 service(ServletRequest, ServletResponse),将参数强转为HttpServletRequest/HttpServletResponse
    • 根据 HTTP 请求方法(GET/POST/PUT/DELETE 等),分发到对应 doXxx() 方法(如 doGet()、doPost())
  • HttpServletBean 由 GenericServlet 里面的 init(ServletConfig config)内部会自动调用由本类重写的init()方法:

    • 获取到 ServletConfig 对象,由 GenericServlet 提供。

      ServletConfig config = getServletConfig(); // 该方法由GenericServlet提供
      

      ServletConfig的设计职责:ServletConfig是单个Servlet的“配置对象”,存储当前Servlet专属的初始化参数(),提供getInitParameter(String name)方法,仅能获取当前Servlet自己的参数。

    • 将参数映射到当前实例的属性中(如给contextConfigLocation赋值)

      PropertyValues pvs = new ServletConfigPropertyValues(config, this.requiredProperties)
      

      ServletConfigPropertyValues会遍历config.getInitParameterNames(),将所有<init-param>转换为PropertyValues集合(ServletConfig本质上是一个键值对容器,而当前类的作用是把这些键值对提取出来,转换为Spring能处理的属性格式),都是键值对,但是pvs有更为强大的API。pvs中的值只是字符串(如maxSize的值是“1024”),但目标Bean的属性可能是int(即int maxSize),这时需结合BeanWrapper进行类型转换。

      获取当前对象的BeanWrapper实例:
      BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this)
      bw.setPropertyValues(pvs, true) // 将pvs注入到当前bean属性中
      
      BeanWrapper是什么?

      是操作Bean属性的核心工具,它提供了:

      • 属性读取、设置(通过反射实现)
      • 类型转换(将字符串等类型转换为Bean支持的目标类型,如String转为int)
      为什么非要将ServletConfig转换为PropertyValues?

      数据结构不统一
      ServletConfig通过 Enumeration name = config.getInitParameterNames()提供键名,再通过键名获取键值,这种“枚举+逐个获取”的方式是Servlet规范定义的标准接口,不是Spring能直接操作的“集合形态”。而PropertyValues内部是List集合,每个PropertyValue直接封装“属性名+原始值”,每个PropertyValue的name直接对应Bean的属性名。如 new PropertyValue("maxFiles", "1024"), BeanWrapper会遍历集合,通过name = "maxFiles",找到setter方法setMxFiles,并将 value="1024" 转换为 int 类型后注入。说到底是 Servlet 的枚举错误,且进行类型转换时,仅返回字符串,需要手写转换逻辑,但是 PropertyValues 可以被 ConversionService(可能背后逻辑仅支持集合获取对应的值吧) 识别自动根据 Bean 属性类型完成转换 。

      那么这里的 requiredProperties 又是什么?

      字符串数组 requiredProperties 是一种防御编程性手段,通过明确声明“哪些属性必须配置”,可以在应用启动阶段校验配置的完整性,避免因缺少相关参数导致运行时出现难以排查的异常。在将格式转换为 pvs 中会检查 requiredProperties 中指定的属性是否缺失,如果缺失会直接抛出异常,只有所有的属性都存在时,才会正常创建 PropertyValues 对象,继续后面的属性注入流程。

      // 留给子类的初始化入口
      initServletBean();//该方法由本类重写的init()方法调用,留给FrameworkServlet重写
      
  • ④ FrameworkServlet 里实现子容器的诞生

    • 初始化或查找 WebApplicationContext

      @Override
      protected final void initServletBean() throws ServletException {// 初始化 Spring WebApplicationContext(核心逻辑)this.webApplicationContext = initWebApplicationContext();//这个方法就是“催生”子容器的关键// 扩展方法(空实现,留给子类按需重写)initFrameworkServlet();
      }
      
    • 先看看有没有现成可用的现成容器。

        1. 有没有提前准备好的?比如开发者主动创建了一个 WebApplicationContext 并绑定了 DispatcherServlet,如果有,直接用现成的。
        1. 有没有之前剩下的?从 Web 应用的全局环境(ServletContext)里找找,有没有之前创建的子容器。
        1. 如果都没有,就进入下一步:全新创建。
    • 全新创建子容器,如果没有现成的,会调用 createWebApplicationContext() 方法。
      createWebApplicationContext()里面创建子容器的两种方法

        1. 如果用 xml 配置(如 dispatcher-servlet.xml)就用 new XmlWebApplicationContext()。
        1. 如果用纯注解(比如 @Controller、@Configuration)就用 new AnnotationConfigWebApplicationContext()

      关键操作是:必须先把之前 ContextLoaderListener 创建的“父容器”设为父容器
      setParent(rootContext);

    • 往子容器里面装东西
      子容器创建好后,会执行 onRefresh() 方法,加载并初始化所有它该管的东西(如 HandlerMapping、HandlerAdapter、ViewResolver)

      // FrameworkServlet 中 onRefresh() 是空实现,交给子类 DispatcherServlet 重写
      protected void onRefresh(ApplicationContext context) {// For subclasses: do nothing by default.
      }
      
    • 最后子容器会被存到 ServletContext 里,方便后续用随时都能找到它。(比如其他组件需要获取 Controller 时,就从这里查)。

      if (this.webApplicationContext == null) { // 没有提前准备好子容器this.webApplicationContext = findWebApplicationContext();
      } else if (this.webApplicationContext == null) { // 也没有找到容器this.webApplicationContext = createWebApplicationContext();
      }
      
    • 那怎么主动创建子容器并传给 DispatcherServlet 呢?
      实例化子容器:

      XmlWebApplicationContext childContext = new XmlWebApplicationContext();
      childContext.setParent(rootContext); // 设置父容器
      childContext.setConfigLocation(getContextConfigLocation()); // Spring-mvc.xml 路径
      childContext.refresh(); // 触发容器初始化 Bean、注册组件等
      childContext.setServletContext(getServletContext());//关联ServletContext
      getServletContext().setAttribute(MVC_CONTEXT_KEY,childContext);//将子容器绑定到servletcontext中(提供给dispatcherservlet获取)
      
  • DispatcherServlet 中重写了 onRefresh(),并初始化所有策略组件。

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

相关文章:

  • PbootCMS留言发送到邮箱,邮件标题如何修改
  • 23、【Ubuntu】【远程编写】内网穿透:SSH 反向隧道
  • 【STM32】定时器、PWM - 教程
  • 大模型安全:共享 GPU 本地内存泄露
  • React Hooks闭包陷阱导致的状态错乱,怎么办
  • MAF快速入门(4)多Agent工作流编排
  • 人工智能之数据分析 Pandas:第一章 简介和安装
  • Dbeaver - 一些好用的设置
  • 内存管理-54-slub-1-文档翻译等 - Hello
  • MYSQL - 数据库优化:慢查询
  • 完整教程:AI代码开发宝库系列:PDF文档解析MinerU
  • 2025年烤兰打包带厂家口碑排行,这十家备受推崇,打包带钢/光伏支架打包带/电镀锌打包带/铜棒打包带/镀锌打包扣烤兰打包带销售厂家推荐排行榜
  • 实用指南:海外短剧系统开发:应对高并发访问的数据库优化与缓存策略
  • 2025年12月AI SEO优化公司推荐:解锁智能搜索流量新密码
  • 易路:连锁餐饮人力资源数智化转型升级新引擎
  • 尘埃粒子计数器生产厂家联系电话,大流量尘埃粒子计数器/粒子计数器/尘埃粒子计数器/悬浮粒子计数器/尘埃粒子计数器厂家排名
  • 尘埃粒子计数器供应商推荐榜,台式粒子计数器/尘埃粒子计数器在线监测系统/大流量尘埃粒子计数器/尘埃粒子计数器公司电话
  • 2025年AI教育培训供应商推荐榜:聚焦企业AI培训,精选优质机构供参考
  • python笔记-循环
  • 2025年12月ChatGPT优化排名公司推荐
  • 2025年12月西安旧房翻新公司TOP5推荐:装修/家装/室内设计领衔企业
  • 2025年12月深圳艺考生文化课培训推荐:聚焦分层教学与艺考政策适配力!
  • 2025 美本留学机构十大推荐:全维服务护航,头部机构引领申请路
  • 2025年AI教育培训课程推荐榜:覆盖AI培训全场景指南
  • 2025污染源监测设备厂家有哪些,废气监测设备厂家有哪些测评
  • 2025年12月通道闸机、速通门品牌厂家TOP10榜单发布,选购指南同步更新
  • 模切机厂家有哪些?国内知名企业推荐
  • 推荐几个模切机品牌 国内优质厂商盘点
  • 自动模切机厂家哪家专业?行业技术实力对比解析
  • 2025年烤漆打包带行业领先品牌,五金打包带/烤漆打包带/冷镀锌打包带/镀锌打包带/光伏支架打包带/打包铁条烤漆打包带销售厂家口碑排行