Spring MVC 的核心知识点梳理

MVC 是什么

MVC 不是 Spring 发明的,而是一种设计模式,目的是"解耦"。

  • M(Model,模型) :数据 + 业务逻辑。比如 Teacher 类,TeacherService
  • V(View,视图):展示数据的界面。比如 JSP、Thymeleaf 模板,或者是现代返回 JSON 的前端页面。
  • C(Controller,控制器):接收用户请求,调用 Model,最后选择 View 来展示。

流程:用户点击一个链接 → Controller 拿到请求 → 调 Service 拿到数据(Model)→ 把数据交给 View 渲染 → 返回 HTML 给浏览器。

Spring MVC 就是把这个流程在 Java Web 环境里落地的一套框架。

核心组件与处理流程

Spring MVC 最核心的就是一个 前端控制器(Front Controller) ------DispatcherServlet

组件 作用 常见实现
DispatcherServlet 统一入口,调度一切 Spring 提供,我们只需配置
HandlerMapping 根据请求 URL 找到对应的处理器 RequestMappingHandlerMapping
HandlerAdapter 执行找到的处理器(Controller 方法) RequestMappingHandlerAdapter
HandlerInterceptor 拦截器,在处理方法前后做增强 自定义
ViewResolver 根据视图名找到真正的视图文件 InternalResourceViewResolver (JSP)
HandlerExceptionResolver 处理异常 ExceptionHandlerExceptionResolver

一个请求的完整生命周期(回顾前面讲过的流程图):

  1. 请求到达 DispatcherServlet
  2. DispatcherServletHandlerMapping:谁处理这个 URL?
  3. HandlerMapping 返回一个 HandlerExecutionChain(包含 Controller 方法 + 一堆拦截器)。
  4. DispatcherServletHandlerAdapter:谁能执行这个 Controller 方法?
  5. HandlerAdapter 执行具体方法(期间会做参数绑定、类型转换、校验等)。
  6. 方法返回 ModelAndView(或 @ResponseBody 直接返回数据)。
  7. 若有视图名,ViewResolver 解析出真正的 JSP 等视图。
  8. 渲染视图,响应给浏览器。

Controller 与注解:从入门到精通

@Controller & @RestController

java 复制代码
@Controller  // 声明这是一个控制器类,方法通常返回视图名
public class TeacherController { ... }

@RestController  // = @Controller + @ResponseBody,所有方法默认返回 JSON
public class TeacherRestController { ... }

@RequestMapping 及衍生注解

java 复制代码
@RequestMapping("/teacher")   // 类级别映射
public class TeacherController {

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list() { ... }  // 等价于 @GetMapping("/list")
}

@GetMapping@PostMapping@PutMapping@DeleteMapping 等都是 @RequestMapping 的快捷方式。

参数绑定注解(重点对比)

注解 从哪里拿数据 示例
@RequestParam URL 问号后的参数或表单数据 ?name=Tom@RequestParam("name") String name
@PathVariable URI 路径中的占位符 /teacher/{id}@PathVariable("id") Long id
@RequestBody 请求体中的 JSON/XML POST 的 JSON {"name":"Tom"} 自动转成 Teacher 对象
@ModelAttribute ① 从 Model 中取;② 把参数绑定到对象 常用于表单提交自动封装对象,
@RequestHeader 请求头 @RequestHeader("User-Agent") String ua
@CookieValue Cookie @CookieValue("JSESSIONID") String sid

把参数自动封装成对象

Spring 可以直接将表单字段或 JSON 映射成一个 Java Bean。

表单提交示例

jsp 复制代码
<form action="/teacher/save" method="post">
    <input name="name"/>     <!-- Teacher.name -->
    <input name="age"/>      <!-- Teacher.age -->
    <input type="submit"/>
</form>
java 复制代码
@PostMapping("/teacher/save")
public String save(@ModelAttribute Teacher teacher) {
    // teacher 对象已被自动填充 name 和 age
    teacherService.save(teacher);
    return "redirect:/teacher/list";
}

