AIによる要約
@GetMappingは一覧表示や詳細表示など、基本的にサーバーの状態を変更しない取得処理へ使います。@PostMappingは登録、申請、ファイル取込など、状態を変更する処理へ使います。@RequestMappingはController全体の共通パスや、HTTPメソッド以外の条件も含めて指定するときに使います。削除をGETで実装せず、成功後はredirectすることが現場で重要な確認点です。


Spring BootのControllerでは、@GetMappingと@PostMappingを頻繁に使います。書き方は似ていますが、単に「画面表示はGET、ボタンはPOST」と暗記すると、検索、削除、確認画面などで判断に迷います。
HTTPメソッドは、URLと合わせて処理の意味を表します。使い方を誤ると、ブラウザの再読み込みで二重登録されたり、リンクを開いただけでデータが削除されたりします。この記事では社員管理画面を例に、新人が実装レビューで説明できる基準を整理します。
この記事のポイント
- GETは基本的に参照、POSTは登録や業務処理に使う
- 同じURLでもHTTPメソッドが違えば別の処理として定義できる
- Controller共通パスはクラスの
@RequestMappingへまとめる - 登録成功後はredirectし、再読み込みによる二重送信を防ぐ
@GetMappingと@PostMappingの基本的な違い
| 観点 | @GetMapping | @PostMapping |
|---|---|---|
| 主な用途 | 一覧、詳細、検索結果、入力画面 | 登録、申請、実行、ファイル取込 |
| データ変更 | 原則として行わない | 行う処理に使う |
| パラメータ | クエリ文字列やパスに現れやすい | Formやリクエストボディで送ることが多い |
| 再読み込み | 同じ参照結果を得られる設計が基本 | 二重実行へ注意が必要 |
GETは安全なメソッドとして、サーバーの状態を変えないことが期待されます。アクセスログや最終閲覧日時など技術的な情報が更新される場合はありますが、注文登録や削除のような利用者が意図する業務データを変更させません。
POSTは、同じリクエストを2回送ると2件登録される可能性があります。そのため、画面の二重送信防止、サーバー側の重複チェック、トークンなど、処理に応じた対策を考えます。
@GetMappingの実装例
一覧表示や詳細表示、登録画面の初期表示はGETが基本です。
@Controller
@RequestMapping("/employees")
public class EmployeeController {
@GetMapping
public String list(Model model) {
model.addAttribute("employees", employeeService.findAll());
return "employees/list";
}
@GetMapping("/{employeeId}")
public String detail(
@PathVariable long employeeId,
Model model) {
model.addAttribute("employee", employeeService.findById(employeeId));
return "employees/detail";
}
@GetMapping("/new")
public String showCreateForm(Model model) {
model.addAttribute("employeeForm", new EmployeeForm());
return "employees/form";
}
}
クラスの@RequestMapping("/employees")と、各メソッドのパスを組み合わせます。たとえば詳細表示はGET /employees/123になります。
@PostMappingの実装例
登録や申請など、サーバーの状態を変更する処理をPOSTで受けます。
@PostMapping
public String create(
@Valid @ModelAttribute("employeeForm") EmployeeForm form,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "employees/form";
}
long employeeId = employeeService.create(form);
return "redirect:/employees/" + employeeId;
}
入力エラーでは同じテンプレートを直接返し、登録成功後に詳細画面へredirectしています。登録後のURLをブラウザで再読み込みしても、GETの詳細表示が実行されるため、POSTが再送信されにくくなります。
@RequestMappingはいつ使うのか
@GetMappingは@RequestMapping(method = RequestMethod.GET)を読みやすくした合成アノテーションです。POST、PUT、PATCH、DELETEにも対応する専用アノテーションがあります。
// 同じ意味だが、通常は@GetMappingの方が意図を読みやすい
@RequestMapping(path = "/employees", method = RequestMethod.GET)
public String list() {
return "employees/list";
}
@GetMapping("/employees")
public String listReadable() {
return "employees/list";
}
メソッド単位では@GetMappingなどを使い、Controller全体の共通パスをクラスの@RequestMappingへ置く形がよく使われます。また、consumes、produces、ヘッダー条件などをまとめて指定する場合も@RequestMappingが候補です。
@RestController
@RequestMapping(
path = "/api/employees",
produces = MediaType.APPLICATION_JSON_VALUE)
public class EmployeeApiController {
// ...
}
同じURLをGETとPOSTで使ってもよい
URLだけでなく、HTTPメソッドも処理を識別する条件です。/employeesをGETで呼べば一覧取得、POSTで呼べば新規登録という設計にできます。
@GetMapping("/employees")
public List<EmployeeResponse> list() {
return employeeService.findAll();
}
@PostMapping("/employees")
public ResponseEntity<EmployeeResponse> create(
@Valid @RequestBody EmployeeCreateRequest request) {
EmployeeResponse created = employeeService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
HTML画面では/employees/newをGETの入力画面、/employeesをPOSTの登録先にする構成もよくあります。URL命名だけを真似せず、既存プロジェクトの規約に揃えます。
削除処理を@GetMappingにしてはいけない
// 避ける: URLを開いただけで削除される
@GetMapping("/{employeeId}/delete")
public String delete(@PathVariable long employeeId) {
employeeService.delete(employeeId);
return "redirect:/employees";
}
GETはリンクの先読み、クローラー、ブラウザ履歴など、人が削除ボタンを押す以外の理由でもアクセスされ得ます。GETでデータを変更すると、意図しない実行につながります。
HTML FormであればPOSTを使い、REST APIであれば@DeleteMappingを検討します。CSRF対策、権限確認、対象の存在確認もHTTPメソッドとは別に必要です。
@PostMapping("/{employeeId}/delete")
public String deleteFromScreen(@PathVariable long employeeId) {
employeeService.delete(employeeId);
return "redirect:/employees";
}
@DeleteMapping("/api/employees/{employeeId}")
public ResponseEntity<Void> deleteFromApi(@PathVariable long employeeId) {
employeeService.delete(employeeId);
return ResponseEntity.noContent().build();
}
PUT・PATCH・DELETEはどう使い分けるか
| アノテーション | 主な意味 | 例 |
|---|---|---|
@PutMapping | 対象全体を置き換える更新 | 社員情報全体の更新 |
@PatchMapping | 対象の一部を変更 | 在籍ステータスだけ変更 |
@DeleteMapping | 対象を削除 | 社員情報を削除 |
実際の業務システムでは、更新もPOSTへ統一する画面設計や、論理削除を使う設計があります。HTTPの一般原則を理解した上で、API仕様書と既存Controllerの方針を優先してください。
405 Method Not Allowedが出たときの確認点
URLは合っているのにHTTPメソッドがControllerの定義と一致しない場合、405エラーになることがあります。404と混同せず、次を確認します。
- HTML Formの
methodがControllerと一致しているか - JavaScriptのfetchやAjaxで指定したmethodが正しいか
- クラスとメソッドのパスを結合したURLが正しいか
- 同じパスを別Controllerが重複定義していないか
- PUTやDELETEをHTML Formから送るための構成が整っているか
<!-- Controllerが@PostMappingならmethod="post"を指定する -->
<form th:action="@{/employees}" method="post">
<!-- 入力欄 -->
<button type="submit">登録</button>
</form>
URLとメソッドを設計する手順
- 何を対象にする処理かを名詞で決める
- 参照か、登録・変更かを判断する
- GET、POST、PUT、PATCH、DELETEから意味に合うものを選ぶ
- 成功時、入力エラー時、対象不存在時の遷移を決める
- Controller、HTML、JavaScript、API仕様書のメソッドを揃える
アノテーションから考え始めず、「この操作は何を変えるのか」を先に文章にします。
現場レビューでよくある指摘
// レビューコメント例 削除処理がGETになっています。 リンクの先読みでも実行され得るため、POSTまたはDELETEへ変更してください。 // レビューコメント例 登録成功後もテンプレートを直接返しているため、再読み込みで再POSTされます。 登録完了後は詳細画面へredirectしてください。 // レビューコメント例 全メソッドで"/employees"が重複しています。 クラスの@RequestMappingへ共通パスをまとめると読みやすくなります。
提出前のセルフチェック
- GETで業務データを登録・更新・削除していないか
- 登録や申請はPOSTになっているか
- 成功後にredirectし、二重送信を防いでいるか
- ControllerとHTML FormのHTTPメソッドが一致しているか
- 共通パスをクラスの
@RequestMappingへまとめられるか - API仕様書とステータスコードの方針に合っているか
HTTPとWebアプリの基本を学ぶ参考書
Springのアノテーションだけでなく、HTTPメソッドやステータスコードの意味を押さえると、Controller設計の判断が安定します。Webの基本へ立ち戻りたいときに役立つ一冊です。
Webを支える技術
HTTP・URI・RESTを、Webアプリ開発の土台から理解する。
RequestParamやRequestBodyの暗記だけでは見えにくい、Web通信の基本原則を整理できます。
- HTTPの仕組みから理解したい
- RESTやURIの設計意図を学びたい
当サイトはAmazonアソシエイト・プログラムの参加者です。価格・在庫・配送条件はAmazonでご確認ください。
この記事とあわせて読みたい
まとめ
@GetMappingは一覧や詳細などの参照処理、@PostMappingは登録や申請などサーバーの状態を変更する処理へ使います。Controller共通のパスはクラスの@RequestMappingへまとめると、各メソッドの役割を読みやすくできます。
削除をGETにしないこと、登録成功後にredirectすること、HTMLやJavaScriptとControllerのHTTPメソッドを揃えることが、現場で特に重要な確認点です。アノテーションの形ではなく、操作の意味からHTTPメソッドを選びましょう。
