JavaでTODOアプリを制作しよう12 使われていないHttpMethodでリクエストが来た時の処理・サーバー内でエラーが起きた時の処理


こんにちは。

前回までに引き続き例外処理の実装を進めていきましょう!

TODOアプリ作成リンク集

1: [超基礎の理解] MVCの簡単な説明
2: [雛形を用意する] Spring Initializrで雛形を作ってHello worldしたい
3: [MySQLとの接続・設定・データの表示] MySQLに仮のデータを保存 -> 全取得 -> topに表示する
4: [POST機能] 投稿機能の実装
5: [PATCH機能] TODOの表示を切り替える
6: [JpaRepositoryの簡単な使い方] 検索機能の実装
7: [Thymeleaf テンプレートフラグメントで共通化] Headerの作成
8: [PUT機能] 編集機能の実装
9: [微調整]TODOの表示を作成日時が新しい順にソートする + 期日のデフォルトを今日の日付にする
10: [springで例外処理] 例外処理についての簡単なまとめ
11: [springで例外処理] 存在しないIDのTODOにアクセスした時の例外処理
12: [springで例外処理] 使われていないHttpMethodでリクエストが来た時の処理・サーバー内でエラーが起きた時の処理

HttpMethodに関する簡単な説明

HTTPメソッドって一体何?と思われる方も多いと思うので今回はまずざっくりですがどういうものなのかを説明してみようと思います。

ウェブサイトにアクセスするとはどういう事なのかを軽く理解する

まず理解して頂きたいのが

インターネットのサイトにアクセスする = ネット上にあるサーバーにアクセスする

ということです。

このサーバー内にはHPを表示させたり色々な機能(例えばTODO機能とか)が置いてあり、アクセスされれば製作者の想定通りに動くはずです。

ちなみに現在作成しているTODOアプリはウェブ上には公開されていませんが、私たちのローカル上に仮のサーバーを作っているので、アプリをRunするとlocalhost:8080にアクセスできるようになっているのです。

URLとHttpMethod

さてサーバーにアクセスする事によってHPを利用できるということが分かりましたが

アクセスする際には何が必要でしょうか?

まずはそのサイトのアドレスが必要になりますね!

サイトが家みたいなものだとしたらアドレスは住所(番地)になるでしょう!

普通にHPを利用するだけでしたらアドレスだけを知っていれば良いのですが、実際にウェブ製作者としてHPを作るとなると、もう一つの概念HttpMethodを理解しなければなりません。

実はサイトにアクセスする際にはHttpMethodというものをつかってアクセスをリクエストしています。

サイトのURL + HttpMethodの同時をリクエストすることで、サイト側はユーザーがどのページにアクセスしたいのかを判別しています!

例えば以下の例を見てみます。

com/example/todo/TodoController.java
@Controller
public class TodoController {

    @GetMapping("/top")
    public String top(Model model){
        return "top";
    }

これはTODOアプリのトップページを表示する部分ですが注目したいのが

@GetMapping("/top")の部分です。

このアノテーションはユーザーが

サイトのURL/topGETメソッドでリクエストしてきた時に行いたい処理というのを明記する役割があります。

よってユーザーがそのようなリクエストをしてきた場合は関数topが走るというわけです。

サイトが家でアドレスが住所であればHttpMethodは鍵のようなものかもしれません。

家の中のトップページを表示させる部屋に入るのに必要な鍵といった感じです。

同じURLでもHttpMethodを変えてアクセスすることもできる

例えば下記の例をみてましょう

com/example/todo/TodoController.java
@Controller
public class TodoController {

    @GetMapping("/top")
    public String top(Model model){
        return "top";
    }

    @PostMapping("/top")
    public String top(Model model){
        //投稿処理
    }

POSTメソッドで/topにアクセスした時の処理を追加してみました。

アクセスするURL自体は同じですがリクエスト時のHTTPメソッドを変更することで違う処理を実現することができます。

様々なHttpMethod

さてHttpMethodにはいろいろな種類がありますが、代表的な物とその役割をまとめてみます。

GET
サイト内のリソースを取得する際に使われる(例:トップページにDBから取得したTODO(リソース)を表示する)
POST
何かを投稿したりする際に使われる(例:TODO投稿時」)
PUT
データの内容を置換する(例:ファイルをアップロードして丸々中身を変える)
PATCH
データの一部もしくは全体を更新、修正して保存する(例:TODO編集時」)

使われていないHttpMethodでリクエストされた時の例外処理

com/example/todo/exception/TodoControllerAdvice.java
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public String badMethod() {
        log.warn("Bad Request");
        return "error/405.html";
    }
templates/error/405.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>405</title>
</head>
<body>
405!
</body>
</html>

上記2つを追加してあげましょう。

ControllerAdviceについては前回の記事を見れば書き方がわかると思います。

ここではHttpRequestMethodNotSupportedException(存在しないHttpMethodのリクエストが投げられた時に起こる例外クラスです。)が起きた時に405.htmlを表示するようにしています。

せっかくなので実際に存在しないHttpMethodをCurlコマンドを使って投げてみましょう!

Todoアプリを起動してターミナルで

$ curl -X POST "http://localhost:8080/top"

と打ちます。これは本来はGETでしか処理を実装していない/topに対してPOSTでアクセスリクエストを投げています。

すると結果は

この様になるはずです!想定通り405が表示されていることがわかります。

ついでサーバー内でエラーが起きた時の設定もしておく

com/example/todo/exception/TodoControllerAdvice.java
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public String otherErrors() {
        log.error("Something went wrong");
        return "error/500.html";
    }
templates/error/500.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>500</title>
</head>
<body>
500!
</body>
</html>

これらを追加することでExceptionクラスが起きた際に500エラーのページを表示できるようになりました!