阅读文章前提:了解springmvc的基本流程
一、SpringMvc的特点
基于原生的Servlet,通过了功能强大的前端控制器DispatcherServlet,对请求和响应进行统一处理
二、零配置方式开发mvc项目
2.1. 按照上一章节的方式创建项目,接着导入依赖
<properties>
<spring.version>6.0.6</spring.version>
<servlet.api>9.1.0</servlet.api>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- springioc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web相关依赖 -->
<!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
<!--
在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
Jakarta EE 提供的相应类库和命名空间。错误信息 “‘org.springframework.web.servlet.DispatcherServlet’
is not assignable to ‘javax.servlet.Servlet,jakarta.servlet.Servlet’” 表明你使用了旧版本的
Servlet API,没有更新到 Jakarta EE 规范。
-->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>${servlet.api}</version>
<scope>provided</scope>
</dependency>
<!-- springwebmvc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
2.2. 创建配置类代替web.xml
//TODO: SpringMVC提供的接口,是替代web.xml的方案,更方便实现完全注解方式ssm处理!
//TODO: Springmvc框架会自动检查当前类的实现类,会自动加载 getRootConfigClasses / getServletConfigClasses 提供的配置类
//TODO: getServletMappings 返回的地址 设置DispatherServlet对应处理的地址
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 指定service / mapper层的配置类
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
/**
* 指定springmvc的配置类
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { SpringMvcConfig.class };
}
/**
* 设置dispatcherServlet的处理路径!
* 一般情况下为 / 代表处理所有请求!
*/
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
2.3. 创建控制器
@Controller
public class HelloController {
//handlers
/**
* handler就是controller内部的具体方法
* @RequestMapping("/springmvc/hello") 就是用来向handlerMapping中注册的方法注解!
* @ResponseBody 代表向浏览器直接返回数据!
*/
@RequestMapping("/springmvc/hello")
@ResponseBody//直接返回字符串给前端,不找视图解析器。
public String hello(){
System.out.println("HelloController.hello");
return "hello springmvc!!";
}
}
在Spring MVC框架中,@ResponseBody 注解用于指示控制器方法的返回值应该直接写入HTTP响应体中,而不是通过视图解析器(如JSP、Thymeleaf等)来渲染。
这意味着,当你在处理RESTful API接口或者返回JSON、XML等数据格式时,通常会用到这个注解。
2.4.核心控制器已配置,接着配置springmvc的组件(处理器映射器,处理器适配器)
//TODO: SpringMVC对应组件的配置类 [声明SpringMVC需要的组件信息]
//TODO: 导入handlerMapping和handlerAdapter的三种方式
//1.自动导入handlerMapping和handlerAdapter [推荐]
//2.可以不添加,springmvc会检查是否配置handlerMapping和handlerAdapter,没有配置默认加载
//3.使用@Bean方式配置handlerMapper和handlerAdapter
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
@Bean
public HandlerMapping handlerMapping(){
return new RequestMappingHandlerMapping();
}
@Bean
public HandlerAdapter handlerAdapter(){
return new RequestMappingHandlerAdapter();
}
}
2.5. 项目结构如下:
三、为啥实现AbstractAnnotationConfigDispatcherServletInitializer就可以实现servlet配置和创建ioc容器呢?
3.1.先来了解WebApplicationInitializer接口
在main方法中实现接口中的方法onStartup(),可知,在服务启动时,会自动调用该接口中的方法。
我们从的配置类继承的接口进入,一直往父类中ctrl+鼠标右键进入,最终发现了onstartup这个方法。webApplicationInitializer接口的作用是做初始化工作,去替代web.xml。
到达顶层接口WebApplicationInitializer
可见源码中的注解提示,可用xml配置文件当时或者代码配置。
❗在进行下面的讲解前,先再看一眼MyWebAppInitializer重写的三个方法❗
3.2. MyWebAppInitializer类中的getServletConfigClasses作用
- 我们先关注创建容器的方法(controller层和springmvc的ioc容器)createServletApplicationContext
- 在注册前端控制器方法中,我们找到web容器的方法createServletApplicationContext
- 在该方法中,调用的是我们新建的MyWebAppInitializer类中的getServletConfigClasses方法,返回的是配置类,配置类放到了ioc容器中加载了。注意,这里只是加载springmvc和controller层的组件
3.3.MyWebAppInitializer类中的getServletMappings方法作用
- DispatcherServlet的配置
- 设置springmvc中DispatcherServlet的地址,也就是我们MyWebAppInitializer类中的getServletMappings方法
3.4. MyWebAppInitializer类中的getRootConfigClasses方法我们还没有讲解,该方法有什么作用呢?
该方法是 指定service / mapper层ioc容器的配置类,后续有讲解
四、 疑问:springmvc有几个容器?
4.1.在Spring MVC框架中,尤其是在非Spring Boot项目中,通常存在两个主要的容器概念:
- 第一个,根容器(Root ApplicationContext):
这是Spring的核心ApplicationContext容器,它负责加载并管理整个应用中的所有bean,包括那些与Web层无关的服务、DAO、组件等。这个容器通常是由DispatcherServlet初始化之前创建的。
- 第二个,Spring MVC子容器(WebApplicationContext):
当使用Spring MVC时,每个DispatcherServlet可以拥有一个独立的WebApplicationContext,这个子容器继承自根容器,并且专门用来管理与Web相关的bean,如@Controller、@Service、@Repository注解标记的类,以及HandlerMappings、ViewResolvers等Spring MVC组件。
在Spring MVC中,每个Servlet可以有自己专属的上下文配置文件,从而实现更细粒度的控制和隔离。 这种设计允许Web相关组件的配置与其他服务或基础设施组件相分离,有助于提高代码的可维护性和复用性。在Spring Boot项目中,尽管仍然可以配置多个上下文,但默认情况下Spring Boot会简化这些配置,并倾向于使用一个单一的应用上下文来管理所有的bean。
4.2. 容器之间的关系
- 所有容器都在Tomcat这个大容器下运行,所以tomcat是最大的;
- servletContext我们在javaweb教学当中就知道,可以为所有的servlet提供配置参数,所以是最大的域对象;
- 其次,就是我们重写方法中创建的两个容器;下篇跳转链接至:
springmvc最详细的开发流程(下)-CSDN博客