【JAVA 进阶】SpringMVC全面解析:从入门到实战的核心知识点梳理

【JAVA 进阶】SpringMVC全面解析:从入门到实战的核心知识点梳理

文章目录

在这里插入图片描述

前言

在Java EE企业级开发领域,SpringMVC作为轻量级的Web层开发框架,凭借其清晰的架构设计、灵活的配置方式以及与Spring生态的无缝集成,成为了当前主流的Web开发技术选型之一。它基于MVC(Model-View-Controller)设计模式,通过分离模型、视图和控制器的职责,有效降低了代码耦合度,提升了项目的可维护性和扩展性。本文将从SpringMVC的基础概念出发,逐步深入其核心原理、核心组件、实战应用、高级特性等关键知识点,结合理论讲解与代码示例,帮助读者系统掌握SpringMVC技术栈。最后将对全文知识点进行总结扩展,并推荐优质阅读资料,助力读者进一步深化学习。

一、SpringMVC概述

1.1 MVC设计模式简介

MVC(Model-View-Controller)是一种经典的软件架构设计模式,其核心思想是将应用程序的功能划分为三个独立的模块,通过明确的职责划分实现代码解耦。

  • Model(模型):负责封装应用程序的核心数据和业务逻辑,是应用程序的数据层和业务层的结合体。模型不依赖于视图和控制器,仅专注于数据的处理和业务规则的实现。常见的模型组件包括实体类(Entity)、服务类(Service)、数据访问类(DAO)等。
  • View(视图):负责向用户展示数据,是用户与应用程序交互的界面。视图仅负责数据的呈现,不涉及业务逻辑的处理。常见的视图技术包括JSP、Thymeleaf、Freemarker等。
  • Controller(控制器):负责接收用户的请求,协调模型和视图完成用户需求。控制器接收请求后,调用模型进行业务逻辑处理,获取处理结果后,选择合适的视图向用户展示数据。

MVC设计模式的优势在于实现了功能模块的分离,使得代码结构清晰,便于团队协作开发和后期维护。当需求发生变化时,只需修改对应的模块,不会影响其他模块的功能。

1.2 SpringMVC的定义与核心优势

SpringMVC是Spring框架的一个重要模块,是基于Java实现MVC设计模式的轻量级Web框架。它并非对MVC设计模式的全新实现,而是在Spring生态的基础上,对MVC架构进行了优化和封装,提供了一套简洁、高效的Web开发解决方案。

SpringMVC的核心优势主要体现在以下几个方面:

  • 与Spring无缝集成:SpringMVC是Spring框架的一部分,能够直接使用Spring的IOC容器、AOP等核心特性,无需额外的整合配置,降低了框架集成的复杂度。
  • 灵活的配置方式:支持XML配置和注解配置两种方式,注解配置简化了开发流程,提高了开发效率;XML配置则便于对全局配置进行统一管理,适用于复杂的项目场景。
  • 清晰的架构设计:基于MVC设计模式,职责划分明确,各组件之间耦合度低,便于代码的维护和扩展。
  • 强大的功能支持:提供了请求参数绑定、数据验证、视图解析、异常处理、文件上传等一系列完善的功能,满足企业级Web开发的各种需求。
  • 良好的扩展性:支持自定义拦截器、转换器、格式化器等组件,能够根据项目的特殊需求进行功能扩展。

1.3 SpringMVC的应用场景

SpringMVC适用于各种规模的Java Web项目开发,尤其是企业级应用项目。无论是中小型的管理系统、电商平台,还是大型的分布式Web应用,SpringMVC都能凭借其灵活的架构和强大的功能满足开发需求。此外,由于SpringMVC与Spring Boot、Spring Cloud等主流技术的无缝集成,它也成为了微服务架构中Web层开发的首选技术。

二、SpringMVC核心原理与执行流程

2.1 SpringMVC核心组件

在这里插入图片描述

SpringMVC的核心功能是通过一系列组件协同工作实现的,每个组件都有明确的职责。了解这些核心组件是掌握SpringMVC原理的关键。

2.1.1 前端控制器(DispatcherServlet)

