SpringBoot 扩展 SpringMVC 核心用法与知识点全解析

前言

SpringBoot 对 SpringMVC 做了大量自动化配置,让开发实现了 "开箱即用",但实际业务开发中,默认配置往往无法满足定制化需求。本文将从核心知识点 + 实操案例 出发,详解如何通过WebMvcConfigurer接口实现 SpringMVC 的四大核心扩展,同时梳理每个扩展的核心原理与关键注意事项,内容可直接复用到实际项目,适配新手学习与开发实战。

一、SpringMVC 扩展核心基础

核心知识点

WebMvcConfigurer是 SpringBoot 扩展 SpringMVC 的核心入口接口 ,提供多个默认空实现的扩展方法,按需实现即可完成定制化配置,不会破坏 SpringBoot 原有自动配置 ;自定义扩展配置类必须添加@Configuration注解,且需放在启动类同包 / 子包下,确保被 Spring 扫描加载。

基础配置类模板

所有扩展功能均基于此配置类实现,后续只需在类中重写对应扩展方法即可:

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * SpringMVC扩展核心配置类
 * 注解+接口缺一不可,是所有扩展的基础载体
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    // 各类扩展方法均写在此处
}

二、扩展 1:视图控制器配置(请求路径转发)

核心知识点

实现addViewControllers方法,无需编写空 Controller ,直接通过配置完成请求路径到页面的转发,简化简单路由开发;需严格区分路径规则:写forward:/xxx.html指向static目录纯静态页,直接写视图名指向templates目录模板页。

实操案例

实现访问/tx自动转发到static目录下的success.html静态页:

java 复制代码
/**
 * 视图控制器:请求路径转发配置
 * 核心:forward:/ 前缀指定静态资源路径,无前缀则指向模板页
 */
@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/tx").setViewName("forward:/success.html");
}

关键注意

若需转发到templates目录的动态模板页,直接写视图名即可,如registry.addView

Controller("/index").setViewName("index")(对应templates/index.html)。

三、扩展 2:自定义日期格式化器注册

核心知识点

实现addFormatters方法,向FormatterRegistry注册自定义Formatter<Date>统一完成前后端日期类型的自动转换 :前端传入的日期字符串自动解析为后端Date类型,后端Date类型自动格式化为指定规则的字符串返回前端,替代手动解析,统一项目日期处理规范。

实操案例

实现yyyy-MM-dd格式的字符串与Date类型互转,适配前后端日期参数传递:

java 复制代码
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

@Override
public void addFormatters(FormatterRegistry registry) {
    registry.addFormatter(new Formatter<Date>() {
        // 响应前端:Date → 字符串(格式化)
        @Override
        public String print(Date date, Locale locale) {
            return new SimpleDateFormat("yyyy-MM-dd").format(date);
        }
        // 接收前端:字符串 → Date(解析)
        @Override
        public Date parse(String s, Locale locale) throws ParseException {
            return new SimpleDateFormat("yyyy-MM-dd").parse(s);
        }
    });
}

测试验证

编写简单 Controller,可直接接收前端yyyy-MM-dd格式的日期参数,无需手动处理:

java 复制代码
@RestController
public class TestController {
    @GetMapping("/date")
    public String testDate(Date date) {
        return "接收并格式化后的日期:" + date;
    }
}

四、扩展 3:FastJson 消息转换器扩展(替换 Jackson)

核心知识点

实现configureMessageConverters方法,通过FastJsonHttpMessageConverter替换 SpringMVC 默认的 Jackson JSON 处理器 ;可全局配置 JSON 格式化规则(如美化输出、全局日期格式),也可通过实体类@JSONField注解实现字段级自定义 JSON 规则,满足项目个性化的 JSON 序列化 / 反序列化需求。

实操案例

步骤 1:引入 FastJson 依赖
XML 复制代码
<!-- pom.xml中添加依赖,指定稳定版本 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
步骤 2:配置 FastJson 消息转换器
java 复制代码
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import java.util.List;

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    // 1. 创建FastJson转换器实例
    FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
    // 2. 配置FastJson全局规则
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); // 美化输出
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); // 全局日期格式化
    fastConverter.setFastJsonConfig(fastJsonConfig);
    // 3. 添加到转换器列表,替换默认Jackson
    converters.add(fastConverter);
}
步骤 3:实体类字段级自定义(可选)
java 复制代码
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;

public class User {
    private String username;
    private Integer age;
    // 单独指定该字段的日期格式,优先级高于全局配置
    @JSONField(format = "yyyy-MM-dd")
    private Date createTime;
    
    // 省略get/set方法
}

测试验证

返回 User 对象时,将以 FastJson 规则格式化 JSON,字段级配置会覆盖全局配置:

