【笔记】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() 时,数据最终会被放入 HttpServletRequest 的 attributes 属性域中。因此,它的作用域是 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. Pageable 和 Sort 需要引入 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 "注册成功";
}

===

相关推荐
程序猿乐锅14 小时前
从0-1一文详解RabbitMQ
java·分布式·后端·中间件·rabbitmq·ruby
考虑考虑17 小时前
JDK26中的List.ofLazy()
java·后端·java ee
小蒜学长17 小时前
基于SpringBoot的公寓报修管理系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·公寓报修管理系统·多角色协同
for_ever_love__17 小时前
MySQL 主从复制讲透:binlog 原理、搭建步骤与读写分离
java·数据库·mysql·binlog·读写分离·原理·主从复制
小π军20 小时前
操作系统面试题
java·linux·服务器
倔强的石头10620 小时前
应用账号最小权限实践:读写账号、报表账号、运维账号分层
java·运维·开发语言
Shaoshing20 小时前
ThreadLocal
java·jvm·threadlocal
写后端的胖头鱼20 小时前
一文详解CAS
java·jvm·spring·cas·乐观锁·自旋
鱼宵21 小时前
Spring AI 提示词模板:{变量} 参数化 + few-shot,一条提示词反复用
java·人工智能·spring·few-shot·提示词工程·springai