REST APIと通常のコントローラーの違いとは?初心者でもわかるSpringの基本
新人
「先輩、SpringのREST APIってよく聞きますけど、普通のコントローラーとどう違うんですか?」
先輩
「いい質問だね。実は両方とも@Controllerを使うことができるけど、使い方や目的がちょっと違うんだよ。」
新人
「どっちも同じに見えるんですが、どんな場面で使い分けるんですか?」
先輩
「それじゃあまず、REST APIとは何かから説明していこう。」
1. REST APIとは何か
REST APIとは、インターネット上でデータのやり取りを行うための仕組みのひとつです。特に、HTTPリクエスト(GETやPOSTなど)を使って、サーバーにデータを要求したり、送信したりします。
たとえば、ブラウザやPostmanといったツールを使って、あるURLにアクセスすると、サーバーからJSON形式でデータが返ってくるような仕組みです。
Springでは、@Controllerと@ResponseBodyを組み合わせて、REST APIのような振る舞いをさせることができます。
以下は、名前を送るとメッセージを返す簡単なREST APIの例です。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ApiController {
@GetMapping("/api/greet")
@ResponseBody
public String greet(@RequestParam String name) {
return name + "さん、こんにちは!";
}
}
この例では、@ResponseBodyを使うことで、メッセージがHTML画面ではなく、HTTPレスポンスの本文として返されています。つまり、画面の代わりに文字列やJSONなどのデータだけを返すのがREST APIの特徴です。
そして、Postmanなどのツールを使ってhttp://localhost:8080/api/greet?name=山田にアクセスすると、次のようなレスポンスが返ってきます。
山田さん、こんにちは!
このように、REST APIでは画面を作らず、バックエンドの処理結果だけを返すのが基本です。
2. 通常のコントローラーとはどう違うのか
一方、通常のコントローラーは、主にHTML画面を返すために使われます。たとえば、ユーザーがブラウザでURLを開いたときに、テンプレートエンジン(Thymeleafなど)で作られた画面が表示されるように設計されます。
以下に、通常のコントローラーの簡単な例を示します。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ViewController {
@GetMapping("/hello")
public String helloPage(Model model) {
model.addAttribute("message", "こんにちは、画面表示の世界へようこそ!");
return "hello";
}
}
このコードでは、返り値として"hello"というHTMLテンプレート名を返しています。つまり、Springはhello.htmlというファイルを探して表示します。
このように、通常のコントローラーでは、ユーザーがブラウザでページを見るためのHTML画面を返すのに対し、REST APIはデータだけを返すという違いがあります。
まとめると、以下のような違いがあります。
- 通常のコントローラー:HTML画面を返す
- REST API:データ(文字列やJSONなど)を返す
そして、Springではどちらも@Controllerを使って実現できますが、目的に応じて@ResponseBodyを付けたり、テンプレートを返したりして使い分けることが大切です。
3. Springで通常のコントローラーを書く場合の構成(HTML画面を返す例)
Springで通常のコントローラーを使ってHTML画面を表示する場合は、テンプレートファイルを用意して、画面に表示したいデータをModelに詰めて返します。
テンプレートファイルは、通常resources/templatesフォルダ内に配置され、Thymeleafなどのテンプレートエンジンを利用します。Spring Bootでは、依存関係を追加するだけで自動的に認識されます。
以下は、名前を入力してあいさつメッセージを表示するHTML画面を返すコントローラーの例です。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingViewController {
@GetMapping("/greet")
public String greetPage(@RequestParam(defaultValue = "ゲスト") String name, Model model) {
model.addAttribute("userName", name);
return "greet";
}
}
そして、greet.htmlのようなテンプレートを作成すれば、以下のように名前付きのメッセージが画面に表示されます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>挨拶画面</title>
</head>
<body>
<h1 th:text="'こんにちは、' + ${userName} + 'さん!'">こんにちは、ゲストさん!</h1>
</body>
</html>
このように、通常のコントローラーでは、ユーザーがブラウザを通じてWebページを見られるよう、HTMLファイルを生成して返すのが基本的な構成です。
画面のレイアウトやデザインも含めて提供できるのが通常のコントローラーの大きな特徴です。
4. SpringでREST API風に書く構成(JSONなどのデータを返す例)
一方で、REST API風にコントローラーを書く場合は、画面を返さずにJSONなどのデータを直接HTTPレスポンスとして返す構成になります。
このとき使うのが@ResponseBodyです。@ResponseBodyを付けると、返り値がそのままHTTPレスポンスの本文としてクライアントに送信されます。
以下の例では、名前と年齢を含むPersonクラスの情報をJSON形式で返しています。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JsonApiController {
@GetMapping("/api/person")
@ResponseBody
public Person getPerson() {
return new Person("田中太郎", 28);
}
public static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
}
このエンドポイントにアクセスすると、次のようなJSON形式のレスポンスが返ります。
{
"name": "田中太郎",
"age": 28
}
このような構成は、画面を持たないシステム同士の通信(API通信)に向いており、PostmanやAjaxなどを使って、データの送受信のみを行うケースに適しています。
たとえば、フロントエンドがVue.jsやReactなどで作られている場合は、バックエンド側はREST API形式でデータのみを返すような設計が一般的です。
5. 同じ@Controllerでも使い方次第で役割が変わることの説明
ここまでの説明でわかるとおり、@Controllerは使い方によって、まったく異なる動きをします。重要なのは、@ResponseBodyを付けるかどうかです。
以下に整理しておきます。
@Controllerのみ → HTMLテンプレートを返す(画面表示用)@Controller + @ResponseBody→ JSONや文字列などのデータを返す(APIレスポンス)
つまり、同じアノテーションであっても、目的によって動きが変化するという点が、Springの柔軟で便利な特徴のひとつです。
たとえば以下のように、条件によって画面表示とデータレスポンスを切り替えることも理論上可能です。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class HybridController {
@GetMapping("/hybrid")
public String handleRequest(@RequestParam(required = false) String json, Model model) {
if ("true".equals(json)) {
return "forward:/hybrid/api";
}
model.addAttribute("message", "HTML画面を表示します");
return "hybrid";
}
@GetMapping("/hybrid/api")
@ResponseBody
public String apiResponse() {
return "これはJSONレスポンスです";
}
}
このように、同じ@Controllerを使っても、画面向けとAPI向けの両方に対応できるため、開発の柔軟性が高く、初心者にも理解して使いやすい構造になっています。
ただし、@RestControllerのような簡易アノテーションもありますが、今回の記事では@Controllerに限定して説明しています。
このような基礎知識を理解しておくと、今後のSpringアプリ開発において、自分がどんな仕組みを作っているのかを明確に意識しながらコーディングできるようになります。
6. それぞれの使いどころと選び方(画面が必要な場合/データだけ返したい場合)
ここで、通常のコントローラーとREST API風のコントローラー、それぞれの使いどころについて整理しておきましょう。
画面が必要な場合、つまりユーザーにWebブラウザを通じて情報を見せたいときには、@Controllerのみを使ってHTMLテンプレートを返します。ログイン画面や入力フォーム、検索結果の表示など、ユーザーと対話するUIが必要な場合に適しています。
一方で、データだけ返したい場合、つまり他のシステムやJavaScriptからデータをやり取りしたいときは、@Controllerに@ResponseBodyを付けて、JSONや文字列としてレスポンスを返す形式にします。スマートフォンアプリやJavaScriptの非同期通信、外部システムとの連携などに向いています。
以下に具体的な使い分けのポイントを示します。
- ユーザーが画面を見ながら操作する → HTMLテンプレートを返す通常のコントローラー
- 画面を使わずデータのやり取りだけしたい → JSONや文字列を返すAPIレスポンス方式
このように目的に応じて使い分けることが大切です。最初は画面表示を作りながら、徐々にREST APIの構成にも慣れていきましょう。
7. よくある初心者の誤解(@Controllerで画面が表示されない・JSONが返らない原因)
初心者がSpringの開発でつまずきやすいポイントのひとつが、「画面が表示されない」「JSONが返ってこない」といった問題です。その原因と対策をいくつか紹介します。
画面が表示されない場合
- テンプレートファイルが存在しない:たとえば
helloという画面を返そうとしているのに、hello.htmlがresources/templatesに存在していないと、エラーになります。 - テンプレートエンジンの依存関係が未設定:
Thymeleafなどのテンプレートエンジンを使うには、build.gradleに適切な依存関係を追加する必要があります。 - コントローラーが正しくマッピングされていない:
@GetMappingなどのアノテーションがURLと一致していないと、ブラウザでアクセスしても反応がありません。
JSONが返らない場合
- @ResponseBodyがついていない:コントローラーメソッドに
@ResponseBodyがついていないと、返り値はテンプレート名と見なされ、HTMLテンプレートを探してしまいます。 - 戻り値のクラスが正しく定義されていない:データクラスに
getterがないと、JSONに変換できずに空のレスポンスになることがあります。 - JSONを返すURLにブラウザでアクセスしている:HTML画面を期待しているのにJSONだけ返ってくると、ブラウザが正しく表示できず真っ白になることがあります。
このように、画面表示とAPIレスポンスは別物なので、目的に応じて@ResponseBodyの有無やテンプレートの存在を確認することが大切です。
8. Postmanやブラウザでの確認方法の違い(HTMLとAPIの挙動の違い)
最後に、Postmanとブラウザでの動作確認の違いについて解説します。これは初心者がREST APIを試すときに非常に重要なポイントです。
ブラウザで確認できるのはHTML画面
ブラウザは主にHTMLページの表示を目的としたツールです。したがって、@Controllerからテンプレートを返す通常の画面表示には向いています。
たとえば、以下のようにURLを直接入力することで、画面が表示されます。
http://localhost:8080/greet?name=鈴木
このとき、greet.htmlというテンプレートが存在していれば、ブラウザに挨拶メッセージが表示されます。
Postmanで確認するのはAPIレスポンス
一方、PostmanはHTTPリクエストを送信してレスポンスを確認するためのツールです。HTML画面ではなく、JSONや文字列のようなデータを確認したいときに便利です。
たとえば、次のようなURLにアクセスすれば、Postmanの画面上にJSONレスポンスが表示されます。
http://localhost:8080/api/person
このように、HTMLテンプレートを返すか、JSONなどのデータを返すかによって、確認方法を使い分ける必要があります。
よくある間違い
- JSONを返すAPIをブラウザで開いて「真っ白で何も出ない」と思ってしまう
- 画面用のURLをPostmanで開いてHTMLが見えてしまい混乱する
このような誤解を防ぐには、自分が今どんなレスポンスを期待しているのかを意識して、Postmanとブラウザを適切に使い分けることが大切です。
また、PostmanではリクエストのパラメータやHTTPメソッドも自由に変更できるため、APIの動作確認に最適です。