7.3.1 将异常映射为 HTTP 状态码
在默认情况下,Spring 会将自身的一些异常自动转换为合适的状态码。表 7.1 列出了这些映射关系。
Spring 异常
HTTP 状态码
BindException
400 - Bad Request
ConversionNotSupportedException
500 - Internal Server Error
HttpMediaTypeNotAcceptableException
406 - Not Acceptable
HttpMediaTypeNotSupportedException
415 - Unsupported Media Type
HttpMessageNotReadableException
400 - Bad Request
HttpMessageNotWritableException
500 - Internal Server Error
HttpRequestMethodNotSupportedException
405 - Method Not Allowed
MethodArgumentNotValidException
400 - Bad Request
MissingServletRequestParameterException
400 - Bad Request
MissingServletRequestPartException
400 - Bad Request
NoSuchRequestHandlingMethodException
404 - Not Found
TypeMismatchException
400 - Bad Request
表 7.1 中的异常一般会由 Spring 自身抛出,作为 DispatcherServlet 处理过程中或执行校验时出现问题的结果。例如,如果 DispatcherServlet 无法找到适合处理请求的控制器方法,那么将会抛出 NoSuchRequestHandlingMethod-Exception 异常,最终的结果就是产生 404 状态码的响应(Not Found)。
尽管这些内置的映射是很有用的,但是对于应用所抛出的异常它们就无能为力了。幸好,Spring 提供了一种机制,能够通过 @ResponseStatus 注解将异常映射为 HTTP 状态码。
为了阐述这项功能,请参考 SpittleController 中如下的请求处理方法,它可能会产生 HTTP 404 状态(但目前还没有实现):
1
@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
2
public String spittle(
3
@PathVariable("spittleId") long spittleId,
4
Model model) {
5
Spittle spittle = spittleRepository.findOne(spittleId);
6
if (spittle == null) {
7
throw new SpittleNotFoundException();
8
}
9
model.addAttribute(spittle);
10
return "spittle";
11
}
Copied!
在这里,会从 SpittleRepository 中,通过 ID 检索 Spittle 对象。如果 findOne() 方法能够返回 Spittle 对象的话,那么会将 Spittle 放到模型中,然后名为 spittle 的视图会负责将其渲染到响应之中。但是如果 findOne() 方法返回 null 的话,那么将会抛出 SpittleNotFoundException 异常。现在 SpittleNot-FoundException 就是一个简单的非检查型异常,如下所示:
1
package spittr.web;
2
3
public class SpittleNotFoundException extends RuntimeException {
4
}
Copied!
如果调用 spittle() 方法来处理请求,并且给定 ID 获取到的结果为空,那么 SpittleNotFoundException(默认)将会产生 500 状态码(Internal Server Error)的响应。实际上,如果出现任何没有映射的异常,响应都会带有 500 状态码,但是,我们可以通过映射 SpittleNotFoundException 对这种默认行为进行变更。
当抛出 SpittleNotFoundException 异常时,这是一种请求资源没有找到的场景。如果资源没有找到的话,HTTP 状态码 404 是最为精确的响应状态码。所以,我们要使用 @ResponseStatus 注解将 SpittleNotFoundException 映射为 HTTP 状态码 404。
1
package spittr.web;
2
3
import org.springframework.http.HttpStatus;
4
import org.springframework.web.bind.annotation.ResponseStatus;
5
6
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found")
7
public class SpittleNotFoundException extends RuntimeException {
8
}
Copied!
在引入 @ResponseStatus 注解之后,如果控制器方法抛出 SpittleNotFound-Exception 异常的话,响应将会具有 404 状态码,这是因为 Spittle Not Found。
Last modified 2yr ago
Copy link