遇到 400、404、405、406、415,到底是谁抛的?是 Spring MVC 的哪个组件?@ControllerAdvice 能不能接到?这篇用一个注册在最前面的异常解析器记录异常类和抛出位置,把常见的 4xx 逐个复现。
没有任何映射的路径:GET /nope → 404 Not Found;org.springframework.web.servlet.resource.NoResourceFoundException ← ResourceHttpRequestHandler.handleRequest 映射是 /only-get,请求多了结尾斜杠:GET /only-get/ → 404 Not Found;org.springframework.web.servlet.resource.NoResourceFoundException ← ResourceHttpRequestHandler.handleRequest 不存在的静态资源:GET /x.png → 404 Not Found;org.springframework.web.servlet.resource.NoResourceFoundException ← ResourceHttpRequestHandler.handleRequest Controller 里抛 ResponseStatusException(NOT_FOUND):GET /rse → 404 Not Found;org.springframework.web.server.ResponseStatusException ← Main.rse
404 多数来自静态资源处理器;Controller 也可能主动抛。
只映射了 GET 的路径用 POST:POST /only-get → 405 Method Not Allowed;org.springframework.web.HttpRequestMethodNotSupportedException ← RequestMappingInfoHandlerMapping.handleNoMatch Allow=GET consumes=application/json 的接口发 text/plain:POST /json → 415 Unsupported Media Type;org.springframework.web.HttpMediaTypeNotSupportedException ← RequestMappingInfoHandlerMapping.handleNoMatch produces=application/json 的接口 Accept: application/xml:GET /prod → 406 ;org.springframework.web.HttpMediaTypeNotAcceptableException ← RequestMappingInfoHandlerMapping.handleNoMatch
在选 Controller 方法阶段就被拒绝,抛出处是 handleNoMatch。
缺少必填的 @RequestParam:GET /param → 400 Bad Request;org.springframework.web.bind.MissingServletRequestParameterException ← RequestParamMethodArgumentResolver.handleMissingValueInternal @RequestParam int 传了 abc:GET /param?n=abc → 400 Bad Request;org.springframework.web.method.annotation.MethodArgumentTypeMismatchException ← AbstractNamedValueMethodArgumentResolver.convertIfNecessary @PathVariable int 传了 abc:GET /path/abc → 400 Bad Request;org.springframework.web.method.annotation.MethodArgumentTypeMismatchException ← AbstractNamedValueMethodArgumentResolver.convertIfNecessary 缺少必填的 @RequestHeader:GET /header → 400 Bad Request;org.springframework.web.bind.MissingRequestHeaderException ← RequestHeaderMethodArgumentResolver.handleMissingValue 缺少必填的 @CookieValue:GET /cookie → 400 Bad Request;org.springframework.web.bind.MissingRequestCookieException ← AbstractCookieValueMethodArgumentResolver.handleMissingValue 要表单参数 a 却只发了 b:POST /form → 400 Bad Request;org.springframework.web.bind.MissingServletRequestParameterException ← RequestParamMethodArgumentResolver.handleMissingValueInternal
六种 400,四个异常类。
JSON 语法错误:POST /json → 400 Bad Request;org.springframework.http.converter.HttpMessageNotReadableException ← AbstractJacksonHttpMessageConverter.readJavaType 请求体为空:POST /json → 400 Bad Request;org.springframework.http.converter.HttpMessageNotReadableException ← RequestResponseBodyMethodProcessor.readWithMessageConverters @Valid 校验不通过:POST /valid → 400 Bad Request;org.springframework.web.bind.MethodArgumentNotValidException ← RequestResponseBodyMethodProcessor.resolveArgument 要 multipart 文件却发了表单:POST /mp → 500 Internal Server Error;org.springframework.web.multipart.MultipartException ← RequestParamMethodArgumentResolver.handleMissingValueInternal URL 里有非法的百分号编码:GET /%zz → 400 ;(没有进入 Spring MVC 的异常解析)
HttpMessageNotReadableException、校验异常、multipart 的 500,以及 Tomcat 层的 400。