添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

异常处理是任何 Java 应用程序非常重要的特性。每个好的开源框架都允许编写异常处理程序,以便我们可以将其与应用程序代码分开。Spring 框架也允许我们使用Spring注解@ExceptionHandler来做到这一点。@ExceptionHandler 注解用于处理特定处理程序类或处理程序方法中的异常。

1. Spring @ExceptionHandler注解

要在 String MVC 中处理异常,我们可以在控制器类中定义一个方法,并在其上使用注解 @ExceptionHandler。 Spring配置将检测此注解并将该方法注册为参数异常类及其子类的异常处理程序。

1.1 异常处理方法参数

使用此注解注释的处理程序方法可以具有非常灵活的签名。他们可以接受不同类型的参数。例如,异常参数、请求和或响应对象、会话对象、语言环境对象和模型对象等。

1.2 异常处理方法返回类型

与参数类似,返回类型可以是不同的类型。例如,ModelAndView 对象、Model 对象、View 对象、视图名称为 String 等。如果方法通过将响应内容直接写入HttpServletResponse来处理响应本身,我们也可以将方法标记为void。

对于特定的HTTP错误状态,我们可以将 ExceptionHandler注释与@ResponseStatus结合使用。

1.3 异常处理方法示例

@ExceptionHandler(NullPointerException.class)
public ModelAndView handleException(NullPointerException ex){
	ModelAndView modelAndView = new ModelAndView();
	modelAndView.setViewName("error");
	modelAndView.addObject("message", ex.getMessage());
	return modelAndView;
}

现在在该控制器中的任何Web请求的请求处理中遇到NullPointerException,控制都会自动来到这个handler方法。

2. Spring @ExceptionHandler示例

例如,下面的处理程序方法有意返回 NullPointerException。

@RequestMapping(value="/demo/not-exist", method = RequestMethod.GET,  headers="Accept=*/*")
public @ResponseBody ModelAndView oneFaultyMethod(){
	if(true){
		throw new NullPointerException("This error message if for demo only.");
	return null;
}

如果我们部署上述应用程序并在浏览器中点击 URL: /SpringApplication/users/demo/not-exist ,它将显示第一节中配置的“错误”页面。

< %@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
< %@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>
< %@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
< %@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>
		<title>This is sample error page</title>
	</head>
		<h1>This is sample error page : <c:out value="${message}"></c:out></h1>
	</body>
<html>

3. Spring @ExceptionHandler - 处理多个异常

如前所述,上述异常处理程序将处理给定类的实例或参数异常的子类的所有异常。但是,如果我们想为多个不同类型的异常配置@ExceptionHandler,那么我们可以将所有这些异常以数组的形式指定。

@ExceptionHandler({NullPointerException.class, ArrayIndexOutOfBoundsException.class, IOException.class})
public ModelAndView handleException(NullPointerException ex){
	ModelAndView modelAndView = new ModelAndView();
	modelAndView.setViewName("error");
	modelAndView.addObject("message", ex.getMessage());
	return modelAndView;
}

4. Spring @ExceptionHandler使用@ControllerAdvice处理全局异常

如果我们想将异常处理逻辑集中到一个能够处理从任何处理程序类控制器类抛出的异常的类中——那么我们可以使用@ControllerAdvice 注解。默认情况下,@ControllerAdvice 中的方法全局应用于所有控制器。我们可以创建一个类并在顶部添加@ControllerAdvice 注解。然后为其中的每种特定异常类添加@ExceptionHandler 方法。

请注意,我们使用 ResponseEntityExceptionHandler 扩展了异常处理程序类。对于希望通过 @ExceptionHandler 方法跨所有 @RequestMapping 方法提供集中式异常处理的 @ControllerAdvice 类来说,它是一个方便的基类。

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
	@ExceptionHandler(Exception.class)
	public final ResponseEntity handleAllExceptions(Exception ex, WebRequest request) {
		List details = new ArrayList<>();
		details.add(ex.getLocalizedMessage());
		ErrorResponse error = new ErrorResponse(ApplicationConstants.SERVER_ERROR, details);
		return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
	@ExceptionHandler(RecordNotFoundException.class)
	public final ResponseEntity handleUserNotFoundException(RecordNotFoundException ex,
												WebRequest request) {
		List details = new ArrayList<>();
		details.add(ex.getLocalizedMessage());
		ErrorResponse error = new ErrorResponse(ApplicationConstants.RECORD_NOT_FOUND, details);
		return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}

请创建特定于应用程序的异常并处理它们。

@ResponseStatus(HttpStatus.NOT_FOUND)
public class RecordNotFoundException extends RuntimeException{
	private static final long serialVersionUID = 1L;
	public RecordNotFoundException(String exception) {
        super(exception);
}
@XmlRootElement(name = "error")
public class ErrorResponse {
    public ErrorResponse(String message, List<String> details) {
        super();
        this.message = message;
        this.details = details;
    private String message;
    private List<String> details;
	public String getMessage() {
		return message;
	public void setMessage(String message) {
		this.message = message;
	public List<String> getDetails() {
		return details;
	public void setDetails(List<String> details) {
		this.details = details;