Spring Web MVC(1)

一、Spring MVC 是什么?

核心角色 :Spring MVC 是⼀套基于 Servlet 规范 的Web开发框架,像餐厅的标准化管理流程,规定了每个环节的职责。用户发起请求(点餐)时,Spring MVC协调各组件处理并响应结果(上菜)。

二、MVC模式深度解析

类比餐厅模型

角色 职责 对应Spring组件
顾客(用户) 发起请求(点菜) 浏览器用户
服务员(View) 展示菜单并上菜(显示结果) JSP/Thymeleaf模板
前厅经理(Controller) 接收订单并分发给厨房,确保流程顺畅 @Controller注解的类
厨师(Model) 处理菜品制作(数据操作、业务逻辑) Service层、DAO层

代码流程示例

java 复制代码
@RestController
public class OrderController {
    @RequestMapping("/order")
    public String placeOrder(@RequestParam String dish) {
        // Service层处理业务(模拟订单处理)
        String result = kitchenService.cookDish(dish);
        return "您的 " + result + " 已准备好!";
    }
}

访问http://localhost:8080/greet → 显示 Hello, Spring MVC!

访问流程

用户访问 http://localhost:8080/order?dish=牛排 → Controller接收参数 → 调用Service处理 → 返回结果。

代码映射:用户访问URL → Controller接收 → Model处理 → View返回结果。

三、核心注解与请求处理

1. @RequestMapping:路由映射的"菜单本"
核心作用
  • URL路由匹配:将HTTP请求的URL路径映射到指定的控制器方法。
  • 方法类型指定:定义支持的HTTP方法(GET、POST、PUT、DELETE等)。
  • 请求头/参数限制:通过附加条件(如请求头、参数等)细化路由匹配规则。
主要属性
属性 类型 说明
value String[] 指定URL路径(可多个路径映射同一方法)。
method RequestMethod[] 限制请求方法(如RequestMethod.GETRequestMethod.POST)。
params String[] 要求请求必须包含某些参数或参数值(如"name=John")。
headers String[] 要求请求头中必须包含指定内容(如"Content-Type=application/json")。
使用示例
基本路由
java 复制代码
@RestController
@RequestMapping("/api")
public class ApiController {

    // 匹配 GET /api/hello
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String sayHello() {
        return "Hello, Spring!";
    }

    // 匹配 POST /api/user,且要求Content-Type为application/json
    @RequestMapping(
        value = "/user",
        method = RequestMethod.POST,
        headers = "Content-Type=application/json"
    )
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
}

多路径映射

java 复制代码
// 匹配 GET /api/book 或 /api/books
@RequestMapping(value = {"/book", "/books"}, method = RequestMethod.GET)
public List<Book> listBooks() {
    return bookService.findAll();
}
2.. @RequestParam:处理查询参数

场景 :从URL的问号后获取参数(如 /user?name=John&age=20)。

示例代码

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

    // 获取单个(必须有name参数)
    @GetMapping("/detail")
    public String getUserDetail(@RequestParam String name) {
        return "用户名称: " + name;
    }

    // 参数别名、默认值(可无age参数)
    @GetMapping("/age")
    public String getUserAge(
            @RequestParam(value = "userAge", required = false, defaultValue = "18") Integer age) {
        return "用户年龄: " + age;
    }

    // 接收数组参数(多个相同的键)
    @GetMapping("/hobbies")
    public String getHobbies(@RequestParam List<String> hobbies) {
        return "用户爱好: " + hobbies;
    }
}

请求示例

  • 必须参数GET /user/detail?name=John → 返回 用户名称: John
  • 可选参数GET /user/age → 返回 用户年龄: 18(使用默认值)
  • 数组参数GET /user/hobbies?hobbies=编程&hobbies=音乐 → 返回 用户爱好: [编程, 音乐]
3. @PathVariable:获取URL路径参数

场景 :用于RESTful风格URL中标识资源(如 /user/1001 中的用户ID)。

示例代码

java 复制代码
@RestController
@RequestMapping("/product")
public class ProductController {

    // 单一路径参数
    @GetMapping("/{id}")
    public String getProduct(@PathVariable Long id) {
        return "产品ID: " + id;
    }

    // 多路径参数与别名
    @GetMapping("/{category}/{sku}")
    public String getProductByCategoryAndSku(
            @PathVariable("category") String productCategory,
            @PathVariable String sku) {
        return "分类: " + productCategory + ", SKU编码: " + sku;
    }
}
4. @RequestBody:接收JSON请求体

场景:处理POST/PUT请求中的复杂数据(如用户注册、订单提交)。

示例代码

java 复制代码
@RestController
@RequestMapping("/order")
public class OrderController {

    // 接收JSON对象并转为Java对象
    @PostMapping("/create")
    public Order createOrder(@RequestBody Order order) {
        // 假设处理订单保存逻辑
        order.setStatus("已创建");
        return order;
    }
}

