大家好,今天我们来详细拆解SpringMVC中的响应机制,从页面跳转、文本返回到JSON数据交互,覆盖传统服务端渲染 和前后端分离两种主流场景,附完整代码实战,帮你彻底搞懂SpringMVC响应的核心原理!
一、SpringMVC响应的两种核心形式
SpringMVC处理完用户请求和数据后,需要将结果返回给用户,常见场景如:根据用户ID查询信息、查询用户列表、新增用户等。响应主要分为两大类:
- 响应页面(传统服务端渲染)
- 响应数据(文本数据、JSON数据,异步调用主流方案)
1. 响应页面(传统服务端渲染模式)
核心逻辑 :后端直接返回完整的HTML页面(或包含动态内容的模板页面),浏览器拿到后可直接渲染展示,无需前端额外处理。
典型场景 :使用JSP、Thymeleaf、Freemarker等模板引擎时,后端控制器(@Controller)方法返回视图名,由视图解析器拼接路径找到页面文件,填充数据后返回完整HTML。
代码示例:
@Controller
public class UserController {
@GetMapping("/user/list")
public String list(Model model) {
// 模拟从数据库查询用户数据
List<User> userList = userService.findAll();
// 将数据存入Model,传递给页面模板
model.addAttribute("users", userList);
// 返回视图名,由视图解析器匹配对应页面(如 user/list.html)
return "user/list";
}
}
浏览器访问 /user/list 时,后端返回已经填充好数据的HTML页面,浏览器直接渲染展示表格、列表等内容,适合传统服务端渲染架构。
2. 响应数据(前后端分离模式)
核心逻辑 :后端不返回完整页面,而是返回纯数据(通常是JSON格式),由前端(Vue、React等项目)拿到数据后,自主渲染页面。
典型场景 :使用 @ResponseBody 或 @RestController 时,方法返回的对象会被自动序列化为JSON,供前端AJAX调用。
代码示例:
@RestController // 等价于 @Controller + @ResponseBody,所有方法自动返回JSON
public class ApiController {
@GetMapping("/api/user")
public User getUser() {
// 返回User对象,自动序列化为JSON:{"id":1,"name":"Tom"}
return new User(1, "Tom");
}
}
前端通过AJAX调用 /api/user 拿到JSON数据后,用JavaScript动态渲染页面,是前后端分离项目的标准方案。
3. 本质区别与适用场景
| 对比项 | 响应页面 | 响应数据 |
|---|---|---|
| 返回内容 | 完整HTML(含动态内容+静态结构) | 纯数据(JSON/XML等,无页面结构) |
| 渲染责任 | 后端(模板引擎填充数据) | 前端(JS动态渲染) |
| 典型架构 | 服务端渲染(SSR) | 前后端分离 |
| 适用场景 | 传统网站、需要SEO优化的页面 | 单页应用(SPA)、移动端接口 |
4. 一句话总结
- 响应页面:后端直接给前端「成品页面」,浏览器拿到就能显示。
- 响应数据:后端只给前端「原材料(数据)」,前端自己决定怎么把数据变成页面。
实际项目中通常结合两种模式:关键页面用服务端渲染做SEO,交互页面用前后端分离提升开发效率。
二、环境准备
我们先搭建一个完整的SpringMVC Web项目,为后续演示做准备。
1. pom.xml添加核心依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>springmvc_05_response</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- SpringMVC核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Jackson:JSON序列化依赖(必须,用于对象转JSON) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Tomcat7插件,用于本地启动测试 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. SpringMVC配置类
Servlet容器初始化配置:
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 处理中文乱码
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
SpringMVC核心配置:
@Configuration
@ComponentScan("com.itheima.controller")
// 开启SpringMVC高级功能,包含JSON数据自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
3. 实体类与页面
User实体类:
public class User {
private String name;
private int age;
// 必须提供getter/setter,否则Jackson无法序列化
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
测试JSP页面:
<html>
<body>
<h2>Hello Spring MVC!</h2>
</body>
</html>
三、响应页面(传统服务端渲染实战)
@Controller
public class UserController {
@RequestMapping("/toJumpPage")
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
}
}
访问地址:http://localhost/toJumpPage,即可渲染页面。
四、返回文本数据
@Controller
public class UserController {
@RequestMapping("/toText")
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
}
}
访问地址:http://localhost/toText,直接返回纯文本。
五、响应JSON数据(前后端分离核心)
1. 响应POJO对象
@Controller
public class UserController {
@RequestMapping("/toJsonPOJO")
@ResponseBody
public User toJsonPOJO(){
User user = new User();
user.setName("itcast");
user.setAge(15);
return user;
}
}
返回结果:
{"name":"itcast","age":15}
2. 响应集合对象
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
List<User> userList = new ArrayList<>();
userList.add(new User("传智播客",15));
userList.add(new User("黑马程序员",12));
return userList;
}
}
六、核心注解:@ResponseBody 详解
| 名称 | @ResponseBody |
| 作用 | 将返回值作为HTTP响应体,不跳转页面 |
| 等价注解 | @RestController = @Controller + @ResponseBody |
|---|
说明
- 该注解可以写在类上或者方法上
- 写在类上就是该类下的所有方法都有
@ResponseBody功能 - 当方法上有
@ResponseBody注解后- 方法的返回值为字符串,会将其作为文本内容直接响应给前端
- 方法的返回值为对象,会将对象转换成JSON响应给前端
此处又使用到了类型转换,内部还是通过Converter接口的实现类完成的,所以Converter除了前面所说的功能外,它还可以实现:
- 对象转Json数据(POJO -> json)
- 集合转Json数据(Collection -> json)
七、总结
- 响应页面:后端渲染HTML,适合传统网站、SEO场景;
- 响应数据:后端返回JSON,前后端分离标准方案;
- JSON转换:依赖Jackson,通过@ResponseBody+@EnableWebMvc自动完成;