SpringMVC相关梳理
SpringMVC 返回值类型
(一)核心返回值类型分类
- 视图渲染类:用于跳转并渲染页面,如String(指定视图名)、ModelAndView(视图 + 数据)。
- 数据返回类:用于返回数据(而非页面),如@ResponseBody + Object(返回 JSON/XML 等)、ResponseEntity(自定义响应头、状态码 + 数据)。
- 响应控制类:直接控制响应内容,如void(通过HttpServletResponse手动写响应)、HttpServletResponse(同上)。
- 异步处理类:用于异步请求处理,如DeferredResult、Callable。
- 重定向专用类:redirect: + RedirectAttributes(重定向时传递数据,避免request失效问题)。
- 转发专用类:forward:(通过String返回值指定转发路径)。
(二)返回值选择指南表格
应用场景 | 推荐返回值类型 | 示例代码 |
显示 JSP/Thymeleaf 页面 | String | return "index";(对应 index.jsp/index.html) |
返回 JSON 数据(接口) | @ResponseBody + Object | @ResponseBody public User getUser() { return user; } |
精确控制响应(头、状态码) | ResponseEntity | return new ResponseEntity<>(data, HttpStatus.OK); |
文件下载 | ResponseEntity<byte[]> 或 void | return new ResponseEntity<>(fileBytes, headers, HttpStatus.OK); |
异步请求处理(如长轮询) | DeferredResult 或 Callable | public DeferredResult<String> asyncHandle() { ... } |
重定向并传递数据 | String + RedirectAttributes | public String redirect(RedirectAttributes attr) { attr.addFlashAttribute("msg", "success"); return "redirect:/index"; } |
服务器内部转发 | String(带forward:前缀) | return "forward:/user/detail"; |
直接手动写响应内容 | void(配合HttpServletResponse) | public void writeResponse(HttpServletResponse response) { response.getWriter().write("hello"); } |
请求转发(Forward)
(一)基本概念
请求转发是服务器内部的行为,客户端仅发起一次请求,服务器在内部将该请求转发到另一个资源。
(二)工作原理
客户端 → 请求 → 服务器(Servlet A) → 转发 → 服务器(Servlet B) → 响应 → 客户端 |
(三)特点
- URL 不变:浏览器地址栏始终显示原始请求的 URL,不会发生变化。
- 一次请求:整个转发流程中,客户端仅发送一次 HTTP 请求。
- 共享 request:转发前后的资源(如 Servlet、JSP 等)共享同一个request对象,可通过request传递数据。
- 服务器内部操作:转发过程对客户端透明,客户端无法感知到服务器内部的转发行为。
- 范围限制:仅能转发到当前应用内部的资源,无法转发到外部 URL(如其他网站)。
(四)使用场景
- 控制器完成业务逻辑处理后,跳转到用于数据展示的页面(如 JSP)。
- 需要在不同资源之间传递数据(如从控制器向页面传递查询结果)时。
- 要求保持浏览器地址栏 URL 不变的页面跳转场景。
重定向(Redirect)
(一)基本概念
重定向是客户端的行为,服务器接收到客户端请求后,会返回一个响应(告知客户端 “请去访问另一个 URL”),随后客户端会根据该响应发起新的请求。
(二)工作原理
客户端 → 请求① → 服务器 → 响应(302重定向状态码) → 客户端 → 请求② → 新URL对应的服务器 → 响应 → 客户端 |
(三)特点
- URL 改变:浏览器地址栏会更新为新的目标 URL,显示最终访问的地址。
- 两次请求:客户端会先后发起两次 HTTP 请求,第一次请求原始 URL,第二次请求重定向后的 URL。
- 不共享 request:两次请求分别对应独立的request对象,无法通过request传递数据。
- 无范围限制:可重定向到任意 URL,包括当前应用内部资源和外部网站(如从自身系统跳转到百度)。
- 客户端知情:客户端能感知到重定向行为(通过地址栏变化或网络请求记录)。
(四)使用场景
- 表单提交后(如用户注册、登录提交),防止刷新页面导致重复提交(即 Post-Redirect-Get 模式)。
- 需要跳转到外部网站时(如从应用内跳转到第三方支付平台)。
- 用户完成登录 / 注销操作后,跳转到目标页面(如登录后跳转到首页,注销后跳转到登录页)。
- 要求改变浏览器地址栏 URL 的场景(如优化 URL 显示,隐藏内部接口路径)。
请求转发与重定向对比表格
特性 | 请求转发(Forward) | 重定向(Redirect) |
请求次数 | 1 次 | 2 次 |
URL 变化 | 不变(显示原始 URL) | 改变(显示目标 URL) |
数据共享 | 共享同一个request对象 | 不共享request对象(两次请求独立) |
速度 | 较快(仅服务器内部处理,无客户端往返) | 较慢(需客户端发起第二次请求,有网络往返) |
目标范围 | 仅能跳转至同一应用内部资源 | 可跳转至任意 URL(内部 / 外部) |
浏览器感知 | 无感知(不知道转发过程) | 有感知(地址栏变化、可查看两次请求) |
实现方式(SpringMVC) | return "forward:url" | return "redirect:url" |
实际应用示例(SpringMVC 环境)
(一)请求转发示例
/*** 返回String类型,实现请求转发* @return 转发目标路径*/@RequestMapping("/save4.do")public String save4() {System.out.println("业务逻辑执行完成(如数据保存)...");// 转发到/pages目录下的suc.jsp页面return "forward:/pages/suc.jsp";}
(二)重定向示例
/*** 返回String类型,实现重定向* @return 重定向目标路径*/@RequestMapping("/save5.do")public String save5() {System.out.println("业务逻辑执行完成(如表单提交)...");// 重定向到/pages目录下的suc.jsp页面return "redirect:/pages/suc.jsp";}
选择原则
(一)优先选择请求转发的场景
- 需保持浏览器地址栏 URL 不变时。
- 需在不同资源(如控制器→页面、控制器→控制器)之间通过request传递数据时。
- 仅需跳转到当前应用内部页面,且对跳转性能有较高要求时。
(二)优先选择重定向的场景
- 表单提交后,需防止刷新页面导致重复提交时(必选 Post-Redirect-Get 模式)。
- 需跳转到外部网站(如第三方平台、合作系统)时。
- 用户完成登录、注销等操作后,需跳转到目标页面(如首页、个人中心)时。
- 需改变浏览器地址栏 URL,隐藏内部接口路径或优化 URL 显示时。
- 需实现跨应用跳转(如从 A 应用跳转到 B 应用)时。