// 订单类(模型)
public class Order {
    private Long id;
    private String productName;
    private Integer quantity;
    private String status;
    // 省略Getter/Setter
}

请求示例(Postman)

  • URLPOST /order/create
  • HeadersContent-Type: application/json
  • Body(JSON)
java 复制代码
{
    "productName": "笔记本电脑",
    "quantity": 1
}

响应

java 复制代码
{
    "id": null,
    "productName": "笔记本电脑",
    "quantity": 1,
    "status": "已创建"
}

5 .@RequestPart:文件上传与多部分请求处理

核心作用

文件上传处理 :接收HTTP多部分(multipart/form-data)请求中的文件或其他分块数据。

绑定参数 :将上传的文件或其他表单字段映射到方法参数(如MultipartFile对象)

主要属性

属性 类型 说明
value String 指定表单字段的名称(对应HTML中的name属性)。
required boolean 是否为必传字段(默认为true)。
3. 使用示例
单文件上传
java 复制代码
@PostMapping("/upload")
public String uploadFile(@RequestPart("file") MultipartFile file) {
    String fileName = file.getOriginalFilename();
    try {
        file.transferTo(new File("D:/uploads/" + fileName));
        return "文件上传成功:" + fileName;
    } catch (IOException e) {
        return "文件上传失败:" + e.getMessage();
    }
}

Postman测试

  • 请求方式POST /upload
  • HeadersContent-Type: multipart/form-data
  • Body :选择form-data,设置Key为file(类型为File),上传文件。

多文件上传

java 复制代码
@PostMapping("/upload-multi")
public String uploadFiles(@RequestPart("files") List<MultipartFile> files) {
    StringBuilder result = new StringBuilder("上传成功文件:");
    for (MultipartFile file : files) {
        if (!file.isEmpty()) {
            result.append(file.getOriginalFilename()).append(", ");
        }
    }
    return result.toString();
}

Postman测试

Body :设置多个Key为filesFile字段,选择不同文件。

混合表单参数与文件上传

java 复制代码
@PostMapping("/user-profile")
public String updateProfile(
    @RequestPart("avatar") MultipartFile avatar,
    @RequestPart("username") String username,
    @RequestPart("bio") String bio
) {
    return String.format(
        "用户信息更新:头像=%s, 用户名=%s, 简介=%s",
        avatar.getOriginalFilename(),
        username,
        bio
    );
}

Postman测试

  • Body
    • avatar:上传图片文件。
    • username:填文字(如John)。
    • bio:填文字(如Java开发者

核心区别总结

对比维度 @RequestParam @PathVariable @RequestBody
参数位置 URL查询字符串(?name=John URL路径(/user/{id} 请求体(HTTP Body)
常见数据格式 字符串、基础类型 字符串、基础类型 JSON/XML(复杂对象)
是否必传 默认为是(可设required=false 是(路径必须包含变量) 是(除非允许空Body)
典型应用 过滤条件、分页参数 RESTful资源标识 创建/更新资源(如用户信息)
注解 典型场景 数据格式 常见参数类型
@RequestMapping 定义所有HTTP方法的请求处理入口 无限制(可结合其他注解处理) 无要求(通常结合其他注解)
@RequestPart 处理文件上传或混合表单数据(multipart/form-data 文件、文本字段混合 MultipartFileString

四、常见问题与注意事项

  1. @RequestParam 默认必传

    • 若未传递参数,会抛出 400 Bad Request,可通过设置 required=false 避免。
  2. @PathVariable 路径变量类型

    • URL路径中的变量默认为字符串,Spring会自动转换为基础类型(如Integer、Long)。
  3. @RequestBody 仅支持POST/PUT

    • GET请求无法携带请求体,需使用其他方式传递数据。
  4. 处理多值参数(数组/集合)

    • @RequestParam 可直接绑定到 List<String>,但需重复键名(如 ?hobbies=编程&hobbies=音乐)。
  5. 参数名称匹配

    • @PathVariable 若参数名与路径变量名一致,可省略 value 属性。
  6. @RequestMapping :Spring MVC的路由核心,定义请求的入口和规则。

  7. @RequestPart :处理文件上传和复杂表单字段的专用注解。

  8. 组合使用 :多数情况下,@RequestMapping搭配其他注解(如@RequestParam@RequestBody@RequestPart)实现完整功能。

相关推荐
devlei4 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
pshdhx_albert4 小时前
AI agent实现打字机效果
java·http·ai编程
沉鱼.445 小时前
第十二届题目
java·前端·算法
努力的小郑5 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
赫瑞6 小时前
数据结构中的排列组合 —— Java实现
java·开发语言·数据结构
Victor3566 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3566 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁6 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp6 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
周末也要写八哥7 小时前
多进程和多线程的特点和区别
java·开发语言·jvm