从零开始,5 分钟写出你的第一个 Web 接口!
你的外卖店要接单、做饭、送餐。如果你一个人全干——既接电话、又炒菜、又送餐——效率很低。
于是你把工作分成三个角色:
SpringMVC 就是帮你管理这三个角色的"店长"!它自动帮你:接单 → 派给厨师 → 打包返回。
SpringMVC 是 Spring 框架中负责处理 Web 请求的模块。MVC 代表:
传统 SpringMVC 需要配置 web.xml、XML 配置文件等一堆东西。但有了 Spring Boot,这些全部自动搞定!我们直接用 Spring Boot 方式学习,省去 80% 的配置烦恼。
当你在浏览器输入 http://localhost:8080/hello 按回车,发生了什么?
👇 点击按钮模拟一次请求的完整流程
| DispatcherServlet | 前端总控制器,所有请求都先到它这里,相当于"前台总管" |
| HandlerMapping | 查找"这个 URL 该交给哪个 Controller 的哪个方法处理" |
| Controller | 你写的代码!处理请求、调用业务逻辑、返回结果 |
浏览器发请求 → DispatcherServlet 接收 → 找到对应的 Controller 方法 → 执行方法 → 返回结果给浏览器。
我们用 Spring Boot 方式创建项目,5 分钟就能跑起来!
打开 IDEA → File → New → Project → Spring Initializr
com.examplespringmvc-demo17点 Create,等下载完就行。
<!-- pom.xml 关键依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>spring-boot-starter-web 自动帮你引入了 SpringMVC、内嵌 Tomcat、JSON 处理(Jackson)等所有东西。不用再手动配 web.xml、不用手动配 DispatcherServlet!
在 com.example.springmvcdemo 包下新建 controller 包,然后创建:
// 📄 HelloController.java — 你的第一个控制器
package com.example.springmvcdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
// @RestController = @Controller + @ResponseBody
// 告诉 Spring:这个类是控制器,方法返回值直接作为 HTTP 响应体(不是视图名)
@RestController
public class HelloController {
// @GetMapping("/hello"): 当收到 GET /hello 请求时,执行这个方法
// 访问: http://localhost:8080/hello
@GetMapping("/hello")
public String hello() {
// 返回的字符串会直接显示在浏览器中
return "Hello, SpringMVC! 🎉 你的第一个接口成功了!";
}
}右键 SpringmvcDemoApplication.java → Run
看到控制台输出:
Tomcat started on port(s): 8080
Started SpringmvcDemoApplication in 2.3 seconds打开浏览器,输入:http://localhost:8080/hello
你会看到:Hello, SpringMVC! 🎉 你的第一个接口成功了!
只写了 1 个类 + 1 个方法 + 2 个注解,就创建了一个 Web 接口!
@RestController → 告诉 Spring:"我是一个处理请求的控制器"@GetMapping("/hello") → 告诉 Spring:"当收到 GET /hello 请求时,执行我"返回视图名称(HTML 页面)
@Controller
public class PageController {
@GetMapping("/page")
public String page() {
return "hello";
// → 找 hello.html 模板
}
}返回数据(JSON/文本)
@RestController
public class ApiController {
@GetMapping("/api")
public String api() {
return "hello";
// → 直接返回 "hello" 文本
}
}做前后端分离项目(99%的现代项目),用 @RestController。它等于 @Controller + @ResponseBody。
// @RequestMapping 放在类上:统一前缀,这个类所有接口 URL 都以 /user 开头
@RestController
@RequestMapping("/user")
public class UserController {
// GET /user/list → 查询操作(获取数据)
@GetMapping("/list")
public String list() { return "查询用户列表"; }
// POST /user/add → 新增操作(提交新数据)
@PostMapping("/add")
public String add() { return "新增用户"; }
// PUT /user/update → 修改操作(更新已有数据)
@PutMapping("/update")
public String update() { return "修改用户"; }
// DELETE /user/delete → 删除操作(移除数据)
@DeleteMapping("/delete")
public String delete() { return "删除用户"; }
}// @PathVariable: 从 URL 路径中提取变量值
// {id} 是占位符,实际值会自动注入到方法参数中
// URL: /user/123 → id = 123
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return "查询用户,id = " + id; // → "查询用户,id = 123"
}
// 多个路径变量: URL: /user/123/orders/456
// → userId = 123, orderId = 456
@GetMapping("/user/{userId}/orders/{orderId}")
public String getOrder(@PathVariable Long userId,
@PathVariable Long orderId) {
return "用户" + userId + "的订单" + orderId;
// → "用户123的订单456"
}// @RequestParam: 从 URL 查询参数(?后面的部分)中取值
// URL: /search?name=张三&age=20
@GetMapping("/search")
public String search(
@RequestParam String name, // 必传参数
@RequestParam(required = false) Integer age) { // 可选参数(不传则为 null)
return "搜索:" + name + ", 年龄:" + age;
// → "搜索:张三, 年龄:20"
}
// URL: /list 或 /list?page=3
@GetMapping("/list")
public String list(
@RequestParam(defaultValue = "1") int page) { // 有默认值,不传则用默认值
return "第 " + page + " 页"; // 不传 page 时返回 "第 1 页"
}输入一个 URL,看看 SpringMVC 怎么解析它
真实项目中,接口不会只返回字符串,而是返回 JSON 对象。SpringMVC + Jackson 帮你自动搞定!
// 📄 User.java — 用户实体类(POJO)
package com.example.springmvcdemo.entity;
// POJO = Plain Old Java Object(普通 Java 对象)
// Jackson 会自动把这个对象转成 JSON:{"id":1,"name":"张三","age":20}
public class User {
private Long id; // 用户 ID
private String name; // 用户名
private Integer age; // 年龄
// 构造方法(方便创建对象)
public User(Long id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// Getter / Setter(Jackson 需要这些方法来转 JSON)
// IDEA 快捷键: Alt+Insert → Getter and Setter 自动生成
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}// 📄 UserController.java — 返回 JSON 的用户接口
package com.example.springmvcdemo.controller;
import com.example.springmvcdemo.entity.User;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController // 控制器,返回值自动转 JSON
@RequestMapping("/user") // 统一前缀: /user
public class UserController {
// 模拟数据库(实际项目会用 MyBatis/JPA 查数据库)
private List<User> users = new ArrayList<>(Arrays.asList(
new User(1L, "张三", 20),
new User(2L, "李四", 25),
new User(3L, "王五", 30)
));
// GET /user/list → 返回所有用户
// 返回 List → Jackson 自动转成 JSON 数组
@GetMapping("/list")
public List<User> list() {
return users; // [{"id":1,"name":"张三",...}, ...]
}
// GET /user/1 → 返回单个用户
// 返回 User 对象 → Jackson 自动转成 JSON 对象
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return users.stream() // 从列表中查找
.filter(u -> u.getId().equals(id)) // 过滤: id 相等
.findFirst() // 取第一个
.orElse(null); // 没找到返回 null
}
// GET /user/search?name=张 → 按名字模糊搜索
@GetMapping("/search")
public List<User> search(@RequestParam String name) {
return users.stream() // 从列表中查找
.filter(u -> u.getName().contains(name)) // 过滤: 名字包含搜索词
.toList(); // 收集结果为 List
}
}打开浏览器访问以下地址:
// GET /user/list 返回:
[
{"id": 1, "name": "张三", "age": 20},
{"id": 2, "name": "李四", "age": 25},
{"id": 3, "name": "王五", "age": 30}
]
// GET /user/1 返回:
{"id": 1, "name": "张三", "age": 20}
// GET /user/search?name=张 返回:
[{"id": 1, "name": "张三", "age": 20}]你只是返回了一个 Java 对象(User),SpringMVC 就自动帮你转成了 JSON!
背后是 Jackson 库在工作:Java 对象 → JSON 字符串,全自动,你什么都不用配。
/user/42,怎么在方法参数中拿到 42 这个值?spring-boot-starter-web 依赖搞定一切@RestController 标记控制器,返回值直接作为响应(JSON/文本)@GetMapping / @PostMapping 等映射 HTTP 请求到方法@PathVariable 从路径取值 /user/{id}@RequestParam 从查询参数取值 ?name=张三