Springboot整合SpringMVC --从0到1

摘要:本文不仅详细展示了Springboot整合SpringbootMVC中组件的几种方式,还把Springmvc中易混淆的点和难点复习,在理解整合的过程中,自己也能达到整合各个组件的套路模版

一、WebMvcConfigurer的直接应用

要想整合SpringMVC ,关键就是理解WebMvcConfigurer。WebMvcConfigurer是一个接口,我们的WebMvcAutoConfiguration(自动装配类)中的WebMvcAutoConfigurationAdapter就实现了这个类,此类用于自定义 Spring MVC 的核心行为,无需替换默认的 Spring MVC 组件,只需重写对应方法即可实现定制化,这也是 Spring Boot 整合 Spring MVC 的推荐配置方式,不会破坏自动配置的特性。

(1)addInterceptors 注册拦截器(最常用)

步骤一、定义一个类实现HandlerInterceptor接口

java 复制代码
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 请求到达controller之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        if((token != null && token.equals( "")) || token == null ){
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("请先登录");
            return false;
        }
        return true;
    }

    /**
     * 响应完全完成,报错渲染视图等等
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("响应完成");
    }
    /**
     * 请求处理之后,视图渲染之前
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        System.out.println("请求处理之后,视图渲染之前执行");
    }
}

步骤二,配置类实现WebMvcConfigurer接口,并实现里面的addInterceptors方法。

java 复制代码
@Configuration
public class SpringMvcConfig  implements WebMvcConfigurer {


     /**
     * 注册登录拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login/**","/index/**","/error/**","/*.png","/mvc/hello");

    }

}

(2)配置静态资源映射

直接编写配置类,实现addResourceHandlers接口

java 复制代码
@Configuration
public class SpringMvcConfig  implements WebMvcConfigurer {
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 配置静态资源映射规则
        // 第一个参数:前端访问的URL路径前缀(必须以 /** 结尾)
        // 第二个参数:静态资源在项目中的实际存储路径(classpath: 表示项目资源目录 src/main/resources/)
        registry.addResourceHandler("/img/**")
                .addResourceLocations("classpath:/images/");
        
        registry.addResourceHandler("/js/**")
                .addResourceLocations("classpath:/static/js/");
        
        registry.addResourceHandler("/css/**")
                .addResourceLocations("classpath:/static/css/");
        
        // 若需要访问本地磁盘的静态资源(如 D:/uploads/ 下的图片),使用 file: 前缀
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("file:D:/uploads/");
    }
}

(3)配置跨域请求,实现addCorsMappings接口

java 复制代码
  @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**") // 对 /api/ 开头的所有接口配置跨域
                .allowedOriginPatterns("*") // 允许所有来源(生产环境建议指定具体域名,如 "http://localhost:8081")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP请求方法
                .allowCredentials(true) // 是否允许携带Cookie(前后端认证时需要)
                .maxAge(3600) // 跨域请求的有效期(秒),默认30分钟
                .allowedHeaders("*"); // 允许所有请求头(如 Token、Content-Type 等)
    }

(4)简化视图跳转,实现addViewControllers

java 复制代码
 @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/")
                .setViewName("forward:index.html");

        registry.addViewController("/login")
                .setViewName("loginView");

        registry.addViewController("/manager")
                .setViewName("error/404");

    }

(5)配置内容协商,支持返回数据为JSON,XML,YML形式

步骤一,开启 请求参数指定返回结果 配置文件写入

java 复制代码
  mvc:
    contentnegotiation:
      favor-parameter: true

写了这个方法以后,在前段给后端传参数时,拼接format=yml或者yaml或者json或者xml,然后返回指定的内容。

或者通过指定Accept,包括application/yaml 或者application/yml或者application/json,application/xml形式

步骤二、

java 复制代码
 /**
     * 配置内容协商
     * @param
     */
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // 1. 定义媒体类型映射:key 是参数值,value 是对应的 HTTP 媒体类型
        Map<String, MediaType> mediaTypeMap = new HashMap<>();
        mediaTypeMap.put("json", MediaType.APPLICATION_JSON);
        mediaTypeMap.put("xml", MediaType.APPLICATION_XML);
        mediaTypeMap.put("yaml", MediaType.parseMediaType("application/yaml")); // 新增 YAML 映射
        mediaTypeMap.put("yml", MediaType.parseMediaType("application/yml")); // 兼容 yml 后缀参数

        // 2. 配置内容协商规则
        configurer.favorParameter(true) // 启用请求参数协商
                .parameterName("format") // 请求参数名(?format=yaml)
                .mediaTypes(mediaTypeMap) // 加载所有媒体类型映射
                .ignoreAcceptHeader(false) // 不忽略 Accept 头,支持混合协商(参数优先级 > 请求头)
                .defaultContentType(MediaType.APPLICATION_JSON); // 默认返回 JSON
    }

(6)格式化器 ,实现addFormatters接口

专门处理「字符串和 Java 类型」的互转,支持注解配置(如@DateTimeFormat),更适合前端传递的字符串参数

configureMessageConverters()的区别

  • addFormatters():主要处理请求参数(URL 参数、表单参数)的类型转换 / 格式化,聚焦于「字符串与 Java 类型」的绑定。
  • configureMessageConverters():主要处理JSON 数据(请求体、响应体)的转换 / 格式化,聚焦于「Java 对象与 JSON 字符串」的序列化 / 反序列化。
  • 简单区分:URL 参数用addFormatters(),JSON 参数用configureMessageConverters()

二、springboot配置过滤器与监听器

过滤器与监听器不属于springMVC,属于JavaEE,本文在这里说即为了帮大家区分,同时扩展。

(1)过滤器

2.1.1 来源

