Springの @ResponseBodyアノテーション完全ガイド!初心者でもわかる使い方
生徒
「Springの@ResponseBodyアノテーションって何ですか?どんな時に使うんでしょうか?」
先生
「良い質問ですね!Springの@ResponseBodyアノテーションは、APIを作成する時にとても便利な機能なんです。簡単に言うと、メソッドの返り値をそのままHTTPレスポンスとして返すためのものです。」
生徒
「具体的にはどのように使えば良いのでしょうか?」
先生
「それでは、実際の使い方をコードで見ていきましょう!」
1. @ResponseBodyアノテーションとは?
Springフレームワークにおいて、@ResponseBodyアノテーションは、メソッドが返すデータをそのままHTTPレスポンスのボディ部分としてクライアントに返すために使用されます。通常、@Controllerクラス内のメソッドは、ビュー名(例えばJSPファイル)を返しますが、@ResponseBodyを使うとJSONやXMLなどのデータを直接返すことができます。
例えば、RESTful APIを作成する際に、クライアントにJSONデータを返したい時にこのアノテーションを使用します。これにより、APIエンドポイントを介してデータを取得しやすくなります。
2. @ResponseBodyアノテーションの基本的な使い方
次に、@ResponseBodyの使い方を具体的に見ていきましょう。まずはシンプルな例です。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String sayHello() {
return "Hello, Spring!";
}
}
上記のコードでは、sayHelloメソッドが@ResponseBodyアノテーションでマークされているため、/helloエンドポイントにアクセスすると「Hello, Spring!」という文字列がそのままレスポンスとして返されます。
実行結果
Hello, Spring!
3. JSON形式のレスポンスを返す方法
では、もう少し実践的な例として、JSONデータを返す方法を見てみましょう。@ResponseBodyアノテーションは、オブジェクトをJSON形式に変換して返してくれます。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
@ResponseBody
public User getUser() {
return new User("John", "Doe");
}
}
class User {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
上記のコードでは、/userエンドポイントにアクセスすると、以下のようなJSONデータが返されます。
実行結果
{
"firstName": "John",
"lastName": "Doe"
}
4. @ResponseBodyと@RestControllerの違い
@ResponseBodyはメソッドごとに付ける必要がありますが、@RestControllerアノテーションをクラスに付けることで、クラス内のすべてのメソッドに@ResponseBodyが自動的に適用されます。そのため、APIを作成する際は@RestControllerを使うのが一般的です。
例えば、次のようにクラスに@RestControllerを付けるだけで、各メソッドに@ResponseBodyを付ける必要がなくなります。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@GetMapping("/product")
public String getProduct() {
return "Spring Boot Product";
}
}
このように、@RestControllerを使うことでコードがシンプルになります。
5. @ResponseBodyが役立つシーン
Spring Bootを使ってWebアプリケーションを開発する際、@ResponseBodyはREST APIを実装するための基本的な要素です。例えば、以下のようなシーンで役立ちます:
- フロントエンド(JavaScriptやReactなど)からバックエンドにデータをリクエストする場合。
- 外部システムにJSON形式でデータを提供するAPIを作成する時。
- 非同期処理(AJAX)を行うWebアプリケーションで動的にデータをやり取りする時。
これらのシーンでは、@ResponseBodyを使うことで、サーバーとクライアント間のデータのやり取りがスムーズになります。
6. コンテンツネゴシエーションとHttpMessageConverterの仕組み
@ResponseBodyが付いたメソッドは、返り値を適切な形式(JSONやプレーンテキストなど)に変換するために、SpringのHttpMessageConverterが自動で選ばれます。クライアントのAcceptヘッダーやメソッドのproduces指定に応じて、JSONにするかテキストにするかが決まります。
JSONを明示したい場合はproducesを使います。テキストを返したいときはtext/plainを指定できます。
import java.time.Instant;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
class InfoController {
// JSONで返す(Accept: application/json にもマッチ)
@GetMapping(value = "/info", produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> info() {
return Map.of("app", "demo", "version", "1.0.0");
}
// プレーンテキストで返す
@GetMapping(value = "/now", produces = MediaType.TEXT_PLAIN_VALUE)
public String now() {
return Instant.now().toString();
}
}
Spring BootではJacksonが標準で導入されるため、POJOやMapを返すだけでJSONにシリアライズされます。
7. ResponseEntityでステータスコードやヘッダーを制御する
@ResponseBodyはボディの直書きに便利ですが、HTTPステータスやレスポンスヘッダーも制御したい場合はResponseEntityを使います。これにより、成功時の200 OKだけでなく、201 Createdやカスタムヘッダーの付与も簡単に行えます。
import java.net.URI;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
class ProductApi {
@GetMapping("/products/{id}")
public ResponseEntity<Map<String, Object>> get(@PathVariable Long id) {
Map<String, Object> body = Map.of("id", id, "name", "Sample");
return ResponseEntity
.ok()
.header("X-Trace-Id", "abc-123")
.body(body);
}
@PostMapping("/products")
public ResponseEntity<Map<String, Object>> create() {
// 作成処理の想定(ID=101が作成されたとする)
URI location = URI.create("/products/101");
return ResponseEntity
.created(location) // 201 Created と Location ヘッダー
.body(Map.of("result", "created"));
}
}
APIの設計では、適切なステータスコードとヘッダーを返すことで、クライアント側の実装がシンプルかつ堅牢になります。
8. 例外ハンドリングとエラーレスポンスの整形(@RestControllerAdvice)
APIでは、例外発生時にも一貫したJSONエラーを返すことが重要です。@RestControllerAdvice(または@ControllerAdvice+@ResponseBody)を使えば、@ResponseBodyスタイルで統一的なエラー形式を提供できます。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
class NotFoundException extends RuntimeException {
public NotFoundException(String message) { super(message); }
}
record ErrorResponse(int status, String error, String message) {}
@RestController
class UserApi {
@GetMapping("/api/users/{id}")
public UserDto find(@PathVariable Long id) {
// 見つからない場合の想定
throw new NotFoundException("User %d not found".formatted(id));
}
}
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(NotFoundException ex) {
ErrorResponse body = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
HttpStatus.NOT_FOUND.getReasonPhrase(),
ex.getMessage()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(body);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneric(Exception ex) {
ErrorResponse body = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Internal Server Error",
"予期しないエラーが発生しました。"
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
}
}
record UserDto(Long id, String name) {}
例外を一箇所で受けて整形することで、クライアントは常に同じJSON構造を扱え、実装・テスト・ドキュメント化が容易になります。
まとめ
今回の記事では、Springフレームワークにおける@ResponseBodyアノテーションについて詳しく学びました。このアノテーションは、メソッドの戻り値をそのままHTTPレスポンスとして返すために使用されるもので、特にRESTful APIを作成する際に非常に有用です。@Controllerと@RestControllerの違いや、@ResponseBodyを使った文字列やJSON形式のレスポンスを返す具体的な方法についても解説しました。
@ResponseBodyを利用することで、従来のビューを使ったレンダリング処理とは異なり、バックエンドから直接データをクライアントに返すことができ、フロントエンドの開発と分離して効率的にAPIを構築することができます。これにより、シングルページアプリケーション(SPA)やモバイルアプリケーション向けのバックエンドとしてSpring Bootを活用する際の柔軟性が向上します。
また、@RestControllerアノテーションを使用することで、クラス全体に@ResponseBodyが自動的に適用され、API開発の際のコーディングをさらにシンプルにすることができる点も大きなメリットです。特に、JSON形式でデータを返すAPIでは、Javaオブジェクトをそのままレスポンスに変換できるため、データの受け渡しが容易になります。
サンプルプログラム: Spring BootでJSONレスポンスを返す
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SampleController {
@GetMapping("/employee")
public Employee getEmployee() {
return new Employee("Alice", "Software Engineer", 3000);
}
}
class Employee {
private String name;
private String position;
private int salary;
public Employee(String name, String position, int salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
public String getName() { return name; }
public String getPosition() { return position; }
public int getSalary() { return salary; }
}
実行結果
{
"name": "Alice",
"position": "Software Engineer",
"salary": 3000
}
上記の例では、Spring Bootの@RestControllerを利用して、/employeeエンドポイントから社員情報をJSON形式で返すAPIを実装しました。
生徒
「@ResponseBodyを使うと、普通のHTMLページじゃなくてデータを直接返せるんですね!API開発が簡単になりそうです。」
先生
「その通りです。@ResponseBodyを使えば、Springを使ったAPI開発が非常にシンプルになりますね。特にフロントエンドとの連携が多いプロジェクトでは、データをJSON形式で返すことが多いので、このアノテーションの使い方を覚えておくと良いでしょう。」
生徒
「@RestControllerを使えば、全てのメソッドに@ResponseBodyを付ける手間が省けるんですね!」
先生
「その通り。APIを大量に作成する場合、@RestControllerの方が断然効率的です。これで、Spring BootでのREST API開発がもっと楽になるはずです。」
生徒
「今日は本当に勉強になりました!次は、データベース連携の方法も教えてください!」
先生
「もちろんです!次回はSpring Data JPAを使ったデータベース連携について学びましょう。」