Salmon的全栈知识 Salmon的全栈知识
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • SpringCloud Gateway
  • Apollo
  • Eureka
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • SpringCloud Gateway
  • Apollo
  • Eureka
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Spring框架

    • 传统Javaweb开发的困惑
    • IoC、DI和AOP思想提出
    • Spring框架的诞生
    • 基于xml的Spring应用
    • 基于注解的Spring应用
    • AOP 简介
    • 基于xml配置的AOP
    • 基于注解配置的AOP
    • 基于AOP的声明式事务控制
  • SpringMVC框架

    • Spring整合web环境
    • web层MVC框架思想与设计思路
    • SpringMVC简介
    • SpringMVC的请求处理
    • SpringMVC的响应处理
    • SpringMVC的拦截器
    • SpringMVC的全注解开发
      • 1、spring-mvc.xml 中组件转化为注解形式
      • 2、DispatcherServlet加载核心配置类
      • 3、消除web.xml
    • SpringMVC的组件原理剖析
    • SpringMVC的异常处理机制
  • 《Spring生态》笔记
  • SpringMVC框架
Salmon
2025-07-23
目录

SpringMVC的全注解开发

# 1、spring-mvc.xml 中组件转化为注解形式

跟之前全注解开发思路一致, xml配置文件使用核心配置类替代,xml中的标签使用对应的注解替代

<!-- 组件扫描 web 层 -->
<context:component-scan base-package="com.itheima.controller"/>

<!-- 注解驱动,支持 @RequestMapping 等注解 -->
<mvc:annotation-driven/>

<!-- 配置文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

<!-- 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*"/>
        <bean class="com.itheima.interceptor.MyInterceptor01"/>
    </mvc:interceptor>
</mvc:interceptors>

<!-- 配置 DefaultServletHttpRequestHandler,处理静态资源 -->
<mvc:default-servlet-handler/>
  • 组件扫描,可以通过@ComponentScan注解完成;

  • 文件上传解析器multipartResolver可以通过非自定义Bean的注解配置方式,即@Bean注解完成

@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMVCConfig {

    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        // 设置默认编码
        multipartResolver.setDefaultEncoding("UTF-8");
        // 设置最大上传总大小(3MB)
        multipartResolver.setMaxUploadSize(3145728);
        // 设置单个文件最大上传大小(1MB)
        multipartResolver.setMaxUploadSizePerFile(1048576);
        // 设置内存中缓存的最大大小(1MB)
        multipartResolver.setMaxInMemorySize(1048576);
        return multipartResolver;
    }
}

<mvc:default-servlet-handler /> 和 <mvc:interceptor > 怎么办呢?SpringMVC 提供了一个注解叫做@EnableWebMvc,我们看一下源码,内部通过@Import 导入了DelegatingWebMvcConfiguration类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {}
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

    // 用于保存所有注入的 WebMvcConfigurer 实例
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

    /**
     * 从 Spring 容器中自动注入所有 WebMvcConfigurer 类型的 Bean
     * @param configurers 注入的 WebMvcConfigurer 列表
     */
    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }
    }

    // 省略其他代码
}

WebMvcConfigurer类型的Bean会被注入进来,然后被自动调用,所以可以实现WebMvcConfigurer接口,完成一些解析器、默认Servlet等的指定,WebMvcConfigurer接口定义如下:

public interface WebMvcConfigurer {

    /** 配置默认的 Servlet 处理器,用于静态资源处理 */
    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { }

    /** 添加拦截器 */
    default void addInterceptors(InterceptorRegistry registry) { }

    /** 添加静态资源处理器,比如映射 /static/** 路径 */
    default void addResourceHandlers(ResourceHandlerRegistry registry) { }

    /** 添加视图控制器,直接实现请求到视图的映射,无需写 Controller */
    default void addViewControllers(ViewControllerRegistry registry) { }

    /** 配置视图解析器 */
    default void configureViewResolvers(ViewResolverRegistry registry) { }

    /** 添加自定义的方法参数解析器 */
    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { }

    // ... 省略其他代码 ...
}

创建MyWebMvcConfigurer实现WebMvcConfigurer接口,实现addInterceptors 和 configureDefaultServletHandling方法