来自Servlet 规范,是 Web 容器(Tomcat)级别的拦截,作用于所有请求(包括静态资源、Servlet 请求等),早于 Spring MVC 的处理流程。

2.1.2 核心功能

核心是 「对请求 / 响应进行统一的预处理和后处理」,具备拦截请求的能力,但侧重点是「统一处理」,不关注请求最终的处理器(Controller)。

  1. 预处理请求 :在请求到达DispatcherServlet之前执行,比如:编码格式统一设置(解决中文乱码)、请求参数过滤(防 XSS 注入)、用户登录状态校验(未登录拦截跳转到登录页)、记录请求日志。
  2. 后处理响应:在 Controller 处理完成、响应返回给客户端之前执行,比如:统一添加响应头、对响应数据进行加密 / 格式化、清理资源。
  3. 链式调用:支持多个 Filter 组成过滤器链,按配置顺序依次执行(先配置的先执行预处理,后执行后处理,类似 "先进后出")。
  4. 拦截范围广 :能拦截所有进入 Web 应用的请求,包括@Controller接口、静态资源(JS、CSS、图片)、JSP 等,只要是 Tomcat 接收的请求,都会经过 Filter。
2.2.3 配置过滤器

步骤 1:自定义 Filter(无需添加@WebFilter注解)

java 复制代码
import jakarta.servlet.*;
import java.io.IOException;

public class MyCustomFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyCustomFilter 初始化完成");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("MyCustomFilter 执行预处理逻辑");
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        
        chain.doFilter(request, response); // 放行
        
        System.out.println("MyCustomFilter 执行后处理逻辑");
    }

    @Override
    public void destroy() {
        System.out.println("MyCustomFilter 销毁完成");
    }
}

步骤 2:创建配置类,注册 Filter 到 Spring 容器

java 复制代码
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // 标记为Spring配置类
public class FilterConfig {

    // 注册自定义Filter
    @Bean
    public FilterRegistrationBean<MyCustomFilter> myCustomFilterRegistration() {
        FilterRegistrationBean<MyCustomFilter> registrationBean = new FilterRegistrationBean<>();
        // 设置要注册的Filter实例
        registrationBean.setFilter(new MyCustomFilter());
        // 设置拦截路径(/* 拦截所有请求)
        registrationBean.addUrlPatterns("/*");
        // 设置Filter名称
        registrationBean.setName("myCustomFilter");
        // 设置执行顺序(值越小,执行优先级越高,默认值为Integer.MAX_VALUE)
        registrationBean.setOrder(1);
        // 可选:排除拦截路径(如静态资源)
        registrationBean.addExcludeUrlPatterns("/static/*", "/favicon.ico");
        return registrationBean;
    }
}

(2)监听器

2.2.1 来源

同样来自Java EEt 规范 ,核心是一系列事件监听接口(如ServletContextListenerHttpSessionListenerServletRequestListener),由 Web 容器(如 Tomcat)负责触发,不属于 Spring 生态。

2.2.2 核心功能

<1>监听 Web 应用的「启动」和「关闭」事件,是最常用的监听器,应用启动时(Tomcat 启动、Spring Boot 内嵌 Tomcat 启动):执行初始化逻辑,如加载全局配置文件、初始化全局缓存、连接第三方服务。应用关闭时:执行清理逻辑,如关闭数据库连接、释放缓存资源、记录应用关闭日志。

<2>HttpSessionListener(会话监听器):监听用户 Session 的「创建」和「销毁」事件,比如统计当前在线用户数量。

<3>ServletRequestListener(请求监听器):监听每个 HTTP 请求的「创建」和「销毁」事件,比如统计每个请求的处理时长。

<4>属性监听器 (如ServletContextAttributeListener):监听全局上下文、Session、Request 中的属性(添加、修改、删除)事件,使用较少。

2.2.3 配置监听器

步骤 1:自定义 Listener(无需添加@WebListener注解)

java 复制代码
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;

public class MyCustomListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("===== 应用启动成功,执行全局初始化逻辑 =====");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("===== 应用即将关闭,执行全局清理逻辑 =====");
    }
}

步骤 2:创建配置类,注册 Listener 到 Spring 容器

java 复制代码
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ListenerConfig {

    @Bean
    public ServletListenerRegistrationBean<MyCustomListener> myCustomListenerRegistration() {
        ServletListenerRegistrationBean<MyCustomListener> registrationBean = new ServletListenerRegistrationBean<>();
        registrationBean.setListener(new MyCustomListener());
        return registrationBean;
    }
}
相关推荐
Serene_Dream2 小时前
NIO 的底层机理
java·jvm·nio·mmap
skywalker_112 小时前
多线程&JUC
java·开发语言·jvm·线程池
黎雁·泠崖2 小时前
Java基础核心能力总结:从语法到API的完整知识体系
java·开发语言
JaguarJack2 小时前
PHP 现在可以零成本构建原生 iOS 和 Android 应用 NativePHP for Mobile v3 发布
后端·php·laravel·服务端
_周游2 小时前
Java8 API 文档搜索引擎_2.索引模块(实现细节)
java·搜索引擎·intellij-idea
鱼跃鹰飞2 小时前
大厂面试真题-说说Kafka消息的不重复和不丢失
java·分布式·kafka
A懿轩A2 小时前
【Maven 构建工具】Maven 依赖管理详解:坐标、传递、作用域与依赖冲突解决(一篇搞懂)
java·linux·maven
2601_949543012 小时前
Flutter for OpenHarmony垃圾分类指南App实战:资讯详情实现
android·java·flutter
cyforkk4 小时前
12、Java 基础硬核复习:集合框架(数据容器)的核心逻辑与面试考点
java·开发语言·面试