
当你在深夜打开IDE准备开始学习SpringBoot时十有八九已经厌倦了SSHStrutsSpringHibernate那套繁琐的XML配置更不想在Maven依赖的海洋里捞针。这一刻你需要一点“开箱即用”的爽感。请记住SpringBoot设计的终极目标就是让你用最少的代码跑通一个能用的系统。REST API就是最佳的第一课。它干净、无状态、用HTTP动词表达意图完美契合现代前后端分离的架构。今天我们不是来背诵官方文档的而是像一个黑客一样从零开始在你的本地机器上制造出第一个真正能接收请求、返回数据的RESTful端点。别急着复制粘贴先问自己一个问题我们希望这个API做什么对初学者而言最简单的场景就是客户端发送一个GET请求到/api/greeting服务器返回一段JSON数据比如{“id”:1,“content”:“Hello, World!”}。如果加上参数则能返回个性化问候。这就是RESTAPI的灵魂——资源导向。第一部分开荒——环境与骨架所有伟大的旅程都始于一个干净的工作目录。你需要的不是Eclipse的巨无霸安装包而是三样东西JDK 1.8、Maven或Gradle但这里推荐Maven因为它的生态成熟度在SpringBoot中表现最好和一款趁手的IDEIntelliJ IDEA社区版足够。打开浏览器访问 start.spring.io——这是SpringBoot的“出生地”一个比任何XML模板都优雅百倍的脚手架生成器。选择Maven工程、Java版本在依赖栏里搜索并勾选“Spring Web”。这是整个项目的核心依赖它内嵌了Tomcat服务器和Spring MVC让你无需部署直接运行。点击“Generate”下载压缩包解压。如何判断你拿到了真正的“神装”而不是一堆垃圾检查你的pom.xml。如果里面的spring-boot-starter-parent版本是最新的稳定版而且没有多余的dependency说明你走在了正确的路上。这个starter-parent锁定了数千个依赖的兼容版本彻底终结了“jar包地狱”的噩梦。现在打开你生成的src/main/java下的主类文件默认名称类似DemoApplication.java。里面只有一行核心代码SpringApplication.run(DemoApplication.class, args);。这就是魔法所在一个普通的main方法就能启动一个内嵌Web服务器处理来自外界的HTTP请求。运行它你会看到控制台输出一个巨大的Spring Boot Banner然后日志显示Tomcat started on port(s): 8080。恭喜你的第一个SpringBoot应用已经活了。第二部分握拳——构建第一个控制器有了活着的服务器还需要一个“耳朵”来听外面的声音。在Java中这个“耳朵”叫Controller。在你的主类同级目录下新建一个包controller虽然这不是强制的但命名规范本身就是一种生产力。在里面创建一个名为GreetingController.java的类。注意RESTAPI的设计哲学是面向资源不是面向动作。你的控制器命名应该是名词复数比如GreetingController、UserController、OrderController而不是GetGreetingController。这能让你在复杂业务中保持头脑清醒。写入以下代码前请先理解两个核心注解RestController它结合了Controller和ResponseBody。意味着这个类的每个方法返回的对象都会被自动序列化为JSON并写入HTTP响应体。RequestMapping这是路由的管家。定义方法应该响应对应哪个URL和HTTP方法。记住永远不要在Controller里写业务逻辑。Controller的工作只有三件接收参数、调用服务、返回结果。违背这一点你的代码将在两周后变成一团乱麻。下面实现一个简单到令人发指的GET端点package com.example.demo.controller; import org.springframework.web.bind.annotation.; import java.util.concurrent.atomic.AtomicLong; RestController public class GreetingController { private static final String TEMPLATE Hello, %s!; private final AtomicLong counter new AtomicLong(); // 标书核心GetMapping 是 RequestMapping(method GET)的缩写 GetMapping(/api/greeting) public Greeting greeting(RequestParam(value name, defaultValue World) String name) { // 注意这里直接new对象返回SpringBoot自动处理JSON序列化 return new Greeting(counter.incrementAndGet(), String.format(TEMPLATE, name)); } // 内部静态类代表返回的资源对象 public static class Greeting { private final long id; private final String content; public Greeting(long id, String content) { this.id id; this.content content; } public long getId() { return id; } public String getContent() { return content; } } }一个致命的错误是忘记提供getter方法。SpringBoot默认使用Jackson库进行JSON序列化它会查找类的公共getter方法。如果你的Greeting类没有getId()和getContent()浏览器会返回一个空对象{}不会报错但会让你怀疑人生。这就是SpringBoot的“静谧失败”设计它不抛出异常只是默默给你最坏的结果。现在重新运行你的main方法。打开浏览器访问http://localhost:8080/api/greeting。你应该能看到{id:1,content:Hello, World!}。然后访问http://localhost:8080/api/greeting?nameSpringBoot响应变成了{id:2,content:Hello, SpringBoot!}。每刷新一次页面ID都会增加。这不仅证明了API正常工作还演示了无状态HTTP如何通过请求参数驱动资源变化。这个counter是static的意味着每次请求都会访问同一个计数器这在实际生产环境要慎用但对于入门演示它清楚展示了服务端状态。第三部分深入——理解请求与响应很多新手以为RESTAPI就是返回JSON这是大错特错的。真正的API设计师会像雕刻家一样精确控制每一个HTTP状态码、请求头和响应头。上面的例子虽然可以跑但违背了REST的一个核心原则使用正确的HTTP方法表达语义。你创建了一个资源理论上也应该允许客户端去“创建”它。为了演示我们再加一个POST方法。修改GreetingController添加一个POST端点// 额外添加一个POST端点用来“创建”一个问候模拟 PostMapping(/api/greeting) public Greeting createGreeting(RequestBody GreetingRequest request) { // 在实际业务中这里会调用Service保存到数据库 // 这里只是演示如何接收JSON请求体 Greeting greeting new Greeting(counter.incrementAndGet(), You sent: request.getMessage()); return greeting; } // 需要一个新的内部类或独立类来接收请求体 public static class GreetingRequest { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message message; } }注意关键点PostMapping表明这是一个POST请求用于创建资源。不应该用PUT或PATCH来做创建。RequestBody告诉Spring将HTTP请求体的JSON内容反序列化成GreetingRequest对象。GreetingRequest必须有一个无参构造器由JVM隐式提供和setter/getter。现在测试你的POST端点。用Postman或curlcurl -X POST http://localhost:8080/api/greeting \ -H Content-Type: application/json \ -d {message:Hello from POST}你会得到{id:3,content:You sent: Hello from POST}这里揭示了一个关键原则请求和响应应该使用不同的模型。GreetingResponse也就是我们原来的Greeting和GreetingRequest应该分离。虽然现在它们看起来很像但公司级的API中请求体通常不需要id字段因为ID由服务端生成而响应体需要提供。混淆模型是所有烂API的通病务必从第一天起就遵守这个规范。第四部分测试——不止是看看浏览器对于专业开发者运行程序后打开浏览器手动点击这绝对不是“测试”而是“意淫”。你应该用单元测试来确保API的行为。在src/test/java目录下Spring Initializr已经为你生成了一个空的测试类。你需要引入一个新的依赖spring-boot-starter-test通常已经在了但如果没有手动添加。我们使用MockMvc来模拟HTTP请求而不需要实际启动服务器或者启动一个轻量级的服务器。测试的价值在于它把你的API规范变成了可执行的契约。只要测试通过你的API行为就是可靠的。重写或重构代码后运行测试如果红了说明你把API搞坏了。创建GreetingControllerTest.javapackage com.example.demo.controller; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.; WebMvcTest(GreetingController.class) // 只测试这个Controller public class GreetingControllerTest { Autowired private MockMvc mockMvc; Test public void testGetGreeting() throws Exception { mockMvc.perform(get(/api/greeting)) // 发起GET请求 .andExpect(status().isOk()) // 期待状态码200 .andExpect(jsonPath($.content).value(Hello, World!)); // 检查响应JSON的content字段 } Test public void testGetGreetingWithName() throws Exception { mockMvc.perform(get(/api/greeting).param(name, SpringBoot)) .andExpect(status().isOk()) .andExpect(jsonPath($.content).value(Hello, SpringBoot!)); } Test public void testCreateGreeting() throws Exception { String jsonRequest {\message\:\Test\}; mockMvc.perform(post(/api/greeting) .contentType(application/json) // 必须指定Content-Type .content(jsonRequest)) .andExpect(status().isOk()) .andExpect(jsonPath($.content).value(You sent: Test)); } }运行这些测试看到绿色通过的那一刻你才算真正“搭建”了第一个RESTAPI。如果你看到红色别慌。检查你的Controller方法签名是否匹配。jsonPath是一个类似XPath的表达式它可以方便地检查JSON的深层结构。没有测试的API就像没有保险的跑车。也许它现在跑的很快但一旦翻车你将付出惨痛代价。第五部分发布与总结——从本地到世界当你完成了开发、测试下一步是让它运行在一个开放环境中。SpringBoot应用可以被打包成可执行的JAR包。在项目根目录下运行mvn clean package你会看到target/目录下生成一个demo-0.0.1-SNAPSHOT.jar文件。这个文件包含了所有依赖、内嵌Tomcat和你的代码。你可以把它放在任何有JDK的机器上通过java -jar target/demo-0.0.1-SNAPSHOT.jar命令直接启动。这就是所谓的“自包含部署”完全不需要配置外部Web服务器。这个JAR包就是你整个产品的实体。你可以把它交给运维部署到Kubernetes集群或者通过Docker容器化后直接扔到云上。SpringBoot消除了开发和部署环境的差异这是它横扫业界的最根本原因。回顾我们走过的路从零搭建没有一行XML配置没有Tomcat安装包。定义了资源Greeting对象通过GET和POST两种HTTP方法表达不同的业务意图。规范了请求和响应使用不同的Java类分离请求模型和响应模型。可测试的代码使用MockMvc编写了契约性测试。可部署的产物一个几百KB的JAR包。现在请回顾你最开始的目标从零搭建第一个RESTAPI。你不仅做完了而且做对了。你的API不是那种随便拼凑出来的demo而是一个具备基本工程规范的微服务雏形。最后给你一个超越本教程建议不要急着学数据库。在学会RESTAPI的本质之前追求ORM框架、事务管理、复杂查询会让你陷入另一个泥潭。先成为一个API工匠打磨你对HTTP的理解对资源的定义对对象的序列化。当你能闭着眼睛设计出精良的REST端点时再接入数据库你会发现后者的难度远远小于前者。去创建一个你自己的文件夹把今天学的代码放进去。然后开始修改它。尝试加入DELETE方法加入PUT方法。试着返回一个包含数组的JSON响应。真正掌握一个工具的秘诀不是看完了文章而是删掉示例代码凭记忆和逻辑把它重新写出来。如果你能做到恭喜你已经正式迈入了SpringBoot开发的大门。永远记住API是你的产品与世界的对话窗口。你今天写的每一行代码都在定义这个对话的优雅程度。