「@RequestMapping」アノテーションのパスの先頭は「スラッシュ(“/”)」は省略できることを知りました。
というのも、こんな感じのControllerを見ていた際、アノテーションでのパス指定の箇所にスラッシュがないものが混ざってました。
@RequestMapping("/api/hoge/panda") class PandaController( ) { @GetMapping("/{userId}") fun get( @PathVariable userId: Long ) = hogehoge @PostMapping("import") fun import( @RequestParam userIds: Set<Long> ) = hogehoge
@PostMapping("import")
のところだけ先頭のパスがないですね。
ちなみに@GetMapping
のようなメソッドに付与しているアノテーションは@RequestMapping
のショートカットアノテーションです。
さて、疑問に思ったのは、これだと
/api/hoge/panda/import
ではなく、/api/hoge/pandaimport
になってしまうのではないかと。
しかし動かしてみると問題なく動きます。マジか。
なんでスラッシュなしで動くのか?
2012年のstackoverflowが引っかかりました。
Use or not leading slash in value for @RequestMapping. Need official docs or point to Spring source? / gavenkoa
回答にはこんなことが書いてあります。
It does not matter: If the path does not start with an
/
then Spring (DefaultAnnotationHandlerMapping) will add it.
なるほど、ということでGithubで該当箇所を見に行ってみます。
if (!typeLevelPattern.startsWith("/")) { typeLevelPattern = "/" + typeLevelPattern; }
確かにDefaultAnnotationHandlerMapping
内で先頭がスラッシュで始まっていなかった場合を判定して付与してくれています。
DefaultAnnotationHandlerMappingはSpring5から削除されてた
でもよくみたらSpring3.2の時点でDefaultAnnotationHandlerMapping
クラスはDeprecatedでした。
Spring5系の現在はクラス自体削除されてます。
じゃあ、今はどこで実装されているか、というと
PatternsRequestCondition
クラスのinitPatterns
で実装されてました。
private static Set initPatterns(String[] patterns) { if (!hasPattern(patterns)) { return EMPTY_PATH_PATTERN; } Set result = new LinkedHashSet<>(patterns.length); for (String pattern : patterns) { if (StringUtils.hasLength(pattern) && !pattern.startsWith("/")) { pattern = "/" + pattern; } result.add(pattern); } return result; }
ちなみにinitPatterns
を呼び出しているPatternsRequestCondition
メソッドは5.2系からDeprecatedになってます。Deprecate use of path extensions in request mapping and content negotiation
まとめ
と、いうわけで@RequestMapping
のパスは先頭にスラッシュがない場合でも内部で付与して処理してくれる。
環境
Spring Boot: 2.3.8.RELEASE
コメント