3.

Spring No mapping found for HTTP request エラーの対処

編集
この記事の要点
  • No mapping found for HTTP request with URI ... in DispatcherServletSpring MVC がリクエスト URL に対応する Controller を見つけられない
  • 原因 ①: コントローラに @RequestMapping / @GetMapping 等が付いていない
  • 原因 ②: コントローラが @ComponentScan 範囲外のパッケージにある
  • 原因 ③: URL パスのタイポ / コンテキストパスの不一致
  • 対処: 起動ログに表示されるマッピング一覧を確認、actuator/mappings で詳細確認

 

エラーの状況

WARN  org.springframework.web.servlet.PageNotFound -
No mapping found for HTTP request with URI [/api/users/123]
in DispatcherServlet with name 'dispatcherServlet'

Spring MVC の DispatcherServlet がリクエストを受け取ったものの、そのパスに対応する Controller のメソッドが登録されていない場合に発生します。クライアントには 404 が返ります。

主な原因と対処

原因 1: @RequestMapping が付いていない

// ダメな例
@Controller
public class UserController {
    public User getUser(Long id) {  // ← @GetMapping 等の指定なし
        return userService.findById(id);
    }
}

// 修正
@Controller
public class UserController {
    @GetMapping("/api/users/{id}")  // ← パスを指定
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
}

原因 2: @ComponentScan の範囲外

Controller が Spring の自動検出パッケージ外にあると Bean として登録されません。

// メインクラスのパッケージが com.example
@SpringBootApplication
public class MyApp { ... }

// 同じ com.example.controllers ならOK
@Controller
public class UserController { ... }

// com.other.controllers だと検出されない!
// 修正: スキャン範囲を広げる
@SpringBootApplication(scanBasePackages = {"com.example", "com.other"})
public class MyApp { ... }

原因 3: @Controller / @RestController が付いていない

// ダメな例 - 普通の Bean
@Component
public class UserController {
    @GetMapping("/api/users/{id}")
    public User get(...) { ... }
}

// 修正
@RestController  // または @Controller
public class UserController { ... }

原因 4: コンテキストパスの考慮漏れ

Spring Boot で server.servlet.context-path を設定している場合、URL の先頭にそのパスが付きます:

# application.properties
server.servlet.context-path=/api/v1

// Controller のパスが /users なら、実際の URL は
// http://localhost:8080/api/v1/users
// http://localhost:8080/users  ← これは 404

原因 5: URL のタイポ

クライアント側のリクエスト URL とコントローラのパスが一致しているか確認:

@GetMapping("/api/users/{id}")   // 末尾スラッシュなし

// クライアント
fetch("/api/users/123")   // OK
fetch("/api/users/123/")  // ← 末尾スラッシュ。Spring の設定次第で 404

# Spring 5.3+ デフォルトでは / の有無を区別する
# 統一したい場合
spring.mvc.pathmatch.matching-strategy=ant-path-matcher  # 古い動作

原因 6: HTTP メソッドの不一致

// GET メソッドだけマッピング
@GetMapping("/users")
public List list() { ... }

// クライアントが POST で来ると 405 Method Not Allowed
// (404 ではないが似た問題)

// 複数メソッド対応
@RequestMapping(value = "/users", method = {RequestMethod.GET, RequestMethod.POST})

登録済みマッピングの確認

① 起動ログを見る

Spring Boot 起動時にマッピングがログに出力されます:

INFO ... RequestMappingHandlerMapping -
  s.w.s.m.m.a.RequestMappingHandlerMapping: Mapped
  "{[/api/users/{id}],methods=[GET]}" onto
  public User com.example.UserController.getUser(java.lang.Long)

② Spring Boot Actuator

actuator を有効にすると /actuator/mappings で全マッピング一覧が見られます:

# application.properties
management.endpoints.web.exposure.include=mappings,health,info

# 起動後
$ curl http://localhost:8080/actuator/mappings | jq .

# レスポンス例
{
  "contexts": {
    "application": {
      "mappings": {
        "dispatcherServlets": {
          "dispatcherServlet": [
            {
              "predicate": "{GET /api/users/{id}}",
              "handler": "com.example.UserController#getUser(Long)",
              ...
            }
          ]
        }
      }
    }
  }
}

静的リソースが 404 になる場合

このエラーは静的ファイル(画像・CSS・JS)でも発生します:

// 配置場所
// src/main/resources/static/css/app.css
// → http://localhost:8080/css/app.css でアクセス可能

// templates/ や webapp/ も Spring Boot は自動認識
// 認識しないなら次の確認
// 1. ファイルパスが間違っていないか
// 2. spring.mvc.static-path-pattern が変えられていないか
// 3. WebMvcConfigurer の addResourceHandlers で別パスにしていないか

デバッグ Tips

① ログレベルを DEBUG に

# application.properties
logging.level.org.springframework.web=DEBUG
logging.level.org.springframework.web.servlet.PageNotFound=DEBUG

② エラーハンドリング

デフォルトの 404 ページをカスタマイズ:

@ControllerAdvice
public class NotFoundHandler {
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity handle(NoHandlerFoundException ex) {
        return ResponseEntity.status(404).body(
            Map.of("error", "Not Found", "path", ex.getRequestURL())
        );
    }
}

# application.properties で NoHandlerFoundException を例外に
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. java.lang.IllegalStateException: CGLIB is required to process @Configuration classes
  2. Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  3. No mapping found for HTTP request with URI ... in DispatcherServlet with name ...
  4. An internal error occurred during: "Building UI model". com/google/common/base/Function
  5. No identifier specified for entity : ...
  6. org.hibernate.hql.internal.ast.QuerySyntaxException: table_name is not mapped
  7. No compiler is provided in this environment
  8. java.sql.SQLException: The server time zone value ' ... ' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone
  9. Caused by: java.lang.RuntimeException: Executing an update/delete query
  10. Not supported for DML operations
  11. Field ... required a bean of type ... hat could not be found.
  12. Annotation-specified bean name ' ... ' for bean class [ ... ] conflicts with existing, non-compatible bean definition of same name and class [...]
  13. Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.
  14. Exception in thread "main" java.lang.UnsupportedClassVersionError