spring mvc源码学习笔记之四
- 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-40</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>
- src/main/webapp/WEB-INF/web.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/qs-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- src/main/webapp/WEB-INF/app-context.xml 的内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="peopleService" class="com.qs.demo.root.PeopleService"/>
</beans>
- src/main/webapp/WEB-INF/qs-servlet.xml 的内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.qs.demo.sub"/>
</beans>
- com.qs.demo.root.PeopleService 的内容如下
package com.qs.demo.root;
/**
* @author qs
* @date 2023/07/05
*/
public class PeopleService {
public void a() {
System.out.println("==== a");
}
}
- com.qs.demo.sub.PeopleController 的内容如下
package com.qs.demo.sub;
import com.qs.demo.root.PeopleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author qs
* @date 2023/07/05
*/
@RestController
public class PeopleController {
@Autowired private ApplicationContext applicationContext;
@Autowired
@Qualifier("peopleService")
private PeopleService peopleService;
@GetMapping("/01")
public String test01() {
System.out.println("demo40 ======================= " + applicationContext.getClass().getName());
return "demo40 01";
}
@GetMapping("/02")
public String test02() {
peopleService.a();
return "demo40 02";
}
}
以上就是全部代码
写这个例子主要是为了看父子容器这个事儿。
上面的例子可以分为2部分看,一部分是父容器相关的,一部分是子容器相关的。
先从 web.xml 来看
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
上面这段是配置父容器的。首先就是 ContextLoaderListener 这个类。它非常重要。准确说是它的父类 ContextLoader 非常重要。
因为 ContextLoaderListener 的很多事情都是在父类 ContextLoader 中完成的。
而名为 contextConfigLocation 的 context-param 是用来指定父容器要用的配置文件的。不指定的话,默认是用 /WEB-INF/applicationContext.xml 这个文件。
关于 ContextLoaderListener 和它的父类 ContextLoader 这2个类,我们会在其他文章中介绍。
接着看父容器的配置文件 /WEB-INF/app-context.xml。我们将 service 层的 bean 配置在父容器中。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="peopleService" class="com.qs.demo.root.PeopleService"/>
</beans>
多说一嘴,spring 设计父子容器的一个目的就是想让我们把 service dao 层配置放到父容器,而跟视图层相关的配置也就是 spring mvc 中的控制器、视图解析器、处理器适配器、处理器映射器等放到子容器。扯远了,回来继续看子容器,也就是下面 web.xml 中下面这部分
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/qs-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在子容器的配置文件 /WEB-INF/qs-servlet.xml 我们定义了组件扫描范围
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.qs.demo.sub"/>
</beans>
而我们的 controller 就在这个 com.qs.demo.sub 包下。