【笔记】Spring MVC 相关介绍

目录

1.介绍一下org.springframework.ui.Model

[1. 本质与实现原理](#1. 本质与实现原理)

[2. 示例代码](#2. 示例代码)

2.被@RequestMapping标注的类的方法参数

[3.BindingResult / Errors 必须紧跟在被校验的实体参数后面(代码说明)](#3.BindingResult / Errors 必须紧跟在被校验的实体参数后面(代码说明))

正确代码

错误代码


====

====

1.介绍一下org.springframework.ui.Model

org.springframework.ui.Model 是 Spring MVC 框架中极其核心的接口,它的主要作用是在 控制器(Controller)视图(View) 之间建立数据传递的桥梁。

简单来说,当你在后端处理完业务逻辑后,需要将数据(如用户信息、列表)送到前端页面(如 JSP、Thymeleaf)显示,Model 就是那个用来装数据的"容器"。

1. 本质与实现原理

  • 本质 :它是一个增强版的 Map<String, Object>。你可以向其中添加 Key-Value 键值对。

  • 实际实现类 :在 Spring MVC 运行时,我们直接使用的 Model 接口对象的实际实现类通常是 BindingAwareModelMap (它继承自 ModelMap,而 ModelMap 又继承自 LinkedHashMap)。

  • 存储位置 :当你调用 model.addAttribute() 时,数据最终会被放入 HttpServletRequestattributes 属性域中。因此,它的作用域是 Request 级别(一次请求有效)。

2. 示例代码

java 复制代码
package com.example.controller; // 假设包名,根据实际情况修改

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

// 自定义的业务类和实体类(根据项目实际包路径导入)
import com.example.service.UserService;
import com.example.entity.User;

@Controller
@RequestMapping("/api/user")  // 类级别定义基础路径
public class UserController {

    // 模拟业务服务
    private UserService userService = new UserService();

    // 方式一:method = RequestMethod.GET ------ 查询用户详情
    @RequestMapping(value = "/profile", method = RequestMethod.GET)
    public String getUserProfile(@RequestParam("id") Long id, Model model) {
        // 1. 业务数据
        User user = userService.findById(id);
        String pageTitle = "用户个人中心";

        // 2. 显式将数据放入 Model(推荐,视图名清晰)
        model.addAttribute("userInfo", user);
        model.addAttribute("title", pageTitle);

        // 3. 返回视图逻辑名(由视图解析器解析,如 Thymeleaf 或 JSP)
        return "profile"; // 对应 /WEB-INF/views/profile.jsp 或 profile.html
    }

    // 方式二:method = RequestMethod.POST ------ 新增用户(重定向)
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addUser(@ModelAttribute User user, Model model) {
        // 模拟保存
        userService.save(user);
        
        // 给 Model 添加提示信息(仅在当前请求有效)
        model.addAttribute("message", "添加成功!");
        
        // 重定向时,Model 中的数据不会带过去(需要用 RedirectAttributes)
        return "redirect:/api/user/profile?id=" + user.getId();
    }
}

==

2.被@RequestMapping标注的类的方法参数

====

分类 参数类型 / 注解 作用说明 示例代码
请求数据提取 @PathVariable 获取 URL 路径中的占位符变量 @PathVariable Long id
@RequestParam 获取请求参数(URL 查询参数或表单参数) @RequestParam String name
@RequestParam + required=false 获取非必填参数,未传时为 null @RequestParam(required=false) Integer age
@RequestParam + defaultValue 获取参数,未传时使用默认值 @RequestParam(defaultValue="1") int page
@RequestBody 将请求体(JSON/XML)绑定到 Java 对象 @RequestBody User user
@RequestHeader 获取 HTTP 请求头中的值 @RequestHeader("User-Agent") String ua
@CookieValue 获取 Cookie 中的值 @CookieValue("JSESSIONID") String jid
@ModelAttribute 将请求参数绑定到对象,并自动放入 Model @ModelAttribute User user
@MatrixVariable 获取矩阵变量(/cars;color=red @MatrixVariable String color
数据输出 Model 添加键值对数据到 Request 作用域 model.addAttribute("key", value)
ModelMap Model 的实现类,用法类似 Map modelMap.put("key", value)
RedirectAttributes 重定向时传递数据(Flash Attributes) redirectAttributes.addFlashAttribute("msg", "成功")
验证与错误 BindingResult 接收 @Valid 校验的结果(错误信息) @Valid @RequestBody User user, BindingResult result
Errors BindingResult 的父接口,功能相同 Errors errors
Servlet API HttpServletRequest 获取原生请求对象 HttpServletRequest request
HttpServletResponse 获取原生响应对象 HttpServletResponse response
HttpSession 获取当前会话(自动创建) HttpSession session
WebRequest Spring 封装的通用请求接口 WebRequest webRequest
NativeWebRequest 更底层的 Web 请求接口 NativeWebRequest nativeRequest
输入输出流 InputStream / Reader 获取请求体的原始输入流 InputStream inputStream
OutputStream / Writer 获取响应的原始输出流 OutputStream outputStream
安全与上下文 Principal 获取当前登录用户信息(配合 Spring Security) Principal principal
Locale 获取当前请求的语言区域 Locale locale
TimeZone 获取当前请求的时区 TimeZone timeZone
Spring Data Pageable 分页参数(需引入 Spring Data) Pageable pageable(自动解析 ?page=0&size=10
Sort 排序参数(需引入 Spring Data) Sort sort(自动解析 ?sort=id,desc
通用封装 HttpEntity<T> 封装整个请求(Headers + Body) HttpEntity<User> entity
RequestEntity<T> HttpEntity 的子类,带更多请求信息 RequestEntity<User> requestEntity
构建工具 UriComponentsBuilder 用于构建动态 URL UriComponentsBuilder builder
其他可选 MultipartFile 接收上传的文件(需搭配 @RequestParam @RequestParam MultipartFile file
BindingAwareModelMap Model 的具体实现类,较少直接用 BindingAwareModelMap modelMap
ModelAttribute + @SessionAttributes 配合 Session 使用的属性 类上标注 @SessionAttributes,方法参数直接用 @ModelAttribute

====

特别提醒

  1. BindingResult / Errors 必须紧跟在被校验的实体参数后面,否则校验异常会直接抛出,无法进入方法体。

  2. PageableSort 需要引入 Spring Data 相关依赖才能使用。

  3. 以上参数可以任意组合 ,顺序基本自由(除了 BindingResult 必须紧跟被校验对象)。

===

3.BindingResult / Errors 必须紧跟在被校验的实体参数后面(代码说明)

===

正确代码

java 复制代码
@RestController
@RequestMapping("/api/user")
public class UserController {

    @PostMapping("/register")
    public String register(
            // 1. 被校验的实体
            @Valid @RequestBody User user,
            // 2. BindingResult 必须紧跟其后(中间不能插入任何其他参数)
            BindingResult result,
            // 3. 其他参数可以放在 BindingResult 后面
            HttpSession session) {

        // 校验是否有错误
        if (result.hasErrors()) {
            // 获取所有错误信息并返回
            String errors = result.getAllErrors()
                    .stream()
                    .map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining(", "));
            return "校验失败:" + errors;
        }

        // 业务逻辑(只有校验通过才会执行到这里)
        userService.register(user);
        session.setAttribute("userId", user.getId());
        return "注册成功";
    }
}

错误代码

===

java 复制代码
@PostMapping("/register")
public String register(
        @Valid @RequestBody User user,
        // 错误:中间插入了 HttpSession 参数
        HttpSession session,      // ← 这里插入了其他参数,打断了顺序
        BindingResult result) {   // ← 没有紧跟被校验对象

    // 即使这里有 if(result.hasErrors()),也永远不会执行到这里
    if (result.hasErrors()) {
        return "校验失败";
    }
    // 业务逻辑...
    return "注册成功";
}

===

相关推荐
兰令水9 小时前
hot100【acm版】【2026.7.18打卡-java版本】
java·开发语言·算法
CoderYanger9 小时前
A.每日一题:3020. 子集中元素的最大数量
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
wear工程师10 小时前
CompletableFuture 的 allOf 到底怎么收结果?面试别只说并行
java·后端
倒流时光三十年10 小时前
Logback 系列(3):三大核心组件 Logger / Appender / Encoder
java·开发语言·logback
什巳10 小时前
JAVA练习312- 二叉搜索树中第 K 小的元素
java·数据结构·算法·leetcode
倒流时光三十年11 小时前
Logback 系列(7):常用 Appender(控制台 / 文件 / 滚动文件)
java·前端·logback
极客先躯11 小时前
高级java每日一道面试题-2026年04月18日-实战篇[Docker]-如何处理金融行业的时序数据容器化?
java·运维·docker·容器·金融·时序数据·高级面试
hdsoft_huge11 小时前
SpringBoot系列18:SpringSecurity登录鉴权,JWT无状态Token认证完整流程(生产级落地)
java·spring boot·后端
野蛮人6号11 小时前
黑马天机学堂系列问题之选集8本地服务报错
java·spring cloud·黑马程序员·天机学堂·黑马天机学堂