spring mvc源码学习笔记之九

news2025/1/9 20:54:58

在前面的文章中,我们简单讲了可以用 WebApplicationInitializer 接口去替换 web.xml
本文对这一块再做个详细讲解。
WebApplicationInitializer 这个接口的 javadoc 中有提到可以用继承 AbstractAnnotationConfigDispatcherServletInitializer 的方式替换实现 WebApplicationInitializer 接口。
先看代码,然后再具体解释。

  • pom.xml 的内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.qsm</groupId>
        <artifactId>learn</artifactId>
        <version>1.0.0</version>
    </parent>

    <groupId>com.qs</groupId>
    <artifactId>demo-47</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.28</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
  • com.qs.demo.MyWebApplicationInitializer 的内容如下
package com.qs.demo;

import com.qs.demo.config.RootApplicationContextConfig;
import com.qs.demo.config.WebApplicationContextConfig;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author qs
 * @date 2023/07/20
 */
public class MyWebApplicationInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootApplicationContextConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebApplicationContextConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }
}
  • com.qs.demo.config.RootApplicationContextConfig 的内容如下
package com.qs.demo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author qs
 * @date 2023/07/20
 */
@Configuration
@ComponentScan(basePackages = {"com.qs.demo.service", "com.qs.demo.dao"})
public class RootApplicationContextConfig {}
  • com.qs.demo.config.WebApplicationContextConfig 的内容如下
package com.qs.demo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author qs
 * @date 2023/07/20
 */
@Configuration
@ComponentScan(basePackages = {"com.qs.demo.controller"})
public class WebApplicationContextConfig {}
  • com.qs.demo.controller.PeopleController 的内容如下
package com.qs.demo.controller;

import com.qs.demo.service.PeopleService;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qs
 * @date 2023/07/20
 */
@RequestMapping("/people")
@RestController
public class PeopleController {

    private final PeopleService peopleService;

    public PeopleController(PeopleService peopleService) {
        this.peopleService = peopleService;
    }

    @GetMapping("/01")
    public String a() {
        return peopleService.a();
    }
}
  • com.qs.demo.service.PeopleService 的内容如下
package com.qs.demo.service;

import com.qs.demo.dao.PeopleDao;

import org.springframework.stereotype.Service;

/**
 * @author qs
 * @date 2023/07/20
 */
@Service
public class PeopleService {

    private final PeopleDao peopleDao;

    public PeopleService(PeopleDao peopleDao) {
        this.peopleDao = peopleDao;
    }

    public String a() {
        return peopleDao.a();
    }
}
  • com.qs.demo.dao.PeopleDao 的内容如下
package com.qs.demo.dao;

import org.springframework.stereotype.Repository;

import java.util.UUID;

/**
 * @author qs
 * @date 2023/07/20
 */
@Repository
public class PeopleDao {

    public String a() {
        return UUID.randomUUID().toString();
    }

}

以上就是全部代码

接下来重点分析下 AbstractAnnotationConfigDispatcherServletInitializer 这个类,源代码不多,如下

/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.support;

import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

