在 SpringMVC 框架中,响应数据 与结果视图是连接后端业务逻辑与前端展示的核心环节。无论是页面跳转、数据传递,还是异步 JSON 交互,都需要通过合理的响应方式实现。本文将从开发环境搭建入手,详细讲解 Controller 方法返回值分类、转发与重定向机制,以及 JSON 异步交互的实现,附带完整代码示例与避坑指南,帮助开发者系统掌握 SpringMVC 响应逻辑。
一、开发环境搭建(基础准备)
在实现响应功能前,需先完成 SpringMVC 基础环境配置,包括 Maven 依赖、Web 组件配置和核心配置文件,确保框架能正常运行。
1. Maven 坐标配置(pom.xml)
核心依赖包括 SpringMVC 核心包、Servlet/JSP 支持包,以及后续 JSON 转换所需的 Jackson 依赖。为避免版本冲突,统一锁定 Spring 版本为 5.0.2.RELEASE。
XML
<properties>
<!-- 统一 Spring 版本 -->
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<!-- 1. Spring 核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 2. Servlet/JSP 依赖(scope=provided:服务器已内置,仅编译时用) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- 3. JSON 转换依赖(后续异步交互用) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
2. Web.xml 配置(核心组件)
Web.xml 需配置两个关键组件:中文乱码过滤器 (解决请求 / 响应乱码)和前端控制器 DispatcherServlet(SpringMVC 入口)。
(1)中文乱码过滤器
拦截所有请求,统一设置编码为 UTF-8,避免中文在传递过程中出现乱码。
XML
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置请求编码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 可选:同时设置响应编码(部分场景需额外配置) -->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- 拦截所有请求 -->
</filter-mapping>
(2)前端控制器 DispatcherServlet
作为 SpringMVC 的核心入口,负责接收所有请求并转发到对应的 Controller。需配置 SpringMVC 配置文件路径,并设置服务器启动时初始化(load-on-startup=1)。
XML
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载 SpringMVC 核心配置文件(classpath 表示类路径下) -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 服务器启动时初始化(优先级 1,数值越小优先级越高) -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 拦截所有 .do 结尾的请求(避免拦截静态资源如 CSS/JS) -->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3. SpringMVC 核心配置(springmvc.xml)
SpringMVC 配置文件需完成注解扫描 、视图解析器 、注解驱动 和静态资源放行四项核心配置,确保 Controller 能被扫描、页面能正确跳转、静态资源不被拦截。
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1. 注解扫描:仅扫描 Controller 所在包(避免扫描 Service/Dao 层) -->
<context:component-scan base-package="com.springmvc.controller" />
<!-- 2. 视图解析器:拼接物理视图路径(逻辑视图名 → 实际页面路径) -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/" /> <!-- 页面所在目录(WebRoot 下) -->
<property name="suffix" value=".jsp" /> <!-- 页面后缀 -->
<!-- 示例:逻辑视图名 "suc" → 拼接后:/pages/suc.jsp -->
</bean>
<!-- 3. 启用 SpringMVC 注解驱动:让 @RequestMapping、@RequestBody 等注解生效 -->
<mvc:annotation-driven/>
<!-- 4. 静态资源放行:避免 CSS/JS/图片被 DispatcherServlet 拦截 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 匹配 /css/ 下所有资源 -->
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
</beans>
二、Controller 方法返回值分类(核心)
SpringMVC 中,Controller 方法的返回值决定了响应方式,主要分为 String 类型 、void 类型 和 ModelAndView 类型,不同返回值适用于不同场景。
1. 返回 String 类型(最常用)
核心作用:
返回逻辑视图名 ,通过视图解析器(InternalResourceViewResolver)拼接为物理视图路径(prefix + 逻辑视图名 + suffix),适用于简单的页面跳转场景。
代码示例:
java
package com.springmvcy.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user") // 类级别的请求路径(统一前缀)
public class UserController {
// 方法级别的请求路径:完整请求路径为 /user/save1.do
@RequestMapping("/save1.do")
public String save1() {
System.out.println("执行用户保存业务(save1)");
// 返回逻辑视图名 "suc" → 视图解析器拼接为:/pages/suc.jsp
return "suc";
}
}
关键注意点:
- 若返回值以
forward:或redirect:开头(如return "forward:/pages/suc.jsp"),则不经过视图解析器,直接按指定路径跳转(详见下文 "转发与重定向")。 - 逻辑视图名需与实际页面目录匹配(如
return "user/list"对应/pages/user/list.jsp)。
2. 返回 void 类型
默认行为:
若方法返回 void,SpringMVC 会默认查找 "当前请求路径.jsp" (如请求 /user/save2.do,默认查找 /user/save2.jsp),而该页面通常不存在,会导致 404 错误。因此,返回 void 时需手动通过 HttpServletRequest 或 HttpServletResponse 处理响应。
常用场景与代码示例:
java
@RequestMapping("/save2.do")
public void save2(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("执行用户保存业务(save2)");
// 场景1:请求转发(服务器内部跳转,地址栏不变,可共享 request 数据)
request.getRequestDispatcher("/pages/suc.jsp").forward(request, response);
// 场景2:直接响应文本(无需跳转页面,如接口返回简单提示)
// response.setContentType("text/html;charset=UTF-8"); // 解决响应中文乱码
// response.getWriter().print("用户保存成功!");
// 场景3:重定向(客户端跳转,地址栏改变,不可共享 request 数据)
// response.sendRedirect(request.getContextPath() + "/pages/suc.jsp");
}
关键注意点:
- 手动处理响应时,需注意中文乱码 :通过
response.setContentType("text/html;charset=UTF-8")设置响应编码。 - 重定向时需拼接项目上下文路径(
request.getContextPath()),避免路径错误(如response.sendRedirect(request.getContextPath() + "/pages/suc.jsp"))。
3. 返回 ModelAndView 类型
核心作用:
ModelAndView 是 SpringMVC 提供的 "数据 + 视图" 封装类,可同时存储页面所需数据 (Model)和视图路径(View),适用于 "业务处理后需传递数据到页面" 的场景(如列表查询后传递数据到页面展示)。
代码示例:
java
@RequestMapping("/save3.do")
public ModelAndView save3() {
System.out.println("执行用户保存业务(save3)");
// 1. 创建 ModelAndView 对象
ModelAndView mv = new ModelAndView();
// 2. 存入页面所需数据(相当于 request.setAttribute("msg", "用户名已存在"))
// 页面可通过 EL 表达式 ${msg} 获取该数据
mv.addObject("msg", "保存失败:用户名已存在,请更换用户名");
// 可存入多个数据:mv.addObject("user", new User("张三", 20));
// 3. 设置逻辑视图名(视图解析器拼接为 /pages/error.jsp)
mv.setViewName("error");
// 返回 ModelAndView 对象,SpringMVC 自动处理数据传递与页面跳转
return mv;
}
关键注意点:
mv.addObject()存入的数据默认存储在 request 域中,生命周期与 request 一致(仅当前请求有效)。- 若需长期存储数据(如用户登录信息),需手动将数据存入 session 域(
request.getSession().setAttribute("user", user))。
三、SpringMVC 转发与重定向(返回 String 实现)
在实际开发中,页面跳转常需区分 "转发" 和 "重定向",SpringMVC 支持通过返回 String 类型实现这两种跳转方式,无需手动操作 HttpServletRequest/HttpServletResponse。
1. 请求转发(forward:)
核心特点:
- 服务器内部跳转,地址栏 URL 不变。
- 可共享 request 域中的数据(如转发前存入的
request.setAttribute("data", xxx)可在目标页面获取)。 - 跳转路径可为相对路径或绝对路径,不经过视图解析器。
代码示例:
java
@RequestMapping("/save4.do")
public String save4() {
System.out.println("执行用户保存业务(save4)");
// 方式1:转发到具体页面(绝对路径)
// return "forward:/pages/suc.jsp";
// 方式2:转发到其他 Controller 方法(完整请求路径)
return "forward:/user/findAll.do";
}
2. 重定向(redirect:)
核心特点:
- 客户端跳转(服务器返回 302 状态码,浏览器重新发起请求),地址栏 URL 改变。
- 不可共享 request 域数据(因是新请求,原 request 已销毁)。
- 跳转路径需写绝对路径(通常需拼接项目上下文路径),不经过视图解析器。
- 无法直接访问 WEB-INF 目录下的资源(Tomcat 等服务器禁止客户端直接访问 WEB-INF)。
代码示例:
javascript
@RequestMapping("/save5.do")
public String save5() {
System.out.println("执行用户保存业务(save5)");
// 方式1:重定向到具体页面(需拼接项目上下文路径,避免路径错误)
// return "redirect:" + request.getContextPath() + "/pages/suc.jsp";
// 方式2:重定向到其他 Controller 方法(完整请求路径)
return "redirect:/user/findAll.do";
}
转发与重定向对比表:
| 对比维度 | 请求转发(forward) | 重定向(redirect) |
|---|---|---|
| 跳转方式 | 服务器内部跳转 | 客户端跳转(浏览器重新请求) |
| 地址栏 URL | 不变 | 改变 |
| request 数据共享 | 可共享 | 不可共享 |
| 路径处理 | 可相对路径,不经过视图解析器 | 需绝对路径,不经过视图解析器 |
| 访问 WEB-INF | 可访问(服务器内部跳转) | 不可访问(客户端禁止访问 WEB-INF) |
四、响应 JSON 数据(异步交互核心)
在前后端分离项目中(如 Vue/React 前端 + SpringMVC 后端),后端通常需返回 JSON 格式数据而非页面。SpringMVC 通过 @RequestBody(接收前端 JSON)和 @ResponseBody(返回 JSON)注解,结合 Jackson 依赖实现 JSON 交互。
1. 核心依赖与注解说明
(1)依赖前提:
需确保已导入 Jackson 相关依赖(见本文 "Maven 坐标配置" 部分),Jackson 负责将 Java 对象转为 JSON 字符串,或反之。
(2)关键注解:
| 注解 | 作用 | 适用位置 |
|---|---|---|
| @RequestBody | 将前端传入的 JSON 字符串转为 Java 对象 | Controller 方法参数前 |
| @ResponseBody | 将 Java 对象转为 JSON 字符串响应前端 | Controller 方法前或类前 |
2. 实体类准备(User.java)
JSON 转换依赖实体类的 getter 方法(Jackson 通过 getter 读取属性值),需确保实体类实现 Serializable 接口(序列化规范),并提供完整的 getter/setter 方法。
java
package com.springmvc.entity;
import java.io.Serializable;
// 实体类:对应前端传递的 JSON 数据结构
public class User implements Serializable {
private String username; // 用户名
private Integer age; // 年龄
// 无参构造(JSON 反序列化需)
public User() {}
// 有参构造(可选)
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
// 必须提供 getter/setter 方法(Jackson 依赖 getter 序列化)
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
@Override
public String toString() {
return "User{" + "username='" + username + "', age=" + age + "}";
}
}
3. 前端 AJAX 代码(JSP 页面)
前端通过 AJAX 发送 JSON 数据,并指定 contentType: "application/json;charset=UTF-8",告诉后端 "当前传递的是 JSON 格式数据"。
html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>SpringMVC JSON 交互</title>
<!-- 引入 jQuery(需确保 js 目录已配置静态资源放行) -->
<script src="/js/jquery.min.js" type="text/javascript"></script>
<script>
$(function() {
$("#btnSubmit").click(function() {
// 1. 构造 JSON 数据(与后端 User 实体类属性对应)
let userData = JSON.stringify({
"username": "张三",
"age": 25
});
// 2. 发送 AJAX 请求
$.ajax({
type: "post", // 请求方式(JSON 传递需用 post)
url: "/user/save6.do", // 请求路径
contentType: "application/json;charset=UTF-8", // 关键:声明请求数据格式为 JSON
data: userData, // 传递的 JSON 数据
dataType: "json", // 期望后端返回 JSON 格式数据
success: function(res) { // 响应成功回调(res 为后端返回的 JSON 对象)
alert("用户名:" + res.username + ",年龄:" + res.age);
},
error: function() { // 响应失败回调
alert("请求失败,请重试!");
}
});
});
});
</script>
</head>
<body>
<button id="btnSubmit">提交用户数据(AJAX)</button>
</body>
</html>
4. 后端 Controller 代码
通过 @RequestBody 接收前端 JSON 并转为 User 对象,处理业务后,通过 @ResponseBody 将处理后的 User 对象转为 JSON 响应前端。
java
@RequestMapping("/save6.do")
// @ResponseBody:将返回的 User 对象转为 JSON 响应前端
@ResponseBody
public User save6(@RequestBody User user) { // @RequestBody:将前端 JSON 转为 User 对象
System.out.println("接收前端传递的用户数据:" + user); // 打印:User{username='张三', age=25}
// 模拟业务处理:如修改用户名和年龄
user.setUsername("张三_已处理");
user.setAge(user.getAge() + 1);
// 直接返回 User 对象,@ResponseBody 自动转为 JSON
return user;
}
5. 关键避坑点:
-
前端必须指定
contentType: "application/json;charset=UTF-8":否则后端无法识别 JSON 格式,@RequestBody会解析失败。 -
实体类必须有 无参构造:Jackson 反序列化(JSON → Java 对象)时需调用无参构造创建对象。
-
静态资源放行:确保 jQuery 等静态资源已通过
mvc:resources配置放行,避免 404 错误。 -
中文乱码:若响应 JSON 包含中文乱码,可在 SpringMVC 配置文件中配置消息转换器(如下):
XML<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
五、核心总结与最佳实践
1. 响应方式选型建议
| 业务场景 | 推荐返回值类型 | 关键技术点 |
|---|---|---|
| 简单页面跳转(无数据传递) | String | 逻辑视图名 + 视图解析器 |
| 页面跳转需传递数据 | ModelAndView | mv.addObject() 存数据 |
| 手动处理响应(如直接输出文本) | void | HttpServletRequest/HttpServletResponse |
| 页面跳转(转发 / 重定向) | String(带 forward:/redirect:) | 不经过视图解析器,绝对路径跳转 |
| 前后端分离异步交互 | Java 对象(配合 @ResponseBody) | @RequestBody 接收 JSON,Jackson 转换 |
2. 核心配置与避坑清单
- 环境配置:确保
DispatcherServlet加载 SpringMVC 配置文件,mvc:annotation-driven已启用。 - 静态资源:通过
mvc:resources放行 CSS/JS/ 图片,避免被 DispatcherServlet 拦截。 - 中文乱码:请求乱码用
CharacterEncodingFilter,响应乱码用response.setContentType()。 - JSON 交互:导入 Jackson 依赖,确保实体类有 getter / 无参构造,前端指定
contentType: application/json。
通过本文的讲解,相信开发者已能掌握 SpringMVC 响应数据与结果视图的核心用法。在实际开发中,需根据业务场景选择合适的响应方式,同时注意配置规范与细节,避免常见错误,提升开发效率与系统稳定性。