【Springboot】异常处理的一点总结

本文介绍了SpringBoot中异常处理的四种方法:Controller内异常处理、使用@ExceptionHandler注解、@ControllerAdvice注解和ResponseEntityExceptionHandler。通过示例展示了如何自定义异常并进行全局捕获。强调了在不同场景下选择合适异常处理方式的重要性,并提供了自定义异常的详细步骤,包括创建异常、捕获异常、Controller处理和全局异常处理器。注意避免将敏感异常信息直接暴露给前端,建议进行模糊处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

异常处理与简单示例

1. Controller内异常处理

2. 使用`@ExceptionHandler`注解

3. 使用`@ControllerAdvice`注解

4. 使用`ResponseEntityExceptionHandler`

自定义异常

1、自定义一个异常

2、实现类调用

3、Controller

4、统一异常捕获

5、注意事项

总结

使用场景

使用场景详细说明

Controller内try-catch

@ExceptionHandler注解

@ControllerAdvice/@RestControllerAdvice

继承ResponseEntityExceptionHandler


异常处理与简单示例

在Spring Boot中,异常处理通常可以通过以下几种方式来实现:

1. Controller内异常处理:在Controller中使用`try-catch`块直接处理异常。

2. 使用`@ExceptionHandler`注解:在Controller中定义方法来处理局部异常。

3. 使用`@ControllerAdvice`或`@RestControllerAdvice`注解:创建一个全局异常处理器,它可以捕获整个应用程序的异常。

4. 使用`ResponseEntityExceptionHandler`:扩展`ResponseEntityExceptionHandler`类来提供全局异常处理,并覆盖其中的方法。

下面是使用这些方法的Java代码示例:

1. Controller内异常处理

@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/item/{id}")
    public ResponseEntity<?> getItem(@PathVariable("id") String id) {
        try {
            // logic to get item
        } catch (ItemNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
        }
    }
}

2. 使用`@ExceptionHandler`注解

@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/item/{id}")
    public String getItem(@PathVariable("id") String id) {
        // logic to get item
        return "item";
    }

    @ExceptionHandler(ItemNotFoundException.class)
    public ResponseEntity<String> handleItemNotFoundException(ItemNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
    }
}

3. 使用`@ControllerAdvice`注解

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ItemNotFoundException.class)
    public ResponseEntity<String> handleItemNotFoundException(ItemNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGeneralException(Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
    }
}

4. 使用`ResponseEntityExceptionHandler`

@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status,
                                                                  WebRequest request) {
        // custom logic
        return new ResponseEntity<>("Custom message", HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(ItemNotFoundException.class)
    protected ResponseEntity<Object> handleItemNotFound(ItemNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

在上述示例中,`ItemNotFoundException`是一个自定义异常,你需要根据自己的业务逻辑来创建和抛出它。这些方法可以根据需要组合使用,例如在Controller中处理特定的异常,同时有一个全局异常处理器来处理整个应用程序的其他异常。

自定义异常

想实现的场景是, 

指定的异常直接抛到前端, 

捕获的异常后log.error(), 前端模糊返回"操作异常"

1、自定义一个异常

public class MyException extends RuntimeException {

    private static final long serialVersionUID = -1004916162498956491L;

    public MyException(String msg) {
        super(msg);
    }

}

2、实现类调用

@Override
    public int add(Demo demo) {
        if (null == demo.getName()) {
            throw new MyException("名称为空!");
        }
        return demoMapper.add(demo);
    }

3、Controller

    @PostMapping(value = "/add")
    public String add(@RequestBody Demo demo) {
        try {
            demoService.add(demo);
        } catch (MyException e) {
            return Resule.fail(e.getMsg());
        } catch (Exception e) 
            log.error("异常:{}",e)
            return Resule.fail();
        }
        return Resule.success();
    }

4、统一异常捕获

package com.xx.xx.manage.exception;

/**
 * @author libusi
 */
@Slf4j
@RestControllerAdvice
public class ApplicationExceptionHandler {

    protected static final Logger logger = LoggerFactory.getLogger(ApplicationExceptionHandler.class);


    @Autowired
    public ApplicationExceptionHandler(LogSaveUtil logSaveUtil) {
        this.logSaveUtil = logSaveUtil;
    }


    /**
     * 异常详细信息
     *
     * @return BaseResponse
     */
    @ExceptionHandler(MyException.class)
    public String msgException(Throwable t) {
        ...
        return Resule.fail();
    }

}

5、注意事项

        自定义异常捕获不到,  那是因为controller没有catch MyException,  或者全局捕获异常的问题

一般情况下, 不要把未知异常的错误信息抛到前端,  要模糊处理返回

总结

        当涉及到Spring Boot中异常处理的不同方法时,我们可以比较它们的优缺点以及它们各自的最佳使用场景。下面是一个简化的对比表格,用于概述每种方法:

使用场景

方法优点缺点使用场景
Controller内try-catch- 简单直接<br>- 控制器内部局部化处理- 代码重复<br>- 没有集中管理异常- 小型应用<br>- 快速原型开发<br>- 特定控制器需要特殊处理时
@ExceptionHandler注解- 减少代码重复<br>- 控制器内部集中处理异常- 只限于单个控制器<br>- 可能导致每个控制器都有重复的异常处理- 控制器内部有多个处理方法需要处理相同的异常
@ControllerAdvice/@RestControllerAdvice- 全局异常处理<br>- 集中管理异常<br>- 可以处理多个控制器的异常- 如果过于通用,可能会捕获并隐藏问题- 大型应用<br>- 需要统一异常响应格式时
继承ResponseEntityExceptionHandler- 全局异常处理<br>- 可以重用Spring的内置异常处理机制- 比自定义@ControllerAdvice更为复杂<br>- 可能需要更多的定制- 需要细粒度控制异常响应<br>- 扩展Spring的默认异常处理

使用场景详细说明

Controller内try-catch

        适用于不需要复杂异常处理机制的小型项目或者是在特定的控制器方法中需要特殊处理异常的情况。

@ExceptionHandler注解

        当你有一个控制器,并且它有多个处理方法需要处理相同的异常时,你可以在该控制器内部使用@ExceptionHandler注解来集中处理这些异常,从而减少代码重复。

@ControllerAdvice/@RestControllerAdvice

        在大型应用程序中,通常需要一个集中的方式来处理所有控制器抛出的异常。@ControllerAdvice或@RestControllerAdvice提供了一种便捷的方式来定义全局异常处理逻辑,这样你就可以保持一个统一的异常响应格式,同时也便于维护。

继承ResponseEntityExceptionHandler

        当你需要更细粒度的控制异常响应时,或者想要扩展和利用Spring MVC提供的默认异常处理机制时,可以选择扩展ResponseEntityExceptionHandler。这种方法适用于需要高度定制异常处理行为的复杂应用程序。

        在实际应用中,开发者可以根据项目的具体需求和复杂度选择最适合的异常处理方法,也可以将不同的方法组合起来使用,以达到最佳的效果。

有用请点赞,养成良好习惯!

疑问、交流、鼓励请留言!


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕白Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值