/**
 * 下面这句话意思是:这个类是一个 WebApplicationInitializer(这个抽象类实现了 WebApplicationInitializer 接口)。
 * 它用于注册 DispatcherServlet 。
 * 并且,它使用 Java-based 的 spring 配置,也就是基于注解的配置方式。
 *
 * {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializer}
 * to register a {@code DispatcherServlet} and use Java-based Spring configuration.
 *
 * 这个类的实现者需要重写 getRootConfigClasses 这个抽象方法。用于指定 root 应用上下文的配置类。
 * 并且这个括号里边也备注了,所谓的 root 应用上下文,应该是非 web 相关的。啥意思呢,粗暴理解,就是 service | dao 这些东西放到 root 应用上下文。
 *
 * 这个类的实现者需要重写 getServletConfigClasses 这个抽象方法。用于指定 DispatcherServlet 的应用上下文的配置类。
 * 在这个配置类中配置的是跟 spring mvc 相关的配置信息。
 *
 * 对比这2个方法。我们可以看出。父子容器设定的一个出发点就是将web相关的东西和非web相关的东西隔离开。
 *
 * <p>Implementations are required to implement:
 * <ul>
 * <li>{@link #getRootConfigClasses()} -- for "root" application context (non-web
 * infrastructure) configuration.
 * <li>{@link #getServletConfigClasses()} -- for {@code DispatcherServlet}
 * application context (Spring MVC infrastructure) configuration.
 * </ul>
 *
 * 下面这段话意思是,如果不需要父子容器的话,可以将所有配置写到 getRootConfigClasses 指定的配置类中,
 * 让 getServletConfigClasses 返回 null。
 *
 * <p>If an application context hierarchy is not required, applications may
 * return all configuration via {@link #getRootConfigClasses()} and return
 * {@code null} from {@link #getServletConfigClasses()}.
 *
 * @author Arjen Poutsma
 * @author Chris Beams
 * @since 3.2
 */
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
		extends AbstractDispatcherServletInitializer {

	/**
	 * {@inheritDoc}
	 * <p>This implementation creates an {@link AnnotationConfigWebApplicationContext},
	 * providing it the annotated classes returned by {@link #getRootConfigClasses()}.
	 * Returns {@code null} if {@link #getRootConfigClasses()} returns {@code null}.
	 */
	@Override
	@Nullable
	protected WebApplicationContext createRootApplicationContext() {
	
        System.out.println("所谓创建根web应用上下文就是 new AnnotationConfigWebApplicationContext() ");
        
		Class<?>[] configClasses = getRootConfigClasses();
		if (!ObjectUtils.isEmpty(configClasses)) {
			AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
			context.register(configClasses);
			return context;
		}
		else {
			return null;
		}
	}

	/**
	 * {@inheritDoc}
	 * <p>This implementation creates an {@link AnnotationConfigWebApplicationContext},
	 * providing it the annotated classes returned by {@link #getServletConfigClasses()}.
	 */
	@Override
	protected WebApplicationContext createServletApplicationContext() {
	
        System.out.println("createServletApplicationContext ----> new AnnotationConfigWebApplicationContext() ");
        
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		Class<?>[] configClasses = getServletConfigClasses();
		if (!ObjectUtils.isEmpty(configClasses)) {
			context.register(configClasses);
		}
		return context;
	}

	/**
	 * Specify {@code @Configuration} and/or {@code @Component} classes for the
	 * {@linkplain #createRootApplicationContext() root application context}.
	 * @return the configuration for the root application context, or {@code null}
	 * if creation and registration of a root context is not desired
	 */
	@Nullable
	protected abstract Class<?>[] getRootConfigClasses();

	/**
	 * Specify {@code @Configuration} and/or {@code @Component} classes for the
	 * {@linkplain #createServletApplicationContext() Servlet application context}.
	 * @return the configuration for the Servlet application context, or
	 * {@code null} if all configuration is specified through root config classes.
	 */
	@Nullable
	protected abstract Class<?>[] getServletConfigClasses();

}

最后,AbstractAnnotationConfigDispatcherServletInitializer 这个抽象类的父类 AbstractDispatcherServletInitializer以及祖父 AbstractContextLoaderInitializer 都值得看看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2274005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaFx 21 项目Markdown 预览、编辑、新建、文件树、删除、重命名

项目文件结构 项目的源代码和资源文件存放在以下路径: 源代码: src/main/java/com/kong/markdown/ 包含多个 Java 文件,主要实现了应用的功能: App.java:主类,可能包含应用的启动逻辑。FileService.java:可能与文件操作相关的服务类。MainController.java:控制器类,可…

jenkins入门6 --拉取代码

Jenkins代码拉取 需要的插件&#xff0c;缺少的安装下 新建一个item,选择freestyle project 源码管理配置如下&#xff1a;需要添加git库地址&#xff0c;和登录git的用户密码 配置好后执行编译&#xff0c;成功后拉取的代码在工作空间里

数学建模入门——建模流程

摘要&#xff1a;本文介绍了数学建模的一般流程概述。 目录 一、前言 二、数据预处理 三、描述性统计分析 四、模型建立 五、模型评价 一、前言 本文将为想要入门数学建模的同学讲述数学建模的一般流程。但数学建模流程并非一成不变。虽有大致步骤&#xff0c;像分析问题、…

《机器学习》集成学习之随机森林

目录 一、集成学习 1、简介 2、集成学习的代表 3、XGBoost和随机森林的对比 相同点&#xff1a; 不同点&#xff1a; 二、Bagging之随机森林 1、简介 2、随机森林的核心思想 3、随机森林生成步骤 4、随机森林的优点 5、随机森林的缺点 三、随机森林的代码实现 1、…

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码 一、前言 官方文档关于屏幕录制的API和示例介绍获取简单和突兀。使用起来会让上手程度变高。所以特意开篇文章&#xff0c;讲解屏幕录制的使用。官方文档参见&#xff1a;使用AVScreenCaptureRecorder录屏写文件(ArkTS) 二…

CSS——22.静态伪类(伪类是选择不同元素状态)

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>静态伪类</title> </head><body><a href"#">我爱学习</a></body> </html>单击链接前的样式 左键单击&#xff08;且…

JavaWeb开发(六)XML介绍

1. XML介绍 1.1. 什么是XML &#xff08;1&#xff09;XML 指可扩展标记语言(EXtensible Markup Language)XML 是一种很像HTML的标记语言。   &#xff08;2&#xff09;XML 的设计宗旨是传输数据(目前主要是作为配置文件)&#xff0c;而不是显示数据。   &#xff08;3&a…