java 复制代码
@GetMapping("/user")
public User testUser() {
    User user = new User();
    user.setUsername("张三");
    user.setAge(20);
    user.setCreateTime(new Date());
    return user;
}

五、扩展 4:自定义拦截器开发与注册

核心知识点

  1. 自定义类实现HandlerInterceptor接口,重写三个核心方法实现拦截逻辑:preHandle(请求处理前执行,返回 true 放行)、postHandle(请求处理后、视图渲染前执行)、afterCompletion(视图渲染后执行,无论是否异常必执行);
  2. 实现addInterceptors方法注册自定义拦截器,通过addPathPatterns配置拦截路径excludePathPatterns配置排除路径,实现精准的请求拦截管控,常用于登录校验、接口日志、权限控制等场景。

实操案例

步骤 1:编写自定义拦截器
java 复制代码
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器:实现请求前置/后置/最终处理
 */
public class MyInterceptor implements HandlerInterceptor {
    // 请求前置拦截:核心拦截逻辑(如登录校验)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置拦截:请求路径=" + request.getRequestURI());
        return true; // 返回true放行,false直接拦截
    }
    // 请求后置处理:视图渲染前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
        System.out.println("后置拦截");
    }
    // 最终处理:视图渲染后执行,可做资源释放
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("最终拦截");
    }
}
步骤 2:注册拦截器并配置规则
java 复制代码
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor())
            .addPathPatterns("/**") // 拦截所有请求
            .excludePathPatterns("/**/*.html", "/**/*.css", "/**/*.js"); // 排除静态资源
}

六、扩展常见问题与解决方案

问题:拦截器重复触发(日志 / 逻辑执行多次)

核心原因

请求转发场景下,转发源路径(如/tx)和目标路径(如/success.html)会触发两次请求,拦截器会分别拦截两次请求,导致日志或业务逻辑重复执行。

解决方案(两种任选)
  1. 精准排除路径 :在excludePathPatterns中排除转发目标路径、所有静态资源,从根源避免拦截重复请求:

    java 复制代码
    .excludePathPatterns("/success.html", "/**/*.html", "/**/*.css", "/**/*.js");
  2. 判断内部转发请求 :在preHandle方法中通过请求属性判断是否为内部转发请求,若是则直接放行不处理:

    java 复制代码
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判定内部转发请求,直接放行
        if (request.getAttribute("javax.servlet.forward.request_uri") != null) {
            return true;
        }
        System.out.println("前置拦截:请求路径=" + request.getRequestURI());
        return true;
    }

七、全文核心知识点总结

  1. SpringMVC 扩展的核心入口是WebMvcConfigurer接口,配合@Configuration注解实现无侵入式扩展,不破坏自动配置;
  2. 视图控制器通过addViewControllers实现无 Controller 的路径转发,需区分statictemplates目录的路径规则;
  3. 自定义日期格式化器通过addFormatters注册,实现前后端日期类型的自动解析与格式化,统一项目日期处理;
  4. 实现configureMessageConverters可替换 FastJson 为 JSON 处理器,支持全局 + 字段级的 JSON 规则配置;
  5. 自定义拦截器需实现HandlerInterceptor并通过addInterceptors注册,配合拦截 / 排除规则实现精准请求管控;
  6. 转发场景下拦截器重复触发的核心解决思路是排除重复路径跳过内部转发请求

后记

本文讲解的WebMvcConfigurer接口扩展方式,是 SpringBoot 开发中最常用、最优雅的 SpringMVC 扩展方案,既保留了 SpringBoot 自动化配置的便捷性,又能完美适配业务的定制化需求。掌握这些扩展方法,能大幅提升日常开发效率,解决实际项目中的各类个性化配置问题。后续可在此基础上进一步学习跨域配置、自定义参数解析器等高级扩展场景,完善 SpringMVC 的定制化能力。

相关推荐
木辰風7 小时前
PLSQL自定义自动替换(AutoReplace)
java·数据库·sql
heartbeat..7 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
7 小时前
java关于内部类
java·开发语言
好好沉淀7 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
gusijin7 小时前
解决idea启动报错java: OutOfMemoryError: insufficient memory
java·ide·intellij-idea
To Be Clean Coder7 小时前
【Spring源码】createBean如何寻找构造器(二)——单参数构造器的场景
java·后端·spring
吨~吨~吨~8 小时前
解决 IntelliJ IDEA 运行时“命令行过长”问题:使用 JAR
java·ide·intellij-idea
你才是臭弟弟8 小时前
SpringBoot 集成MinIo(根据上传文件.后缀自动归类)
java·spring boot·后端
短剑重铸之日8 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式
码农水水8 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展