7.3 处理异常
到现在为止,在Spittr应用中,我们假设所有的功能都正常运行。但是如果某个地方出错的话,该怎么办呢?当处理请求的时候,抛出异常该怎么处理呢?如果发生了这样的情况,该给客户端什么响应呢?
不管发生什么事情,不管是好的还是坏的,Servlet请求的输出都是一个Servlet响应。如果在请求处理的时候,出现了异常,那它的输出依然会是Servlet响应。异常必须要以某种方式转换为响应。
Spring提供了多种方式将异常转换为响应:
- 特定的Spring异常将会自动映射为指定的HTTP状态码;
- 异常上可以添加
@ResponseStatus
注解,从而将其映射为某一个HTTP状态码; - 在方法上可以添加
@ExceptionHandler
注解,使其用来处理异常。
处理异常的最简单方式就是将其映射到HTTP状态码上,进而放到响应之中。接下来,我们看一下如何将异常映射为某一个HTTP状态码。
7.3.1 将异常映射为HTTP状态码
在默认情况下,Spring会将自身的一些异常自动转换为合适的状态码。表7.1列出了这些映射关系。
表7.1 Spring的一些异常会默认映射为HTTP状态码
pring异常 | 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
无法找到适合处理请求的控制器方法,那么将会抛出NoSuchRequestHandlingMethodException
异常,最终的结果就是产生404状态码的响应(Not Found)。
尽管这些内置的映射是很有用的,但是对于应用所抛出的异常它们就无能为力了。幸好,Spring提供了一种机制,能够通过@ResponseStatus
注解将异常映射为HTTP状态码。
为了阐述这项功能,请参考SpittleController
中如下的请求处理方法,它可能会产生HTTP 404状态(但目前还没有实现):
@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(
@PathVariable("spittleId") long spittleId,
Model model) {
Spittle spittle = spittleRepository.findOne(spittleId);
if (spittle == null) {
throw new SpittleNotFoundException();
}
model.addAttribute(spittle);
return "spittle";
}
在这里,会从SpittleRepository
中,通过ID检索Spittle
对象。如果findOne()
方法能够返回Spittle
对象的话,那么会将Spittle
放到模型中,然后名为spittle
的视图会负责将其渲染到响应之中。但是如果findOne()
方法返回null