DispatcherServlet是SpringMVC的核心控制器,负责接收所有用户的请求,并协调其他组件完成请求的处理。它是整个SpringMVC流程的入口,相当于一个“中央处理器”。DispatcherServlet的主要职责包括:

  • 接收HTTP请求,解析请求URL和请求参数;
  • 根据请求信息查找对应的处理器(Handler);
  • 调用处理器适配器(HandlerAdapter)执行处理器;
  • 接收处理器的处理结果(ModelAndView);
  • 调用视图解析器(ViewResolver)解析视图,渲染并返回响应结果。

2.1.2 处理器映射器(HandlerMapping)

HandlerMapping的职责是根据用户请求的URL,查找对应的处理器(Handler)和拦截器(Interceptor)。SpringMVC提供了多种HandlerMapping实现,例如:

  • RequestMappingHandlerMapping:支持@RequestMapping注解的处理器映射,是当前最常用的映射器;
  • BeanNameUrlHandlerMapping:根据Bean的名称作为URL进行映射;
  • SimpleUrlHandlerMapping:通过XML配置的方式,将URL与处理器进行直接映射。

当DispatcherServlet接收到请求后,会调用HandlerMapping获取对应的HandlerExecutionChain(包含处理器和拦截器)。

2.1.3 处理器适配器(HandlerAdapter)

HandlerAdapter的职责是适配不同类型的处理器,使得DispatcherServlet无需关心处理器的具体实现,能够统一调用处理器的处理方法。由于SpringMVC支持多种类型的处理器(如注解式处理器、控制器接口实现类等),不同处理器的调用方式不同,HandlerAdapter通过适配模式解决了这一问题。

常用的HandlerAdapter实现包括:

  • RequestMappingHandlerAdapter:适配使用@RequestMapping注解的处理器;
  • SimpleControllerHandlerAdapter:适配实现Controller接口的处理器;
  • SimpleServletHandlerAdapter:适配实现Servlet接口的处理器。

2.1.4 处理器(Handler)

Handler即业务处理器,是SpringMVC中处理具体业务逻辑的组件,相当于MVC架构中的Controller。处理器接收请求参数,调用业务层服务完成数据处理,最终返回处理结果(ModelAndView)。在实际开发中,处理器通常是一个使用@RequestMapping注解的Controller类中的方法。

2.1.5 视图解析器(ViewResolver)

ViewResolver的职责是根据处理器返回的ModelAndView中的视图名称,解析出具体的视图对象(View)。它将逻辑视图名转换为物理视图路径,例如将“index”解析为“/WEB-INF/views/index.jsp”。

常用的ViewResolver实现包括:

  • InternalResourceViewResolver:解析JSP视图,是最常用的视图解析器;
  • ThymeleafViewResolver:解析Thymeleaf视图;
  • FreeMarkerViewResolver:解析Freemarker视图。

2.1.6 视图(View)

View是视图组件,负责将处理器返回的数据(Model)渲染为用户可查看的界面。View接收Model中的数据,通过特定的视图技术(如JSP、Thymeleaf)将数据展示出来。不同的视图技术对应不同的View实现类。

2.1.7 模型和视图(ModelAndView)

ModelAndView是处理器返回的结果对象,包含了视图名称和需要展示的数据(Model)。其中,Model是一个键值对集合,用于存储需要传递给视图的数据;ViewName是逻辑视图名,用于视图解析器解析具体的视图。

2.2 SpringMVC执行流程详解

SpringMVC的请求处理流程是一个标准化的流程,各组件按照固定的顺序协同工作。以下是SpringMVC完整的执行流程,结合核心组件的交互进行说明:

  1. 用户发送HTTP请求:用户通过浏览器向服务器发送请求,请求URL例如“http://localhost:8080/springmvc/user/list”。
  2. 请求到达前端控制器(DispatcherServlet):服务器接收到请求后,根据Web.xml中的配置(或Spring Boot的自动配置),将请求转发给DispatcherServlet。DispatcherServlet是SpringMVC的入口,负责统一处理所有请求。
  3. DispatcherServlet调用处理器映射器(HandlerMapping):DispatcherServlet将请求URL传递给HandlerMapping,HandlerMapping根据URL查找对应的处理器(Handler)和拦截器(Interceptor),返回HandlerExecutionChain对象(包含处理器和拦截器列表)。
  4. DispatcherServlet调用处理器适配器(HandlerAdapter):DispatcherServlet根据HandlerMapping返回的处理器类型,选择对应的HandlerAdapter。HandlerAdapter负责适配处理器,调用处理器的处理方法(如Controller中的@RequestMapping注解方法)。
  5. 处理器执行业务逻辑并返回ModelAndView:处理器(Controller方法)接收请求参数,调用业务层(Service)的方法完成数据处理,将处理结果(数据)存入Model,设置逻辑视图名,最终返回ModelAndView对象。
  6. DispatcherServlet调用视图解析器(ViewResolver):DispatcherServlet将ModelAndView中的逻辑视图名传递给ViewResolver,ViewResolver解析出具体的物理视图路径(如“/WEB-INF/views/user/list.jsp”),返回View对象。
  7. 视图渲染数据:View对象接收Model中的数据,通过视图技术(如JSP)将数据渲染为HTML页面。
  8. 返回响应结果:渲染后的HTML页面通过HTTP响应返回给用户浏览器,用户看到最终的页面效果。

