LoginSignup
1
0

More than 1 year has passed since last update.

【ちょっとアレンジ】Spring bootのControllerクラスで定義したパスを一覧として取得する

Posted at

やりたいこと

APIの本数が増えてきたので、実装済みのAPIのURIの一覧を出力したい

Spring bootのControllerクラスで定義したパスを一覧として取得するの内容の踏襲でほぼいけたのですが、PJの実装ルール的に少し考慮が必要な部分があったので、その部分を書き記しておきます

アレンジした部分

クラスに@RequestMappingを付与して基幹部分のパスを、メソッドにリクエストメソッドに応じたアノテーションを付与して相対パスを定義するルールなので、以下2点実現できるように手を加えました。

  • リクエストメソッドに応じたアノテーションからリクエストメソッドと相対パスを出力する
  • クラスに定義された親パスとメソッドに定義された相対パスの関係性が分かるように出力する
参考記事のControllerクラスをループする部分改変.java
        // 略
        for (BeanDefinition def : beanSet) {
            Class<?> clazz = Class.forName(def.getBeanClassName());
            RequestMapping requestMappingClazz = clazz.getAnnotation(RequestMapping.class);
            // Controllerクラスに設定されているパスを出力
            System.out.println(requestMappingClazz.value()[0]);
            // Controllerメソッドに設定されているパスを出力
            Arrays.stream(clazz.getDeclaredMethods()).forEach(a -> writeUri(a));
        }
        // 略
Controllerメソッドに設定されているリクエストメソッドとパスを出力(詳細).java
    private static void writeUri(Method method) {
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (Objects.nonNull(getMapping)) {
            writeValue("GET", getMapping.value());
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (Objects.nonNull(postMapping)) {
            writeValue("POST", postMapping.value());
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (Objects.nonNull(putMapping)) {
            writeValue("PUT", putMapping.value());
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (Objects.nonNull(deleteMapping)) {
            writeValue("DELETE", deleteMapping.value());
        }
    }

    private static void writeValue(String methodType, String[] value) {
        System.out.println("\t" + methodType + "\t" + (value.length == 0 ? "/" : value[0]));
    }

(余談ですが、アノテーションのvalueってなんとなくStringと思い込んでいましたが、String配列でした。ひとつのクラス・メソッドに対して複数のパスをマッピングできるみたいですが、需要あります…?)

最後に

出力イメージはこんな感じです。超便利!

/hoge1/fuga1
    GET    /
    POST   /piyo1
/hoge2/fuga2
    PUT    /piyo2
    DELETE /piyo3

今回は質よりスピード重視だったので妥協してしまいましたが、
調べる中で、@{リクエストメソッド}Mappingクラスは@RequestMappingのエイリアス的な位置付けであることが分かりました。
@AliasForあたりの詳細が解析出来たらwriteUri()に記載しているアノテーション毎の処理は共通化出来そうな気がしています。
(余力があったらチャレンジしてみます)

GetMapping.java
package org.springframework.web.bind.annotation
// 略
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// @RequestMappingのメソッドを指定
@RequestMapping(
    method = {RequestMethod.GET}
)
public @interface GetMapping {
    // @RequestMappingの同名設定値のエイリアスであることを示す?
    @AliasFor(
        annotation = RequestMapping.class
    )
    String name() default "";
    // 略
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0