【问题标题】:Spring boot @ExceptionHandler not catching subclass exceptionSpring boot @ExceptionHandler 没有捕获子类异常
【发布时间】:2020-06-05 23:47:15
【问题描述】:

我为异常处理创建了一些子类。该方法引发子类异常。我为超类和子类制作了@ExceptionHandler。但只有在没有处理超类异常(handleSuperException(SuperclassExceptionexception e))时,才会处理子类异常。 SubClassAException、SubClassBException、SubClassCException 扩展了 SuperclassExceptionexception。

 public class Controller @PostMapping("/path/") {
       public ResponseEntity<String> method() throws   SuperclassException{
 }
    @ExceptionHandler(SuperclassException.class)   
public ResponseEntity handleSuperException(SuperclassExceptionexception e) {
       //hadle superclass related
    }

 @ExceptionHandler({SubClassAException.class, SubClassBException.class, SubClassCException.class}) 
public ResponseEntity handleSubClassException(SuperclassExceptionexception e) {
//handle more specific
}

但是即使抛出了子类异常,它也永远不会进入handleSubClassException。

【问题讨论】:

  • 我相信这就像catch 子句,你必须在超类之前指定子类。翻转两种方法。 This Spring article 也是这样显示的,尽管它没有明确说明订单。
  • 我也做了翻页。没有帮助
  • 我想知道是不是因为子类处理程序的签名与父类的签名相同。尝试为任何子类异常创建一个单独的处理程序,看看它是否被调用。
  • 我只是看了一下Spring Boot 2.2.0 / Spring 5.2.0的源码,只有@ExceptionHandler注解中没有列出异常时才使用参数类型。然后将实际异常与列出的异常进行匹配,并选择与实际异常相比 深度 最小的列出异常,即应始终选择更具体的子类异常,而不管方法顺序如何。跨度>
  • 在超类异常处理方法中也尝试使用 instanceof 很奇怪。不知何故,它没有进入 if 子句

标签: java spring-boot exception


【解决方案1】:

无法重现!

这里是Minimal, Reproducible Example,使用 Spring Boot 2.2.0 (Spring 5.2.0) 测试。

package web.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class FailController {

    @GetMapping("/dmz/fail")
    public String failSuper() {
        throw new SuperclassException("failSuper()");
    }

    @GetMapping("/dmz/failA")
    public String failA() {
        throw new SubClassAException("failA()");
    }

    @GetMapping("/dmz/failB")
    public String failB() {
        throw new SubClassBException("failB()");
    }

    @ExceptionHandler(SuperclassException.class)
    public ResponseEntity<?> handleSuperException(SuperclassException e) {
        return ResponseEntity.badRequest().body("handleSuperException: " + e);
    }

    @ExceptionHandler({SubClassAException.class, SubClassBException.class}) 
    public ResponseEntity<?> handleSubClassException(SuperclassException e) {
        return ResponseEntity.badRequest().body("handleSubClassException: " + e);
    }

}

class SuperclassException extends RuntimeException {
    public SuperclassException(String message) {
        super(message);
    }
}

class SubClassAException extends SuperclassException {
    public SubClassAException(String message) {
        super(message);
    }
}

class SubClassBException extends SuperclassException {
    public SubClassBException(String message) {
        super(message);
    }
}

我使用的是/dmz/,所以 Spring Security 设置不需要登录。在普通的 Spring Boot 设置中,当然不需要。

输出 (http://localhost:8080/dmz/fail)

handleSuperException: web.controller.SuperclassException: failSuper()

输出 (http://localhost:8080/dmz/failA)

handleSubClassException: web.controller.SubClassAException: failA()

输出 (http://localhost:8080/dmz/failB)

handleSubClassException: web.controller.SubClassBException: failB()

【讨论】:

    猜你喜欢
    • 2016-12-16
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多