攻防世界 bug

发现有Register界面&#xff0c;先去注册 登录以后发现以下界面&#xff0c;点击Manage显示you are not admin&#xff0c;并且在注册界面用admin为注册名时显示用户名已存在。初步推测是设法改变admin的密码取得权限。 在主界面一通操作并没有什么发现&#xff0c;去findpw…

maven依赖的配置和排除依赖

1.依赖的配置 1.1位置&#xff1a;写在<properties></properties>标签之下&#xff0c;<project></project>里。 1.2语法固定的格式 <dependencies><dependency></dependency></dependencies> 1.3在 <dependency><…

transformer深度学习实战CCTSDB中国交通标志识别

本文采用RT-DETR作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。RT-DETR以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对CCTSDB交通标志数据集进行训练和优化&#xff0c;该数据集包含丰富的CCTSDB交…

Elastic-Job相关

文档参考视频&#xff1a;09_SpringBoot案例演示_哔哩哔哩_bilibili 一、Elastic-Job介绍 Elastic-Job 是一个轻量级、分布式的任务调度框架&#xff0c;旨在解决分布式环境下的定时任务调度问题。 1.1. Elastic-Job 的核心组件 Elastic-Job 是由多个核心组件构成的&#x…

esp32开发笔记之一:esp32开发环境搭建vscode+ubuntu

最近想用esp32做一个物联网项目&#xff0c;踩坑N个终于有点心得&#xff0c;写下来避免和我一样的小白踩无谓的坑。 写在前面&#xff1a; 第一&#xff0c;大家一定要用linux系统作为编译工具&#xff0c;速度上是windows无法比的&#xff0c;不要因为不熟悉linux而选择win…

(七)人工智能进阶之人脸识别:从刷脸支付到智能安防的奥秘,小白都可以入手的MTCNN+Arcface网络

零、开篇趣谈 还记得第一次用支付宝"刷脸"时的新奇感吗&#xff1f;或者被抖音的人脸特效逗乐的瞬间&#xff1f;这些有趣的应用背后&#xff0c;其实藏着一个精妙的AI世界。今天&#xff0c;就让我们开启一段奇妙的人脸识别技术探索之旅吧&#xff01; 一、人脸识…

攻防世界 ics-07

点击之后发现有个项目管理能进&#xff0c;点进去&#xff0c;点击看到源码&#xff0c;如下三段 <?php session_start(); if (!isset($_GET[page])) { show_source(__FILE__); die(); } if (isset($_GET[page]) && $_GET[page] ! index.php) { include(flag.php);…

使用 SQL 和表格数据进行问答和 RAG(6)—将指定目录下的 CSV 或 Excel 文件导入 SQLite 数据库

将指定目录下的 CSV 或 Excel 文件导入 SQLite 数据库。以下是详细代码逻辑&#xff1a; 1. 类结构 该类包含三个主要方法&#xff1a; _prepare_db&#xff1a;负责将文件夹中的 CSV 和 XLSX 文件转换为 SQL 表。_validate_db&#xff1a;用于验证 SQL 数据库中创建的表是否…

各品牌大语言模型汇总

2024年大语言模型快速发展&#xff0c;应用广泛。面对众多选择&#xff0c;我们整理了一份各大语言模型汇总表格&#xff0c;提供清晰参考&#xff0c;助您了解各模型参数&#xff08;截止日期为2025年1月8日&#xff09;。 高通智匠AI支持在Windows/Android/MAC等平台上使用 …

xtu oj 1614 数字(加强版)

输出格式# 每行输出一个样例的结果&#xff0c;为一个整数。 样例输入# 3 1 10 101 样例输出# 1 2 3 解题思路&#xff1a;这个题不要想复杂了&#xff0c;很容易超时。 首先需要注意的点&#xff0c;n<10的10000次方&#xff0c;用int或者long long都会爆&#xff0c;所…

【25考研】川大计算机复试情况,重点是啥?怎么准备?

24年进入复试的同学中&#xff0c;有10位同学的复试成绩为0分。具体是个人原因还是校方原因&#xff0c;还尚不明确。但是C哥提醒&#xff0c;一定要认真复习&#xff01;复试完后不要跟任何人讨论有关复试的题目及细节&#xff01; 一、复试内容 四川大学复试内容较多&#xf…

AR 眼镜之-拍照/录像动效切换-实现方案

目录 &#x1f4c2; 前言 AR 眼镜系统版本 拍照/录像动效切换 1. &#x1f531; 技术方案 1.1 技术方案概述 1.2 实现方案 1&#xff09;第一阶段动效 2&#xff09;第二阶段动效 2. &#x1f4a0; 默认代码配置 2.1 XML 初始布局 2.2 监听滑动对 View 改变 3. ⚛️…

STM32-笔记39-SPI-W25Q128

一、什么是SPI&#xff1f; SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且 在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为…