SpringMVC处理异常的方式有以下四种:
- 使用 @ResponseStatus
- 使用 @ExceptionHandler
- 使用 @ControllerAdvice
- 使用 HandlerExceptionResolver
使用 @ResponseStatus
@ResponseStatus可以被用于指定的方法或者类上,可以返回指定的HTTP Response状态码和原因。
使用方式如下:
NotFoundException.java
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "NOT FOUND.")
public class NotFoundException extends RuntimeException {
public NotFoundException() {
super();
}
}
TestController.java
@RequestMapping("/test")
public String test() {
boolean isException = true; //模拟了有异常的时候
if (isException) {
throw new NotFoundException(); //抛出异常
}
return "success";
}
使用 @ExceptionHandler
可以在Controller类的一些方法上添加@ExceptionHandler注解,该方法就可以用来处理该Controller类抛出的特定异常。
TestController.java
//一个预定义的异常转换为一个HTTP状态代码
@ResponseStatus(value=HttpStatus.CONFLICT, reason="Data already present")
@ExceptionHandler(SQLException.class)
public void dataConflict() {
System.out.println("----Caught SQLException----");
}
//通过ModelAndView处理
@ExceptionHandler(Exception.class)
public ModelAndView myError(Exception exception) {
System.out.println("----Caught Exception----");
ModelAndView mav = new ModelAndView();
mav.addObject("exc", exception);
mav.setViewName("myerror");
return mav;
}
//直接返回到error页面
@ExceptionHandler({SQLException.class,DataAccessException.class})
public String handDatabaseError(){
return "error";
}
这样的异常处理方式比较简单,扩展性好。我们可以创建一个处理异常的BaseExController基类,所有的要处理异常的Controller类都继承于该基类。
使用 @ControllerAdvice
在ControllerAdvice的javadoc上有一段话,大致意思是@ControllerAdvice通常用来定义@ExceptionHandler,
@InitBinder,@ModelAttribute方法,适用于所有@RequestMapping方法。
GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IOException.class)
public ModelAndView myError(Exception exception) {
ModelAndView mav = new ModelAndView();
mav.addObject("exception", exception);
mav.setViewName("globalerror");
return mav;
}
@ExceptionHandler(KeywordNotFoundException.class)
public String notFound() {
return "404";
}
}
使用 HandlerExceptionResolver
SpringMVC通过HandlerExceptionResolver处理程序的异常。SpringMVC中默认使用了:
- DefaultHandlerExceptionResolver:HandlerExceptionResolver的默认实现。
- ResponseStatusExceptionResolver:处理使用了@ResponseStatus注解的方法。
- ExceptionHandlerExceptionResolver:处理使用了@ExceptionHandler注解的方法(当然也包括了使用了@ControllerAdvice)
我们可以通过实现HandlerExceptionResolver接口来定义自己的异常处理器,达到统一处理异常的目的。
最简单的,我们可以使用SpringMVC默认的SimpleMappingExceptionResolver来进行简单的统一异常处理。使用方法如下(因为使用了Spring boot,所以直接使用Java Configuration):
@Configuration
@ComponentScan("cn.webfuse.exception.demos")
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean(name = "simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties errorMaps = new Properties();
errorMaps.setProperty("ElectricityNotFoundException", "error");
errorMaps.setProperty("NullPointerException", "error");
errorMaps.setProperty("DatabaseException", "databaseError");
resolver.setExceptionMappings(errorMaps);
resolver.setDefaultErrorView("error");
resolver.setExceptionAttribute("exc");
return resolver;
}
}
当然我们也可以直接继承SimpleMappingExceptionResolver来定义我们自己的简单的异常处理类。