Spring MVC Controller 方法的返回类型有哪些?

Spring MVC Controller 方法的返回类型非常灵活,可以根据不同的需求返回多种类型的值。Spring MVC 会根据返回值的类型和相关的注解来决定如何处理响应。

以下是一些常见的 Controller 方法返回类型:

  1. String:

    • 最常见的类型之一,用于返回逻辑视图名 (Logical View Name)。 Spring MVC 会使用配置的 ViewResolver 根据这个逻辑视图名找到对应的物理视图(例如 JSP 文件、Thymeleaf 模板等),并渲染响应。
    • 特殊用法: 如果返回的 String"redirect:" 开头,Spring MVC 会执行一个客户端重定向到指定的 URL。
    • 特殊用法: 如果返回的 String"forward:" 开头,Spring MVC 会执行一个服务器端转发到指定的 URL 或另一个 Controller 方法。
    @GetMapping("/show")
    public String showPage() {return "myPage"; // 返回逻辑视图名 "myPage"
    }@PostMapping("/save")
    public String saveData() {// ... save data ...return "redirect:/success"; // 重定向到 /success
    }@GetMapping("/process")
    public String processRequest() {// ... process ...return "forward:/internal/handler"; // 转发到 /internal/handler
    }
    
  2. void:

    • 当 Controller 方法返回 void 时,意味着该方法直接处理了响应(例如通过 Servlet API 获取 HttpServletResponse 并写入数据),或者 Spring MVC 会根据请求的 URL 自动推断视图名(这种方式较少使用,且依赖于特定的配置)。
    • 更常见的是结合 @ResponseBody 使用 void,表示不需要返回响应体,或者响应体已经在方法内部通过其他方式写入(例如流式写入)。
    @PostMapping("/noContent")
    @ResponseBody // 表示不需要视图,但也没有响应体
    public void doNothing() {// 完成一些操作,但不需要返回数据或视图
    }// 或者直接操作 response
    @GetMapping("/directWrite")
    public void writeResponse(HttpServletResponse response) throws IOException {response.setContentType("text/plain");response.getWriter().write("Directly written!");
    }
    
  3. Object (any POJO or collection) with @ResponseBody:

    • 当方法返回一个普通的 Java 对象(POJO)、集合或基本数据类型,并且方法或类上使用了 @ResponseBody 注解时,Spring MVC 会跳过视图解析阶段。
    • 它会使用配置的 HttpMessageConverter 将返回的对象序列化成特定的格式(如 JSON、XML)写入到 HTTP 响应体中。这种方式是构建 RESTful API 的主要方式。
    • @RestController 注解本质上是 @Controller@ResponseBody 的组合,用在类级别时,该类下所有方法默认都会将返回值序列化为响应体。
    @GetMapping("/api/user")
    @ResponseBody
    public User getUser() {// ... retrieve user ...return new User("Alice", 30); // 返回 User 对象,会被序列化为 JSON/XML 等
    }@RestController // 整个类的方法默认都带 @ResponseBody
    @RequestMapping("/api")
    public class UserRestController {@GetMapping("/list")public List<User> getAllUsers() {// ... retrieve list ...return Arrays.asList(new User("Alice", 30), new User("Bob", 25));}
    }
    
  4. ResponseEntity<?>:

    • 这是 Spring MVC 提供的用于完全控制 HTTP 响应的类型。它允许设置响应的状态码 (Status Code)、HTTP 头 (Headers) 和响应体 (Body)。
    • 适合构建 RESTful API,可以方便的返回 200 OK, 201 Created, 404 Not Found 等不同的状态码,并包含响应体。
    @GetMapping("/api/users/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {User user = findUser(id);if (user != null) {return ResponseEntity.ok(user); // 返回 200 OK 和用户对象} else {return ResponseEntity.notFound().build(); // 返回 404 Not Found}
    }@PostMapping("/api/users")
    public ResponseEntity<User> createUser(@RequestBody User newUser) {User savedUser = saveUser(newUser);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser); // 返回 201 Created 和创建的用户对象
    }
    
  5. ModelAndView:

    • Spring MVC 早期常用的类型,它将模型数据 (Model Data) 和视图名 (View Name) 封装在一起返回。
    • 虽然功能强大,但相对于返回 String@ResponseBody + Object 而言,代码略显繁琐,但在某些场景下(例如需要在返回视图的同时设置特定的模型数据)仍然有用。
    @GetMapping("/details")
    public ModelAndView showDetails(@RequestParam Long id) {User user = findUser(id);ModelAndView mav = new ModelAndView("userDetails"); // 设置视图名mav.addObject("user", user); // 添加模型数据return mav;
    }
    
  6. View:

    • 可以直接返回一个 View 接口的实现类实例,而不是逻辑视图名。这允许你编程方式地选择或创建一个视图。
    @GetMapping("/customView")
    public View customView() {return new MyCustomView(); // 返回一个自定义的 View 实现
    }
    
  7. 异步支持的类型:

    • Spring MVC 提供了对异步请求处理的支持,可以在 Controller 方法中返回代表未来结果的对象,从而释放容器线程。
    • Callable<?>: 将耗时操作封装在 Callable 中,Spring 会在一个单独的线程中执行它。
    • DeferredResult<?>: 允许在一个完全独立的线程或服务中返回结果,然后通过 DeferredResult.setResult() 来完成请求。
    • ListenableFuture<?> (Spring 4.x+), CompletionStage<?> / CompletableFuture<?> (Spring 5.x+): 支持与异步框架(如 CompletableFuture)集成。
    @GetMapping("/async/callable")
    public Callable<String> asyncCallable() {return () -> {Thread.sleep(2000); // 模拟耗时操作return "asyncResult"; // 返回逻辑视图名};
    }@GetMapping("/async/deferred")
    public DeferredResult<ResponseEntity<?>> asyncDeferred() {DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();// 在另一个线程或事件中处理并设置结果// someExternalService.process(data -> deferredResult.setResult(ResponseEntity.ok(data)));return deferredResult;
    }
    
  8. 资源相关类型:

    • 用于直接返回文件或流资源。
    • Resource / InputStreamResource / ByteArrayResource: 用于文件下载或提供静态资源。
    • StreamingResponseBody: 用于需要流式写入响应体,特别是当响应体非常大或需要动态生成时。
    @GetMapping("/download")
    public ResponseEntity<Resource> downloadFile() throws IOException {Path file = Paths.get("path/to/your/file.txt");Resource resource = new UrlResource(file.toUri());return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").body(resource);
    }@GetMapping("/stream")
    public StreamingResponseBody streamData() {return outputStream -> {for (int i = 0; i < 1000; i++) {outputStream.write(("Data line " + i + "\n").getBytes());outputStream.flush();Thread.sleep(10);}};
    }
    

总结:

  • 返回 HTML 页面: 使用 String 返回视图名,或 ModelAndView
  • 返回 JSON/XML 数据 (REST API): 使用 @ResponseBody + Object,或 ResponseEntity<?>。推荐 ResponseEntity<?> 因为它能控制响应状态和头部。
  • 重定向: 使用 String (前缀 "redirect:")。
  • 服务器端转发: 使用 String (前缀 "forward:")。
  • 需要完全控制响应 (状态码、头部、体): 使用 ResponseEntity<?>
  • 异步处理请求: 使用 Callable<?>, DeferredResult<?>, CompletableFuture<?> 等。
  • 直接返回文件或流: 使用 Resource 相关类型或 StreamingResponseBody
  • 不需要返回任何内容 (with @ResponseBody): 使用 void

Spring MVC 通过 HandlerMethodReturnValueHandler 机制来处理这些不同的返回类型,为每种类型找到合适的处理器来生成最终的 HTTP 响应。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80100.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[ctfshow web入门] web55

信息收集 这里把小写字母都过滤了&#xff0c;众所周知linux是大小写区分的&#xff0c;没有小写字母根本整不出来命令 if(isset($_GET[c])){$c$_GET[c];if(!preg_match("/\;|[a-z]|\|\%|\x09|\x26|\>|\</i", $c)){system($c);} }else{highlight_file(__FILE…

2021-11-11 C++泰勒sin(x)以2步进乘方除以阶乘加减第N项

缘由c书本题&#xff0c;求解了&#xff0c;求解-编程语言-CSDN问答 int n 10, d 3, z -1; double x 2.5, xx x;while (n){xx (乘方(x, d) / 阶乘(d)) * z;d 2, --n, z * -1;}std::cout << xx << std::endl;

湖仓一体化介绍

目录 一、湖仓一体化的定义与核心概念 二、湖仓一体化出现的背景 (一)数据仓库的局限性 (二

仓颉编程语言快速入门:从零构建全场景开发能力

在万物互联的智能时代,编程语言的演进始终与计算范式的革新紧密相连。华为推出的仓颉编程语言(Cangjie Programming Language)以“原生智能化、天生全场景”为核心理念,为开发者提供了一种兼顾高效开发与极致性能的新选择。本文将带你从零开始,快速掌握这门面向未来的语言…

AI教你学VUE——Deepseek版

一、基础阶段&#xff1a;打好Web开发基础 HTML/CSS基础 学习HTML标签语义化、CSS布局&#xff08;Flex/Grid&#xff09;、响应式设计&#xff08;媒体查询、REM/VW单位&#xff09;。资源推荐&#xff1a; MDN Web文档&#xff08;免费&#xff09;&#xff1a;HTML | CSS实战…

DeepSeek智能时空数据分析(八):NL2SQL绘制河流-轨迹缓冲区如何生成

序言&#xff1a;时空数据分析很有用&#xff0c;但是GIS/时空数据库技术门槛太高 时空数据分析在优化业务运营中至关重要&#xff0c;然而&#xff0c;三大挑战仍制约其发展&#xff1a;技术门槛高&#xff0c;需融合GIS理论、SQL开发与时空数据库等多领域知识&#xff1b;空…

推导部分和-图论+dfs+连通块

先研究一下&#xff0c;感觉有点像lca里的树上前缀和&#xff0c;不过树有多颗&#xff0c;用color区分一下 https://www.luogu.com.cn/problem/P8779 #include<bits/stdc.h> using namespace std; #define N 100011 typedef long long ll; typedef pair<int,int&g…

WPF MVVM入门系列教程(六、ViewModel案例演示)

&#x1f9ed; WPF MVVM入门系列教程 一、MVVM模式介绍二、依赖属性三、数据绑定四、ViewModel五、命令和用户输入六、ViewModel案例演示 在前面的文章中&#xff0c;介绍了ViewModel的基础概念 本文会使用一些实例来进行ViewModel的演示 一个基础的数据展示示例 假设我们要…

第2章 算法分析基础

2-1 算法的时间复杂度分析 2.1.1 输入规模与基本语句 输入规模&#xff1a;算法处理数据的规模&#xff0c;通常用 n 表示。 基本语句&#xff1a;执行次数与输入规模直接相关的关键操作。 例2.1 顺序查找 int SeqSearch(int A[], int n, int k) { for (int i 0; i < n…

QT高级(1)QTableView自定义委托集合,一个类实现若干委托

自定义委托集合 1同系列文章2 功能3 源码 1同系列文章 QT中级&#xff08;1&#xff09;QTableView自定义委托&#xff08;一&#xff09;实现QSpinBox、QDoubleSpinBox委托 QT中级&#xff08;2&#xff09;QTableView自定义委托&#xff08;二&#xff09;实现QProgressBar委…

webrtc 视频直播

webrtc 是一种开源的音视频通信技术&#xff0c;可以不借助中间媒介建立浏览器点对点&#xff08;peer-to-peer&#xff09;连接&#xff0c;实现音视频以及其他数据的传输。webrtc具有平台兼容性&#xff0c;低延迟与高实时的优点。今天主要记录一下webrtc的使用记录&#xff…

游戏引擎学习第261天:切换到静态帧数组

game_debug.cpp: 将ProfileGraph的尺寸初始化为相对较大的值 今天的讨论主要围绕性能分析器&#xff08;Profiler&#xff09;以及如何改进它的可用性展开。当前性能分析器已经能够正常工作&#xff0c;但我们希望通过一些改进&#xff0c;使其更易于使用&#xff0c;特别是在…

three.js设置物体轮廓发光和物体发光

设置物体轮廓发光 <script setup> import * as THREE from three; import { OrbitControls } from three/addons/controls/OrbitControls.js; // 导入后期合成 import { EffectComposer } from three/examples/jsm/postprocessing/EffectComposer.js; import { RenderPas…

homebrew安装配置Python(MAC版)

Mac系统自带python路径为: /System/Library/Frameworks/Python.framework/Versionbrew 安装 Python3 在终端输入以下命令&#xff1a; brew search python3 # 查看支持安装的版本 brew install python3就可以轻松easy安装python了&#xff0c;安装完成后提示 查看 pyth…

如何建设网站?网站建设简单步骤有哪些?

新手如何开展网站建设&#xff1f;网站建设包括哪些步骤&#xff1f; 在开展网站建设之前先清楚了解网站建设的流程和步骤&#xff1a;注册域名、租用虚拟主机/服务器、建站工具的选取、网站建设流程详细流程共计7步&#xff0c;分别是注册域名、域名实名制、服务器或虚拟主机、…

当K8S容器没有bash时高阶排查手段

遇到容器没有bash甚至没有sh的情况&#xff0c;就像被困在没有门窗的房间。但真正的K8S运维高手&#xff0c;即使面对这种情况也能游刃有余。 一、无Shell容器三大特征 极简主义&#xff1a;移除所有非必要组件&#xff08;如/bin/sh&#xff09;安全加固&#xff1a;减少攻击…

Python案例实战《手势识别》

目录 1、效果图2、手势识别关键步骤&#xff08;1&#xff09; 导入必要的库&#xff08;2&#xff09;配置 MediaPipe&#xff08;3&#xff09;启动摄像头&#xff08;4&#xff09;设置手指张开判断的距离阈值&#xff08;5&#xff09;计算手指之间的欧几里得距离&#xff…

5G赋能农业物联网:智能化种植的新纪元

5G赋能农业物联网&#xff1a;智能化种植的新纪元 在农业领域&#xff0c;精准化、智能化已成为现代农业发展的方向。而5G的出现&#xff0c;让农业物联网&#xff08;Agri-IoT&#xff09;突破了传统的瓶颈&#xff0c;真正实现了实时监测、高效数据传输、智能化决策&#xf…

VIVADO IP核整理(二)——FFT

目录 IP 核配置IP 核接口s_axis_config_tdata 配置输入输出端口描述 仿真 参考&#xff1a;FFT IP核 详细介绍 参考&#xff1a;官方文档介绍 IP 核配置 在 IP Catalog 中搜索&#xff1a;Fast Fourier Transform 按照上图所示进行配置&#xff0c;下文对配置内容进行详述。 …

【计算机基础】任意进制转换方法详解

文章目录 一、通用进制转换(整数部分)1. R进制转十进制(整数)2. 十进制转R进制(整数)二、通用进制转换(小数部分)1. 十进制小数转R进制2. R进制小数转十进制三、二进制与十进制互转(整数部分)1. 二进制转十进制(整数)2. 十进制转二进制(整数)四、二进制与十进制互…