spring basic
@RestController
@RestController 是 @Controller 与 @ResponseBody 的组合注解,用于编写 RESTful API:控制器方法的返回值会直接写入 HTTP 响应体(通常是 JSON),而不是交给视图解析器去渲染页面。
@RestController
@RequestMapping("/api/comments")
public class CommentController {
@GetMapping("/{id}")
public Comment get(@PathVariable long id) {
return commentService.findById(id);
}
}
上例中,Comment 对象会被 HttpMessageConverter(如 Jackson)序列化为 JSON 返回给客户端。
适用场景:
- 前后端分离:Vue、React、移动端等通过 HTTP 调用后端接口
- 微服务之间的 HTTP 调用
- 任何「请求数据 → 返回 JSON/XML」的 API
不适用场景:
- 传统的服务端渲染 Web 应用(JSP、Thymeleaf 等):这类应用需要
@Controller返回视图名或ModelAndView,由视图解析器渲染 HTML 页面
@Controller
public class PageController {
@GetMapping("/home")
public String home(Model model) {
model.addAttribute("title", "Home");
return "home"; // 解析为 home.jsp 或 templates/home.html
}
}
若把 JSP/Thymeleaf 页面控制器写成 @RestController,返回值会被当作响应体内容(例如字符串 "home" 会原样输出),而不会走视图解析,页面无法正常渲染。
| 注解 | 返回值处理 | 典型用途 |
|---|---|---|
@Controller |
默认解析为视图名;方法上加 @ResponseBody 时才写入响应体 |
MVC 页面、混合应用 |
@RestController |
每个方法等价于带 @ResponseBody |
RESTful API |
同样是 GET,浏览器和 fetch 怎么处理?
RESTful API 与传统 Web 应用的区别,不是靠浏览器识别服务端用了哪种注解,而是靠 URL 路径、谁在发请求、响应的 Content-Type。
| 场景 | 典型 URL | 谁发请求 | 服务器返回 |
|---|---|---|---|
| 传统 Web | GET /home |
地址栏、<a href> 跳转 |
整页 HTML |
| RESTful API | GET /api/users/1 |
页面内 fetch / axios |
JSON body |
实践中通常用不同路径和不同控制器分开,而不是让前端在同一个 URL 上「猜」返回的是页面还是数据。
地址栏 / 链接(整页导航)
- 浏览器发 GET,默认
Accept里会带text/html,表示偏好 HTML 页面 - 收到响应后,按响应的
Content-Type决定如何展示,不关心服务端是@RestController还是 JSP Content-Type: text/html→ 解析并渲染网页Content-Type: application/json→ 不渲染成页面,通常把 JSON 当文本显示
页面内的 fetch / AJAX
- 由 JS 代码决定如何解析,浏览器不会自动「知道这是 API」
- 返回 JSON 且调用
response.json()→ 正常提取数据 - 返回 HTML(例如误请求了页面 URL,或未登录被重定向到登录页)→ HTTP 可能仍是 200,但
response.json()会在解析阶段报错(SyntaxError) - 生产代码应检查
res.ok和Content-Type,再选择.json()或.text()
Accept 与 Content-Type
| Header | 方向 | 含义 |
|---|---|---|
Accept |
客户端 → 服务端 | 客户端声明能接受 / 更希望收到哪些类型的响应(偏好,服务端可参考也可不采纳) |
Content-Type |
服务端 → 客户端 | 服务端声明响应体实际是什么类型(事实,客户端应按此解析和展示) |
可以记成:一个说「我想要什么」,一个说「我给你的是什么」。理想情况下两者匹配;不匹配时,客户端仍以 Content-Type + body 为准。
# 浏览器打开页面
Accept: text/html,application/xhtml+xml,...
# JS 调 API
Accept: application/json
# 服务端响应
Content-Type: application/json;charset=UTF-8
Content-Type: text/html;charset=UTF-8
Spring 中 @RestController 通常配合 Jackson 返回 application/json;@Controller + 视图解析器通常返回 text/html。这是服务端的实现约定,浏览器只看到 HTTP 响应头与 body。
Content-Type 与 body 不一致时
地址栏整页访问时,浏览器优先相信 Content-Type,不会根据服务端实现方式改变行为:
| Content-Type | 实际 body | 地址栏典型结果 |
|---|---|---|
application/json |
HTML | 不渲染成网页,多半当文本/源码显示 |
text/html |
JSON | 一般不报错,把 JSON 当页面文字显示 |
text/html |
HTML | 正常渲染网页 |
application/json |
JSON | 格式化或原文显示 JSON |
fetch 场景下,若代码假定 JSON 却收到 HTML,会在 response.json() 阶段失败,而不是浏览器拒绝显示。
Spring Shell
Spring Shell 是一个用于构建交互式命令行应用程序的 Spring 框架,让开发者能够快速创建功能丰富的 CLI 工具。
核心特性:
- 注解驱动 - 使用
@ShellComponent和@ShellMethod定义命令 - 自动补全 - Tab 键补全命令和参数
- 命令历史 - 支持历史命令记录和回溯
- 内置帮助 - 自动生成帮助文档
- Spring Boot 集成 - 无缝集成 Spring Boot 生态
典型使用场景:
- 管理工具(部署、监控)
- 数据库客户端
- DevOps 工具
- 微服务管理控制台
简单示例:
@ShellComponent
public class MyCommands {
@ShellMethod("Say hello")
public String hello(@ShellOption String name) {
return "Hello " + name + "!";
}
}
运行后可在交互式 shell 中执行:
shell:> hello --name World
Hello World!