注意:在整个执行流程中,拦截器会在处理器执行前后进行拦截处理,实现权限控制、日志记录等功能。拦截器的执行顺序是:preHandle(处理器执行前)→ 处理器执行 → postHandle(处理器执行后,视图渲染前)→ afterCompletion(视图渲染后)。

三、SpringMVC入门实战

3.1 环境搭建(基于Spring Boot)

Spring Boot提供了自动配置功能,能够快速搭建SpringMVC项目,无需繁琐的XML配置。以下是基于Spring Boot的SpringMVC环境搭建步骤:

3.1.1 创建Maven项目

使用IDEA或Eclipse创建一个Maven项目,选择“Spring Initializr”模板(IDEA内置),填写项目基本信息(Group、Artifact、Version等)。

3.1.2 引入依赖

在pom.xml文件中引入Spring Boot Web依赖(包含SpringMVC核心依赖):

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

Spring Boot Starter Web依赖会自动引入SpringMVC的核心组件(DispatcherServlet、HandlerMapping、ViewResolver等)以及Tomcat服务器依赖,实现开箱即用。

3.1.3 编写主启动类

创建Spring Boot主启动类,使用@SpringBootApplication注解标识:

importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassSpringMvcDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SpringMvcDemoApplication.class, args);}}

@SpringBootApplication注解包含了@ComponentScan(组件扫描)、@EnableAutoConfiguration(自动配置)、@Configuration(配置类)三个核心注解,能够自动扫描当前包及其子包下的组件,并完成SpringMVC的自动配置。

3.2 第一个SpringMVC程序:Hello World

编写一个简单的Controller,实现“Hello World”功能,验证SpringMVC环境是否搭建成功。

3.2.1 创建Controller类

在com.example.springmvcdemo.controller包下创建HelloController类,使用@Controller注解标识控制器,使用@RequestMapping注解映射请求路径:

importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.ResponseBody;@ControllerpublicclassHelloController{// 映射请求路径:/hello@RequestMapping("/hello")@ResponseBody// 直接返回字符串,不进行视图渲染publicStringhello(){return"Hello SpringMVC!";}}

说明:

  • @Controller:标识该类为SpringMVC的控制器组件,Spring会自动扫描并将其纳入IOC容器管理;
  • @RequestMapping(“/hello”):映射HTTP请求路径“/hello”到该方法;
  • @ResponseBody:表示该方法的返回值直接作为HTTP响应体返回,不经过视图解析器解析视图。如果不使用该注解,SpringMVC会将返回值作为逻辑视图名进行解析。

3.2.2 启动项目并测试

运行主启动类SpringMvcDemoApplication,启动成功后,打开浏览器访问“http://localhost:8080/hello”,浏览器会显示“Hello SpringMVC!”,说明SpringMVC环境搭建成功,请求处理正常。

3.3 请求参数绑定

SpringMVC提供了强大的请求参数绑定功能,能够自动将HTTP请求参数绑定到Controller方法的参数上。常见的参数绑定场景包括基本类型参数、引用类型参数、集合类型参数等。

3.3.1 基本类型参数绑定

请求参数名与Controller方法参数名一致时,SpringMVC会自动完成参数绑定。例如:

@RequestMapping("/user/find")@ResponseBodypublicStringfindUserById(Integer id,String name){return"id: "+ id +", name: "+ name;}

访问URL:“http://localhost:8080/user/find?id=1&name=zhangsan”,响应结果:“id: 1, name: zhangsan”。

如果请求参数名与方法参数名不一致,可以使用@RequestParam注解指定请求参数名:

@RequestMapping("/user/findByParam")@ResponseBodypublicStringfindByParam(@RequestParam("user_id")Integer id,@RequestParam("user_name")String name){return"id: "+ id +", name: "+ name;}

访问URL:“http://localhost:8080/user/findByParam?user_id=2&user_name=lisi”,响应结果:“id: 2, name: lisi”。

3.3.2 引用类型参数绑定

当请求参数较多时,可以将参数封装为引用类型(如实体类),SpringMVC会自动将请求参数绑定到实体类的属性上(要求请求参数名与实体类属性名一致)。

第一步:创建User实体类:

publicclassUser{privateInteger id;privateString name;privateInteger age;// 无参构造器、有参构造器、getter、setter方法publicUser(){}publicUser(Integer id,String name,Integer age){this.id = id;this.name = name;this.age = age;}// getter和setter方法省略@OverridepublicStringtoString(){return"User{id="+ id +",+ name +"', age="+ age +"}";}}

第二步:编写Controller方法:

@RequestMapping("/user/add")@ResponseBodypublicStringaddUser(User user){return"添加用户:"+ user.toString();}

访问URL:“http://localhost:8080/user/add?id=3&name=wangwu&age=25”,响应结果:“添加用户:User{id=3, name=‘wangwu’, age=25}”。

3.3.3 集合类型参数绑定

当需要传递多个同类型参数时(如批量删除用户的ID列表),可以使用集合类型(List、Map)接收参数。此时需要将集合参数封装到一个VO(Value Object)类中,或者使用@RequestParam注解指定参数名。

示例1:使用List接收批量删除的ID:

@RequestMapping("/user/deleteBatch")@ResponseBodypublicStringdeleteBatch(@RequestParam("ids")List<Integer> ids){return"批量删除的ID:"+ ids.toString();}

访问URL:“http://localhost:8080/user/deleteBatch?ids=1&ids=2&ids=3”,响应结果:“批量删除的ID:[1, 2, 3]”。

示例2:使用VO类封装集合参数(适用于复杂场景):

// 创建UserVO类publicclassUserVO{privateList<User> userList;// getter和setter方法publicList<User>getUserList(){return userList;}publicvoidsetUserList(List<User> userList){this.userList = userList;}}// Controller方法@RequestMapping("/user/addBatch")@ResponseBodypublicStringaddBatch(UserVO userVO){return"批量添加用户:"+ userVO.getUserList().toString();}

前端传递参数时,需要按照“userList[0].id=1&userList[0].name=zhangsan&userList[1].id=2&userList[1].name=lisi”的格式传递。

3.4 视图解析与页面跳转

在实际开发中,除了返回JSON数据(使用@ResponseBody),还经常需要返回页面视图。SpringMVC通过视图解析器(ViewResolver)完成逻辑视图名到物理视图路径的解析。以下是基于Thymeleaf视图技术的页面跳转示例(Thymeleaf是Spring Boot推荐的视图技术,比JSP更灵活、更强大)。

3.4.1 引入Thymeleaf依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

3.4.2 配置视图解析器

Spring Boot对Thymeleaf提供了自动配置,默认的视图解析规则如下:

  • 模板文件路径:classpath:/templates/
  • 模板文件后缀:.html
  • 逻辑视图名“index”会被解析为:classpath:/templates/index.html

如果需要自定义配置,可以在application.properties文件中添加以下配置:

# thymeleaf模板前缀(默认classpath:/templates/) spring.thymeleaf.prefix=classpath:/templates/pages/ # thymeleaf模板后缀(默认.html) spring.thymeleaf.suffix=.html # 编码格式 spring.thymeleaf.encoding=UTF-8 # 模板模式 spring.thymeleaf.mode=HTML5 

3.4.3 编写视图页面

在classpath:/templates/目录下创建index.html文件:

<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>首页</title></head><body><h1th:text="${message}">欢迎访问首页</h1><ath:href="@{/user/list}">查看用户列表</a></body></html>

在classpath:/templates/目录下创建user/list.html文件:

<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>用户列表</title></head><body><h1>用户列表</h1><tableborder="1"><tr><th>ID</th><th>姓名</th><th>年龄</th></tr><trth:each="user : ${userList}"><tdth:text="${user.id}"></td><tdth:text="${user.name}"></td><tdth:text="${user.age}"></td></tr></table></body></html>

3.4.3 编写Controller方法实现页面跳转

@RequestMapping("/index")publicStringtoIndex(Model model){// 向Model中存入数据,供视图页面使用 model.addAttribute("message","Hello SpringMVC + Thymeleaf!");// 返回逻辑视图名“index”,视图解析器会解析为classpath:/templates/index.htmlreturn"index";}@RequestMapping("/user/list")publicStringuserList(Model model){// 模拟从数据库查询用户列表List<User> userList =newArrayList<>(); userList.add(newUser(1,"zhangsan",22)); userList.add(newUser(2,"lisi",23)); userList.add(newUser(3,"wangwu",24));// 向Model中存入用户列表 model.addAttribute("userList", userList);// 返回逻辑视图名“user/list”,解析为classpath:/templates/user/list.htmlreturn"user/list";}

测试:访问“http://localhost:8080/index”,会跳转到index.html页面,显示“Hello SpringMVC + Thymeleaf!”;点击“查看用户列表”链接,会跳转到user/list.html页面,显示用户列表数据。

四、SpringMVC高级特性

4.1 拦截器(Interceptor)

SpringMVC的拦截器类似于Servlet的过滤器(Filter),用于在请求处理的不同阶段对请求进行拦截和处理。拦截器可以实现权限控制、日志记录、参数校验、性能监控等功能。与Filter不同的是,拦截器是SpringMVC框架内部的组件,能够访问Spring的IOC容器,而Filter是Servlet规范的组件,作用范围更广。

4.1.1 拦截器的工作原理

拦截器通过实现HandlerInterceptor接口或继承HandlerInterceptorAdapter类(已过时,推荐实现接口)来定义。HandlerInterceptor接口提供了三个方法,对应拦截器的三个执行时机:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):在处理器(Handler)执行前执行。返回true表示放行,继续执行后续的拦截器和处理器;返回false表示拦截,不再执行后续操作。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):在处理器执行后、视图渲染前执行。可以通过ModelAndView对象对视图和数据进行修改。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):在视图渲染后、请求完成后执行。通常用于资源清理、日志记录等操作。

