What is `@ResponseBody` does?
@ResponseBody
是SpringMVC
框架中的一个注解,将方法返回值
转换为HTTP响应体内容
当 @ResponseBody
注解应用在一个控制器方法上时,SpringMVC
会将该方法的返回对象(如Java对象、字符串或基本类型)通过MessageConverter
转换为指定的媒体类型(如JSON
、XML
等),然后直接写入HTTP响应体
中,而不是经过视图解析器
查找和渲染视图。
使用样例
RESTful API开发
RESTful API
开发:在创建REST服务时,通常需要将业务对象以JSON或其他格式发送给客户端。这时可以使用 @ResponseBody
来直接返回对象,框架会自动进行序列化
。
返回基本数据类型
import org.springframework.web.bind.annotation.*;@RestController
public class CalculatorController {@GetMapping("/calculate")@ResponseBodypublic double addNumbers(@RequestParam("num1") double num1, @RequestParam("num2") double num2) {return num1 + num2;}
}
返回JSON格式数据
import org.springframework.web.bind.annotation.*;@RestController
public class ProductController {@GetMapping("/products/{id}")@ResponseBodypublic Product getProduct(@PathVariable Long id) {// 获取产品逻辑...Product product = productService.findById(id);return product; // 返回的对象会被自动序列化为JSON并发送给客户端}@PostMapping("/products")@ResponseBodypublic Product createProduct(@RequestBody Product newProduct) {// 创建产品逻辑...Product createdProduct = productService.create(newProduct);return createdProduct; // 同样将返回的对象序列化为JSON响应体}
}
返回字符串
import org.springframework.web.bind.annotation.*;@RestController
public class MessageController {@GetMapping("/message")@ResponseBodypublic String getMessage() {return "Hello, World!"; // 直接返回一个字符串,它会作为HTTP响应体内容}
}// 或者更复杂的动态生成的字符串
@GetMapping("/dynamic-message")
@ResponseBody
public String getDynamicMessage(@RequestParam String name) {return "Hello, " + name + "!"; // 根据请求参数生成消息,并作为响应体返回
}
返回自定义对象集合
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/employees")
public class EmployeeController {@GetMapping@ResponseBodypublic List<Employee> getAllEmployees() {// 获取所有员工逻辑...List<Employee> employees = employeeService.getAll();return employees; // 返回的员工列表会被转换为JSON并发送给客户端}
}// 假设Employee类如下:
public class Employee {private Long id;private String name;private String position;// 构造函数、getter和setter省略
}
返回HTTP状态码及响应体
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
public class StatusController {@GetMapping("/status/{code}")@ResponseBodypublic ResponseEntity<String> getStatus(@PathVariable int code) {if (HttpStatus.resolve(code) == null) {return ResponseEntity.badRequest().body("Invalid status code");}return ResponseEntity.status(code).body("Requested status code: " + code);}
}
返回分页数据
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/products")
public class ProductController {private final ProductService productService;public ProductController(ProductService productService) {this.productService = productService;}@GetMapping(params = {"page", "size"})@ResponseBodypublic Page<Product> getProducts(@RequestParam("page") int page, @RequestParam("size") int size) {return productService.getProducts(page, size);}
}
返回异步处理并返回结果
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.CompletableFuture;@RestController
public class AsyncController {@Async@GetMapping("/async-result")@ResponseBodypublic CompletableFuture<String> getAsyncResult() {// 模拟耗时操作try {Thread.sleep(2000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return CompletableFuture.completedFuture("This is the result from an asynchronous operation");}
}
返回异步返回文件下载链接
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class FileDownloadController {@Async@GetMapping("/generate-file")@ResponseBodypublic Future<ResponseEntity<String>> generateFileAndReturnLink(@RequestParam("filename") String filename) {// 模拟文件生成过程try {Thread.sleep(5000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 假设fileService.generateFile(filename)返回的是文件存储路径String fileUrl = fileService.generateFile(filename);HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.TEXT_PLAIN);return CompletableFuture.completedFuture(ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"").header(HttpHeaders.LOCATION, fileUrl).body("The file has been generated. Download it from: " + fileUrl));}
}
与@RestController配合使用
如果一个控制器类的所有方法都需要返回响应体内容,而不是视图名,那么可以将整个类标记为 @RestController
@RestController
= @Controller
+ @ResponseBody
@RestController
@RequestMapping("/api/users")
public class UserController {@GetMapping("/{id}")public User getUser(@PathVariable Long id) {// 不需要单独标注@ResponseBody,因为@RestController已经提供了这个功能return userService.findById(id);}
}