@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        // 开启 DefaultServlet 处理静态资源,等价于 <mvc:default-servlet-handler/>
        configurer.enable();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器,拦截所有一级路径请求(/xxx)
        // 多个拦截器执行顺序按注册顺序决定
        registry.addInterceptor(new MyInterceptor01()).addPathPatterns("/*");
    }
}

最后,在SpringMVC核心配置类上添加@EnableWebMvc注解

@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMVCConfig {

    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        // 设置默认编码
        multipartResolver.setDefaultEncoding("UTF-8");
        // 设置最大上传总大小(3MB)
        multipartResolver.setMaxUploadSize(3145728);
        // 设置单个文件最大上传大小(1MB)
        multipartResolver.setMaxUploadSizePerFile(1048576);
        // 设置内存缓存最大大小(1MB)
        multipartResolver.setMaxInMemorySize(1048576);
        return multipartResolver;
    }
}

# 2、DispatcherServlet加载核心配置类

DispatcherServlet在进行SpringMVC配置文件加载时,使用的是以下方式:

<!-- 配置 Spring MVC 前端控制器 -->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
    <!-- 指定 Spring MVC 配置文件位置 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    
    <!-- 服务器启动时立即创建 DispatcherServlet -->
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

现在是使用SpringMVCConfig核心配置类提替代的spring-mvc.xml,怎么加载呢?参照Spring的ContextLoaderListener加载核心配置类的做法,定义了一个AnnotationConfigWebApplicationContext,通过代码注册核心配置类

public class MyAnnotationConfigWebApplicationContext extends AnnotationConfigWebApplicationContext {

    public MyAnnotationConfigWebApplicationContext() {
        // 注册核心配置类 SpringMVCConfig,加载 Spring MVC 配置
        super.register(SpringMVCConfig.class);
    }
}
<!--指定springMVC的applicationContext全限定名 -->
<init-param>
   <param-name>contextClass</param-name>
   <param-value>com.itheima.config.MyAnnotationConfigWebApplicationContext</param-value>
</init-param>

# 3、消除web.xml

目前,几乎消除了配置文件,但是web工程的入口还是使用的web.xml进行配置的,如下

<!-- 配置 Spring MVC 前端控制器 -->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
    <!-- 指定 Spring MVC 的 ApplicationContext 全限定类名 -->
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>com.itheima.config.MyAnnotationConfigWebApplicationContext</param-value>
    </init-param>
    
    <!-- 服务器启动时创建 DispatcherServlet -->
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • Servlet3.0环境中,web容器提供了javax.servlet.ServletContainerInitializer接口,实现了该接口后,在对应的类加载路径的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作;

  • 基于这个特性,Spring就定义了一个SpringServletContainerInitializer实现了ServletContainerInitializer接口;

  • 而SpringServletContainerInitializer会查找实现了WebApplicationInitializer的类,Spring又提供了一个WebApplicationInitializer的基础实现类AbstractAnnotationConfigDispatcherServletInitializer,当我们编写类继承AbstractAnnotationConfigDispatcherServletInitializer时,容器就会自动发现我们自己的类,在该类中我们就可以配置Spring和SpringMVC的入口了。

按照下面的配置就可以完全省略web.xml

public class MyAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    /**
     * 返回带有 @Configuration 注解的类,用来配置 ContextLoaderListener(Spring 容器)
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        System.out.println("加载核心配置类创建 ContextLoaderListener");
        return new Class[]{ApplicationContextConfig.class};
    }

    /**
     * 返回带有 @Configuration 注解的类,用来配置 DispatcherServlet(Spring MVC 容器)
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        System.out.println("加载核心配置类创建 DispatcherServlet");
        return new Class[]{SpringMVCConfig.class};
    }

    /**
     * 将一个或多个路径映射到 DispatcherServlet 上,通常是 "/"
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
上次更新: 2025/07/28, 17:18:00
SpringMVC的拦截器
SpringMVC的组件原理剖析

← SpringMVC的拦截器 SpringMVC的组件原理剖析→

Theme by Vdoing | Copyright © 2022-2025 Salmon's Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式