SpringMVC异常处理

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来定义我们自己的简单的异常处理类。