底层原理:DataBinder + BeanWrapper 负责属性拷贝。

自定义类型转换器:String → Date

很多时候,请求参数是 String,但你想转成 DateLocalDate 或自定义类型。

Spring 内置的转换器和格式化器

  • Converter<S, T> :源类型 → 目标类型,如 StringToDateConverter
  • Formatter :专为字符串和对象互转设计,支持国际化,适合 String <-> Date

自定义一个 String → Date 的 Converter 示例

java 复制代码
@Component
public class StringToDateConverter implements Converter<String, Date> {
    private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date convert(String source) {
        try {
            return format.parse(source);
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式必须为 yyyy-MM-dd");
        }
    }
}

在 Spring Boot 中,只需让它被容器管理(@Component)就会自动注册到转换器链。

在传统 Spring MVC XML 中,需要配置 FormattingConversionServiceFactoryBean

使用场景

java 复制代码
@GetMapping("/teacher/search")
public String searchByDate(@RequestParam("date") Date date) {
    // /teacher/search?date=2025-01-01 → date 直接转换好
}

如果转换失败,会抛出 TypeMismatchException,我们可以用异常处理来统一返回友好信息。

拦截器(Interceptor)和过滤器(Filter)

两者都可以在请求前后做手脚,但层级不同。

对比维度 Filter(过滤器) Interceptor(拦截器)
归属 Servlet 规范,Java EE Spring MVC 框架
作用范围 能拦截所有进入 Servlet 的请求(包括静态资源) 只能拦截进到 Spring MVC 的请求(DispatcherServlet 处理)
是否能用 Spring Bean 不能直接注入(可以迂回) 可以正常注入其他 Bean
执行顺序 先经过 Filter,再进 DispatcherServlet 在 DispatcherServlet 之后,Controller 方法之前
典型场景 字符编码、跨域、权限安全检查 登录检查、日志记录、性能监控、用户权限补充

定义拦截器示例

java 复制代码
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        // 检查 session 中是否有用户
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login");
            return false;  // 不放行
        }
        return true;
    }
}

注册拦截器

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/teacher/**")   // 要拦截的
                .excludePathPatterns("/teacher/login"); // 排除的
    }
}

异常处理:优雅地给前端报错

还记得我们之前聊过的"异常和错误"吗?常用的处理方式是:

局部异常处理

java 复制代码
@Controller
public class TeacherController {
    @ExceptionHandler(TeacherNotFoundException.class)
    public String handleNotFound(TeacherNotFoundException ex, Model model) {
        model.addAttribute("msg", ex.getMessage());
        return "error/404";   // 返回错误视图
    }
}

全局异常处理(推荐)

java 复制代码
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {
        // 返回校验失败信息,如 {"name":"不能为空"}
        ...
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Map<String, String> handleGeneral(Exception ex) {
        return Map.of("error", "服务器内部错误");
    }
}
相关推荐
码云数智-园园3 天前
C++20 Modules 模块详解
java·开发语言·spring
咖啡八杯3 天前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
Flittly3 天前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring
李少兄3 天前
从原理到实战:Spring IoC/DI 核心知识体系与高频面试题全解
java·后端·spring
shushangyun_3 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
ofoxcoding3 天前
在AI API聚合平台配置DeepSeek V3.2提示词缓存实战:快速接入与成本优化指南
人工智能·spring·缓存·ai
一杯奶茶¥4 天前
水果销售网站 CRM客户信息管理系统 超市管理系 酒店管理系统 健身房管理系统 在线音乐网站 校园招聘系统
java·vue.js·spring boot·mysql·spring·java项目
摇滚侠4 天前
SpringMVC 入门到实战 RESTFul 49-55
java·开发语言·后端·spring·intellij-idea·restful
我登哥MVP4 天前
SpringCloud Alibaba 核心组件解析:服务链路追踪
java·spring boot·后端·spring·spring cloud·java-ee·maven
Ysouy4 天前
Spring Data Elasticsearch 全流程学习教程
java·spring·elasticsearch