4.1.2 自定义拦截器实现

第一步:创建自定义拦截器类,实现HandlerInterceptor接口:

importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;publicclassLoginInterceptorimplementsHandlerInterceptor{// 处理器执行前拦截@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{// 模拟登录验证:从Session中获取用户信息Object user = request.getSession().getAttribute("user");if(user ==null){// 未登录,重定向到登录页面 response.sendRedirect(request.getContextPath()+"/login.html");returnfalse;}// 已登录,放行returntrue;}// 处理器执行后、视图渲染前拦截@OverridepublicvoidpostHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{// 可以修改ModelAndView中的数据或视图if(modelAndView !=null){ modelAndView.addObject("interceptorMsg","来自LoginInterceptor的消息");}}// 视图渲染后、请求完成后拦截@OverridepublicvoidafterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throwsException{// 资源清理、日志记录等操作System.out.println("请求处理完成,执行资源清理...");}}

4.1.3 配置拦截器

在SpringMVC中,需要通过配置类(实现WebMvcConfigurer接口)来注册拦截器,并指定拦截的请求路径和排除的请求路径。

importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){// 注册LoginInterceptor拦截器 registry.addInterceptor(newLoginInterceptor()).addPathPatterns("/**")// 拦截所有请求.excludePathPatterns("/login.html","/user/login");// 排除登录页面和登录接口的请求}}

说明:

  • addPathPatterns(“/**”):表示拦截所有请求路径;
  • excludePathPatterns(“/login.html”, “/user/login”):表示排除对“/login.html”页面和“/user/login”接口的拦截,允许未登录用户访问这些资源。

4.2 异常处理

在Web应用开发中,异常处理是不可或缺的一部分。SpringMVC提供了多种异常处理方式,能够统一捕获和处理Controller层的异常,避免异常直接暴露给用户,提升用户体验。常用的异常处理方式包括:@ExceptionHandler注解、@ControllerAdvice注解、实现HandlerExceptionResolver接口等。

4.2.1 @ExceptionHandler注解(局部异常处理)

@ExceptionHandler注解用于在Controller内部定义异常处理方法,只能处理当前Controller中的异常,属于局部异常处理。

@ControllerpublicclassUserController{// 业务方法,可能抛出异常@RequestMapping("/user/get")@ResponseBodypublicStringgetUserById(Integer id){if(id ==null){thrownewNullPointerException("用户ID不能为空");}if(id <=0){thrownewIllegalArgumentException("用户ID必须为正数");}return"用户ID:"+ id;}// 处理当前Controller中的NullPointerException@ExceptionHandler(NullPointerException.class)@ResponseBodypublicStringhandleNullPointerException(NullPointerException e){return"错误:"+ e.getMessage();}// 处理当前Controller中的IllegalArgumentException@ExceptionHandler(IllegalArgumentException.class)@ResponseBodypublicStringhandleIllegalArgumentException(IllegalArgumentException e){return"错误:"+ e.getMessage();}}

4.2.2 @ControllerAdvice + @ExceptionHandler(全局异常处理)

@ControllerAdvice注解用于定义全局异常处理类,结合@ExceptionHandler注解可以捕获所有Controller中的异常,实现全局异常统一处理。

importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.ResponseBody;// 全局异常处理类,捕获所有Controller的异常@ControllerAdvicepublicclassGlobalExceptionHandler{// 处理NullPointerException@ExceptionHandler(NullPointerException.class)@ResponseBodypublicStringhandleNullPointerException(NullPointerException e){return"全局错误:"+ e.getMessage();}// 处理IllegalArgumentException@ExceptionHandler(IllegalArgumentException.class)@ResponseBodypublicStringhandleIllegalArgumentException(IllegalArgumentException e){return"全局错误:"+ e.getMessage();}// 处理所有未捕获的异常(兜底处理)@ExceptionHandler(Exception.class)@ResponseBodypublicStringhandleException(Exception e){return"系统异常:"+ e.getMessage();}}

使用全局异常处理后,所有Controller中抛出的异常都会被GlobalExceptionHandler中的对应方法捕获并处理,无需在每个Controller中单独定义异常处理方法。

4.3 文件上传

SpringMVC提供了便捷的文件上传功能,基于Apache Commons FileUpload组件实现(Spring Boot已自动整合相关依赖)。以下是文件上传的实现步骤:

4.3.1 引入文件上传依赖

Spring Boot的spring-boot-starter-web依赖已包含文件上传所需的依赖,无需额外引入。如果是传统SpringMVC项目,需要手动引入以下依赖:

<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>

4.3.2 配置文件上传解析器

Spring Boot会自动配置MultipartResolver(文件上传解析器),默认的最大上传文件大小为1MB。如果需要自定义配置,可以在application.properties文件中添加以下配置:

# 单个文件最大上传大小 spring.servlet.multipart.max-file-size=10MB # 单次请求最大上传大小(多文件上传时) spring.servlet.multipart.max-request-size=50MB # 文件上传临时目录(默认在系统临时目录) spring.servlet.multipart.location=${java.io.tmpdir} 

4.3.3 实现文件上传功能

第一步:编写文件上传页面(upload.html):

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>文件上传</title></head><body><formaction="/file/upload"method="post"enctype="multipart/form-data"> 选择文件:<inputtype="file"name="file"><br><inputtype="submit"value="上传"></form></body></html>

注意:form表单的enctype属性必须设置为“multipart/form-data”,否则无法正确上传文件。

4.3.4 编写文件上传Controller方法

importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.ResponseBody;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.multipart.MultipartFile;importjava.io.File;importjava.io.IOException;importjava.util.UUID;@RestControllerpublicclassFileUploadController{// 文件上传路径(实际开发中建议配置在配置文件中)privatestaticfinalString UPLOAD_PATH ="D:/upload/";@PostMapping("/file/upload")publicStringuploadFile(@RequestParam("file")MultipartFile file){// 检查文件是否为空if(file.isEmpty()){return"文件不能为空";}// 获取文件名String originalFilename = file.getOriginalFilename();// 生成唯一文件名(避免文件名重复覆盖)String fileName = UUID.randomUUID().toString()+ originalFilename.substring(originalFilename.lastIndexOf("."));// 创建上传目录(如果不存在)File uploadDir =newFile(UPLOAD_PATH);if(!uploadDir.exists()){ uploadDir.mkdirs();}try{// 保存文件到指定路径 file.transferTo(newFile(UPLOAD_PATH + fileName));return"文件上传成功!文件名:"+ fileName;}catch(IOException e){ e.printStackTrace();return"文件上传失败:"+ e.getMessage();}}}

测试:访问“http://localhost:8080/upload.html”,选择文件并点击“上传”按钮,文件会被保存到“D:/upload/”目录下,并返回上传结果。

五、SpringMVC与其他技术的集成

5.1 SpringMVC与Spring的集成

SpringMVC本身就是Spring框架的一部分,因此与Spring的集成非常简单。在Spring Boot项目中,通过@SpringBootApplication注解的@ComponentScan功能,会自动扫描Controller、Service、Repository等组件,实现Spring IOC容器与SpringMVC的无缝集成。

在传统SpringMVC项目中,需要在Web.xml中配置Spring的ContextLoaderListener,加载Spring的配置文件,实现Spring IOC容器的初始化。配置示例如下:

<!-- 配置Spring的ContextLoaderListener,加载Spring配置文件 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml</param-value></context-param>

集成后,SpringMVC的Controller可以直接通过@Autowired注解注入Spring IOC容器中的Service、DAO等组件,实现业务逻辑的调用。

5.2 SpringMVC与MyBatis的集成

MyBatis是一款优秀的持久层框架,SpringMVC与MyBatis的集成是企业级开发的常见组合。集成步骤如下:

5.2.1 引入依赖

<!-- MyBatis核心依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><!-- MyBatis与Spring集成依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.7</version></dependency><!-- 数据库驱动依赖(MySQL) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!-- 数据源依赖(Druid) --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version></dependency>

5.2.2 配置数据源和SqlSessionFactory

在Spring配置文件中配置数据源(Druid)、SqlSessionFactoryBean、MapperScannerConfigurer等组件:

<!-- 配置数据源 --><beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><propertyname="driverClassName"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC"/><propertyname="username"value="root"/><propertyname="password"value="123456"/></bean><!-- 配置SqlSessionFactoryBean --><beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"><propertyname="dataSource"ref="dataSource"/><!-- 配置MyBatis映射文件路径 --><propertyname="mapperLocations"value="classpath:mapper/*.xml"/><!-- 配置MyBatis全局配置文件 --><propertyname="configLocation"value="classpath:mybatis-config.xml"/></bean><!-- 配置Mapper扫描器,自动扫描Mapper接口并创建代理对象 --><beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer"><propertyname="basePackage"value="com.example.dao"/><propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory"/></bean>

5.2.3 编写Mapper接口和映射文件

创建UserMapper接口:

publicinterfaceUserMapper{UserselectUserById(Integer id);}

创建UserMapper.xml映射文件:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.example.dao.UserMapper"><selectid="selectUserById"parameterType="java.lang.Integer"resultType="com.example.entity.User"> select id, name, age from user where id = #{id} </select></mapper>

5.2.4 在Service中注入Mapper接口

@ServicepublicclassUserService{@AutowiredprivateUserMapper userMapper;publicUsergetUserById(Integer id){return userMapper.selectUserById(id);}}

5.2.5 在Controller中调用Service

@ControllerpublicclassUserController{@AutowiredprivateUserService userService;@RequestMapping("/user/get/{id}")@ResponseBodypublicUsergetUserById(@PathVariable("id")Integer id){return userService.getUserById(id);}}

集成完成后,通过访问“http://localhost:8080/user/get/1”,即可调用MyBatis查询数据库中的用户数据并返回。

六、总结与扩展

6.1 本文知识点总结

本文围绕SpringMVC知识点展开,采用总分总的编写模式,从基础到进阶,系统讲解了SpringMVC的核心内容。首先介绍了MVC设计模式和SpringMVC的基本概念、核心优势及应用场景,帮助读者建立对SpringMVC的整体认知;其次深入剖析了SpringMVC的核心组件(DispatcherServlet、HandlerMapping、HandlerAdapter等)和执行流程,让读者理解SpringMVC的工作原理;然后通过基于Spring Boot的实战案例,讲解了SpringMVC的环境搭建、请求参数绑定、视图解析与页面跳转等基础应用;接着介绍了SpringMVC的高级特性,包括拦截器、异常处理、文件上传等,提升读者的实战能力;随后讲解了SpringMVC与Spring、MyBatis等技术的集成,满足企业级开发的需求;最后通过总结与扩展,梳理全文知识点,并提供进一步学习的阅读资料。

核心知识点梳理:

  • MVC设计模式:模型(Model)、视图(View)、控制器(Controller)的职责划分;
  • SpringMVC核心组件:DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)等的作用;
  • SpringMVC执行流程:从接收请求到返回响应的完整步骤,各组件的协同工作机制;
  • 基础实战:环境搭建、请求参数绑定(基本类型、引用类型、集合类型)、视图解析与页面跳转;
  • 高级特性:拦截器(权限控制、日志记录)、异常处理(局部异常、全局异常)、文件上传;
  • 技术集成:与Spring的无缝集成、与MyBatis的持久层集成。

6.2 知识点扩展

除了本文讲解的核心知识点,SpringMVC还有一些进阶内容值得深入学习,以应对更复杂的开发场景:

  • RESTful风格API开发:RESTful是一种软件架构风格,通过HTTP方法(GET、POST、PUT、DELETE)对应CRUD操作,实现资源的统一管理。SpringMVC通过@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping等注解

Read more

Vibe Coding - Claude Code 做 Java 项目 AI 结对编程最佳实践

Vibe Coding - Claude Code 做 Java 项目 AI 结对编程最佳实践

文章目录 * 概述 * 一、Claude Code + Developer Kit 是什么 * 1. Claude Code:类 IDE 的 AI 开发伴侣 * 2. Developer Kit:给 Claude 装上一整套 Java 技能包 * 二、快速上手:把 Developer Kit 装进你的 Java 项目 * 1. 安装到本机 / CLI 环境 * 2. 安装到具体的 Java 项目(重点) * 三、日常开发:Claude 作为 Java 结对编程伙伴 * 1. 从领域模型到完整 CRUD(

By Ne0inhk
【Java 开发日记】我们来说一下消息的可靠性投递

【Java 开发日记】我们来说一下消息的可靠性投递

目录 1. 核心概念 2. 面临的挑战 3. 关键实现机制 3.1 生产端保证 3.2 Broker端保证 3.3 消费端保证 4. 完整可靠性方案 4.1 事务消息方案(如RocketMQ) 4.2 最大努力投递方案 4.3 本地消息表方案(经典) 5. 高级特性与优化 5.1 顺序性保证 5.2 批量消息可靠性 5.3 监控与对账 6. 不同MQ的实现差异 7. 实践建议 总结 面试回答 1. 核心概念 可靠性投递(Reliable

By Ne0inhk

骑士一百天下载安装 MC JAVA

一、先搞清楚:到底下的是啥? 名称说明骑士一百天B 站 UP 主“M 仔”等发布的剧情向生存整合包(含任务书、假面骑士系模组、100 天倒计时)。核心 Mod假面骑士(KamenRider)、CraftTweaker、GameStage、CustomNPC、倒计时插件等。运行环境Java 版 1.16.5( Forge 36.2+ 实测可启动)。 二、获取地址(官方源) 直达链接:【整合包】MC假面骑士100天整合包(完结) 三、两种安装姿势:懒人一键包 vs 手动拼装 ✅ 推荐:一键整合(小白专用) 1. 下整合包 得到 骑士一百天v0.95.

By Ne0inhk
告别 IDEA,拥抱 Trae:一位 Java 后端程序员的真实迁移体验

告别 IDEA,拥抱 Trae:一位 Java 后端程序员的真实迁移体验

作为一名常年和 Spring Boot、微服务打交道的 Java 开发者,IDEA 几乎是我过去几年的 “本命 IDE”。但最近,我彻底把主力开发环境换成了Trae。这不是跟风尝鲜,而是真实体验到效率、流畅度与 AI 能力的全面升级。 这篇文章,我用最实在的体验,告诉你Java 程序员从 IDEA 迁移到 Trae 到底值不值、怎么迁、踩过哪些坑、带来哪些爽点。 一、为什么我会从 IDEA 转向 Trae? 先说说我放弃 IDEA 的核心原因: 1. 启动慢、吃内存:项目稍大就卡,开机启动要等半天 2. 插件臃肿:很多功能用不上,却占资源 3. AI 能力弱:自带补全跟不上时代,装插件又不稳定

By Ne0inhk