@ControllerAdvice和@ExceptionHandler

1. 使用 @ControllerAdvice和@ExceptionHandler处理全局异常

1. 新建异常信息实体类

非必要的类,主要用于包装异常信息。

 1 package com.test.exception.myexception;
 2 
 3 public class ErrorResponse {
 4     private String message;
 5     private String errorTypeName;
 6 
 7     public ErrorResponse(Exception e) {
 8         this(e.getClass().getName(), e.getMessage());
 9     }
10 
11     public ErrorResponse(String errorTypeName, String message) {
12         this.errorTypeName = errorTypeName;
13         this.message = message;
14     }
15 
16     public String getMessage() {
17         return message;
18     }
19 
20     public void setMessage(String message) {
21         this.message = message;
22     }
23 
24     public String getErrorTypeName() {
25         return errorTypeName;
26     }
27 
28     public void setErrorTypeName(String errorTypeName) {
29         this.errorTypeName = errorTypeName;
30     }
31 }

 

2. 自定义异常类型

package com.test.exception.myexception;

public class ReourceNotFoundException extends RuntimeException {
    private String message;

    public ReourceNotFoundException() {
        super();
    }

    public ReourceNotFoundException(String message) {
        super(message);
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

 

3. 新建异常处理类

我们只需要在类上加上@ControllerAdvice注解这个类就成为了全局异常处理类,当然你也可以通过 assignableTypes指定特定的 Controller类,让异常处理类只处理特定类抛出的异常。

 1 package com.test.exception.handler;
 2 
 3 
 4 import com.test.exception.myexception.ErrorResponse;
 5 import com.test.exception.myexception.ReourceNotFoundException;
 6 import org.springframework.http.ResponseEntity;
 7 import org.springframework.web.bind.annotation.ControllerAdvice;
 8 import org.springframework.web.bind.annotation.ExceptionHandler;
 9 import org.springframework.web.bind.annotation.ResponseBody;
10 import org.springframework.web.server.ResponseStatusException;
11 
12 @ControllerAdvice(assignableTypes = {com.test.exception.controller.ExceptionController.class})
13 @ResponseBody
14 public class GlobalExceptionHandler {
15     ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("参数错误!"));
16     ErrorResponse resourseNotFoundResponse = new ErrorResponse(new com.test.exception.myexception.ReourceNotFoundException("Sorry, the resourse not found!"));
17 
18 
19     @ExceptionHandler(value = Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常
20     public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) {
21 
22         if (e instanceof IllegalArgumentException) {
23             return ResponseEntity.status(400).body(illegalArgumentResponse);
24         } else if (e instanceof ReourceNotFoundException) {
25             return ResponseEntity.status(404).body(resourseNotFoundResponse);
26         }else if(e instanceof ResponseStatusException){
27             return ResponseEntity.status(502).body(resourseNotFoundResponse);
28         }
29         return null;
30     }
31 }

 

4. controller模拟抛出异常

 1 package com.test.exception.controller;
 2 
 3 import com.test.exception.myexception.ReourceNotFoundException;
 4 import org.springframework.http.HttpStatus;
 5 import org.springframework.web.bind.annotation.GetMapping;
 6 import org.springframework.web.bind.annotation.RestController;
 7 import org.springframework.web.server.ResponseStatusException;
 8 
 9 @RestController
10 public class ExceptionController {
11 
12     @GetMapping("/illegalArgumentException")
13     public void throwException() {
14         throw new IllegalArgumentException();
15     }
16 
17     @GetMapping("/resourceNotFoundException")
18     public void throwException2() {
19         throw new ReourceNotFoundException();
20 
21     }
22 
23     @GetMapping("/resourceNotFoundException2")
24     public void throwException3() {
25         throw new ResponseStatusException(HttpStatus.BAD_GATEWAY,"The resource not found",new ReourceNotFoundException());
26     }
27 }

 

使用 Get 请求: http://localhost:8080/resourceNotFoundException

{"message":"Sorry, the resourse not found!","errorTypeName":"com.test.exception.myexception.ReourceNotFoundException"}

 


 

3. ResponseStatusException

研究 ResponseStatusException 我们先来看看,通过 ResponseStatus注解简单处理异常的方法(将异常映射为状态码)。

package com.test.exception.myexception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(code = HttpStatus.BAD_GATEWAY)
public class ReourceNotFoundException2 extends RuntimeException {
    public ReourceNotFoundException2() {
    }

    public ReourceNotFoundException2(String message) {
        super(message);
    }
}

 

这种通过 ResponseStatus注解简单处理异常的方法是的好处是比较简单,但是一般我们不会这样做,通过ResponseStatusException会更加方便,可以避免我们额外的异常类。

    @GetMapping("/resourceNotFoundException2")
    public void throwException3() {
        throw new ResponseStatusException(HttpStatus.BAD_GATEWAY,"The resource not found",new ReourceNotFoundException());
    }

 

ResponseStatusException 提供了三个构造方法:

    public ResponseStatusException(HttpStatus status) {
        this(status, null, null);
    }

    public ResponseStatusException(HttpStatus status, @Nullable String reason) {
        this(status, reason, null);
    }

    public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) {
        super(null, cause);
        Assert.notNull(status, "HttpStatus is required");
        this.status = status;
        this.reason = reason;
    }

 

构造函数中的参数解释如下:

  • status : http status
  • reason :response 的消息内容
  • cause : 抛出的异常
上一篇:java-Spring如何管理ExceptionHandler优先级?


下一篇:逆序~~~~