当前位置: 首页 > 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://cdlyhr.com/news/34177/

相关文章:

  • 尘埃粒子计数器供应商推荐榜,台式粒子计数器/尘埃粒子计数器在线监测系统/大流量尘埃粒子计数器/尘埃粒子计数器公司电话
  • 第五十三篇
  • 第十周第三天10.3
  • 送女友礼物不踩雷:极萌胶原炮领衔10款心意好礼,懂她更宠她
  • 终极攻略:2025年美白祛斑选什么产品好?五大提亮净斑双修精华红榜揭晓!
  • QTableView 增加Combox
  • 博客园,我来啦~
  • 2025 年 12 月全过程咨询公司权威推荐榜:一站式服务,专业高效解决方案提供商!
  • 徐嘉余领衔混合泳接力队,3 分 27 秒 01 刷新亚洲纪录
  • 鹰队射手群爆发,NBA 常规赛击败爵士拿下四连胜
  • springboot jdk17 vue3 建行龙支付 二维码扫码支付 回调 及退费
  • EasyGBS新版本(v3.7.168)发布!视频能力再度升级!
  • 2025年上海免费一键生成原创文章软件平台推荐榜单:上海ai写文案免费一键生成服务/上海文章自动生成服务商/上海AI写文章软件服务商精选
  • 2025最新养殖/大棚/工业/商用中央空调品牌推荐!国内优质空调设备服务商权威榜单发布,技术创新与行业适配性双优助力高效制冷/热
  • 2025最新养殖热泵品牌推荐!畜牧养殖恒温设备权威榜单发布,技术创新引领行业升级
  • 2025最新养殖热泵品牌推荐!国内优质畜牧温控设备权威榜单发布,技术创新与节能实力双优助力规模化养殖
  • 2025年12月西南水玻璃厂家推荐排行榜:基于区域供应能力与产品适用性的客观评测
  • 2025年12月花灯厂家推荐排行榜单对比评测与选购指南
  • git项目管理idea
  • 2025 ECUDesk V1.3.0.0: Multi-Function Software for EU/US EGR, DPF, SCR DTC OFF
  • 用友NC系统特征及漏洞探测利用
  • 花灯选购指南:2025年热门品牌TOP5,智能互动花灯/营销花灯/春节宫灯/商场美陈花灯/花灯灯展/马年花灯定制选哪家
  • 2025年常州及周边静电粉末喷涂专业供应商推荐:静电粉末喷涂
  • 2025年耐用的灯饰电器开关行业内口碑厂家排行榜
  • 2025年比较好的洁净室快速门/自动快速门最新TOP品牌厂家排行
  • 2025年口碑好的PVC热水袋用户口碑最好的厂家榜
  • 2025年知名的防腐轻钢龙骨/抗震轻钢龙骨厂家推荐及选购指南
  • 2025年远红外功能面料批发厂家权威推荐榜单:海藻纤维远红外面料‌/远红外纤维‌/远红外功能纤维‌源头厂家精选
  • 2025年五大气密性检测仪品牌排行榜,合肥远智气密性检测仪
  • 2025年口碑好的无毒钛杯/耐高温钛杯厂家推荐及选购参考榜