处理异常
Spring提供了多种方式将异常转为响应:
- Spring会将部分异常转成HTTP状态码;
- 在异常上使用注解@ResponseStatus将异常映射为某一个http状态码;
- 使用注解@ExceptionHandler处理异常。
Spring会将部分异常转成HTTP状态码
Spring默认可以将一些异常转成http状态码,如下表
在异常上使用注解@ResponseStatus将异常映射为某一个http状态码
以查找spittle方法为例,如果没有找到,那么抛出自定义异常。
public class SpittleNotFoundException extends RuntimeException {
}
@RequestMapping(value = "/{spittleId}", method = RequestMethod.GET)
public String spittle(
@PathVariable("spittleId") String spittleId,
Model model) {
Spittle spittle = spittleRepository.findOne(spittleId);
if(spittle == null) {
throw new SpittleNotFoundException();
}
model.addAttribute(spittle);
return "spittle";
}
接着,如果抛出这个异常,在响应中转为404。
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Spittle Not Found")
public class SpittleNotFoundException extends RuntimeException {
}
编写异常处理的方法
在保存Spittle时,如果这个Spittle已经存在,那么,抛出异常。
public class DulplicatedSpittleException extends RuntimeException {
}
@RequestMapping(method = RequestMethod.POST)
public String saveSpittle(Spittle spittle, Model model) {
try {
spittleRepository.save(
new Spittle(null, spittle.getMessage(), new Date(),
spittle.getLongitude(), spittle.getLatitude()));
return "redirect:spittles";
} catch (DulplicatedSpittleException e) {
return "error/dulplicate";
}
}
但是这个只是Java处理异常的方式。接下来,我们将业务逻辑和处理异常的逻辑分开。
- 控制器方法
@RequestMapping(method = RequestMethod.POST)
public String saveSpittle(Spittle spittle, Model model) {
spittleRepository.save(
new Spittle(null, spittle.getMessage(), new Date(),
spittle.getLongitude(), spittle.getLatitude()));
return "redirect:spittles";
}
- 异常处理方法
@ExceptionHandler(DulplicatedSpittleException.class)
public String handleDulplicate() {
return "error/dulplicate";
}
@ExceptionHandler(value=异常类.class)
注意: 这个异常处理方法要在控制器类中定义,那么,在这个控制器方法中,如果出现DulplicatedSpittleException,都会执行这个异常处理方法。
其实,我们还可以更进一步,让异常处理方法处理所有控制器处理器方法的同一种异常,就是下面要说的控制器通知类。
为控制器添加通知
在一个类上添加注解@ControllerAdvice,那么这个类就是控制器通知类,我们可以在该类里面定义一个或多个如下注解修饰的方法:
- @ExceptionHandler
- @InitBinder
- @ModelAttribute
注解@ControllerAdvice里面已经定义了@Component注解,只要开启组件扫描,那么控制器通知类就会交给了Spring容器。
下面定义一个控制器通知类,来处理所有控制器方法中的DulplicateSpittleException异常。
@ControllerAdvice
public class AppWideExceptionHandler {
@ExceptionHandler(DulplicateSpittleException.class)
public String dulplicateSpittleHandler() {
return "error/dulplicate";
}
}