SpringBoot——全局异常处理和自定义异常

超、凢脫俗 2022-11-10 10:44 323阅读 0赞

SpringBoot中有一个@ControllerAdvice的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。

  1. @ControllerAdvice
  2. public class GlobalException {
  3. @ExceptionHandler(value =Exception.class)
  4. public String exceptionHandler(Exception e){
  5. System.out.println("未知异常!原因是:"+e);
  6. return e.getMessage();
  7. }
  8. }

上述的示例中,我们对捕获的异常进行简单的二次处理,返回异常的信息,虽然这种能够让我们知道异常的原因,但是在很多的情况下来说,可能还是不够人性化,不符合我们的要求。
那么我们这里可以通过自定义的异常类以及枚举类来实现我们想要的那种数据吧。

一、自定义基础接口类

首先定义一个基础的接口类,自定义的错误描述枚举类需实现该接口。

  1. public interface BaseErrorInfo {
  2. /** 错误码*/
  3. String getResultCode();
  4. /** 错误描述*/
  5. String getResultMsg();
  6. }

二、自定义枚举类

枚举类实现接口,枚举类要有构造方法,不然自定义错误信息报错

  1. import com.example.mybatis.demo.exception.BaseErrorInfo;
  2. public enum CommonNum implements BaseErrorInfo {
  3. /** * 自定义错误信息 */
  4. SUCCESS("200", "成功!"),
  5. BODY_NOT_MATCH("400","请求的数据格式不符!"),
  6. SIGNATURE_NOT_MATCH("401","请求的数字签名不匹配!"),
  7. NOT_FOUND("404", "未找到该资源!"),
  8. INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),
  9. SERVER_BUSY("503","服务器正忙,请稍后再试!")
  10. ;
  11. /** * 错误码 */
  12. private String resultCode;
  13. /** * 错误描述 */
  14. private String resultMsg;
  15. CommonNum(String resultCode, String resultMsg) {
  16. this.resultCode = resultCode;
  17. this.resultMsg = resultMsg;
  18. }
  19. @Override
  20. public String getResultCode() {
  21. return null;
  22. }
  23. @Override
  24. public String getResultMsg() {
  25. return null;
  26. }
  27. }

三、自定义异常类

  1. public class ServiceRuntimeException extends RuntimeException{
  2. /** * 错误码 */
  3. private String code;
  4. /** * 错误信息 */
  5. private String message;
  6. public ServiceRuntimeException(String message){
  7. super(message);
  8. this.message = message;
  9. }
  10. public ServiceRuntimeException(String code,String message){
  11. super(message);
  12. this.code = code;
  13. this.message = message;
  14. }
  15. //Throwable是Error和Exception的父类,用来定义所有可以作为异常被抛出来的类。
  16. public ServiceRuntimeException(String code,String message,Throwable cause){
  17. super(message,cause);
  18. this.code = code;
  19. this.message = message;
  20. }
  21. public ServiceRuntimeException(BaseErrorInfo baseErrorInfo){
  22. super(baseErrorInfo.getResultMsg());
  23. this.code = baseErrorInfo.getResultCode();
  24. this.message = baseErrorInfo.getResultMsg();
  25. }
  26. public ServiceRuntimeException(BaseErrorInfo baseErrorInfo,Throwable cause){
  27. super(baseErrorInfo.getResultMsg(),cause);
  28. this.code = baseErrorInfo.getResultCode();
  29. this.message = baseErrorInfo.getResultMsg();
  30. }
  31. public String getCode() {
  32. return code;
  33. }
  34. public void setCode(String code) {
  35. this.code = code;
  36. }
  37. @Override
  38. public String getMessage() {
  39. return message;
  40. }
  41. public void setMessage(String message) {
  42. this.message = message;
  43. }
  44. }

四、自定义数据格式

自定义数据传输格式

  1. import com.example.mybatis.demo.exception.BaseErrorInfo;
  2. public class ResultGenerator {
  3. /** * 响应代码 */
  4. private String code;
  5. /** * 响应消息 */
  6. private String message;
  7. /** * 响应结果 */
  8. private Object result;
  9. public ResultGenerator(){
  10. }
  11. public ResultGenerator(BaseErrorInfo baseErrorInfo){
  12. this.code = baseErrorInfo.getResultCode();
  13. this.message = baseErrorInfo.getResultMsg();
  14. }
  15. public String getCode() {
  16. return code;
  17. }
  18. public void setCode(String code) {
  19. this.code = code;
  20. }
  21. public String getMessage() {
  22. return message;
  23. }
  24. public void setMessage(String message) {
  25. this.message = message;
  26. }
  27. public Object getResult() {
  28. return result;
  29. }
  30. public void setResult(Object result) {
  31. this.result = result;
  32. }
  33. /** * 成功 * @return */
  34. public static ResultGenerator success(){
  35. return success(null);
  36. }
  37. /** * 成功 * @param data * @return */
  38. public static ResultGenerator success(Object data){
  39. ResultGenerator generator = new ResultGenerator();
  40. generator.setCode(CommonNum.SUCCESS.getResultCode());
  41. generator.setMessage(CommonNum.SUCCESS.getResultMsg());
  42. generator.setResult(data);
  43. return generator;
  44. }
  45. /** * 失败 * @param baseErrorInfo * @return */
  46. public static ResultGenerator error(BaseErrorInfo baseErrorInfo){
  47. ResultGenerator generator = new ResultGenerator();
  48. generator.setCode(baseErrorInfo.getResultCode());
  49. generator.setMessage(baseErrorInfo.getResultMsg());
  50. generator.setResult(null);
  51. return generator;
  52. }
  53. /** * 失败 * @param code * @param message * @return */
  54. public static ResultGenerator error(String code,String message){
  55. ResultGenerator generator = new ResultGenerator();
  56. generator.setCode(code);
  57. generator.setMessage(message);
  58. generator.setResult(null);
  59. return generator;
  60. }
  61. @Override
  62. public String toString() {
  63. return "ResultGenerator{" +
  64. "code='" + code + '\'' +
  65. ", message='" + message + '\'' +
  66. ", result=" + result +
  67. '}';
  68. }
  69. }

五、自定义全局异常处理类

  1. import com.example.mybatis.demo.common.CommonNum;
  2. import com.example.mybatis.demo.common.ResultGenerator;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.web.bind.annotation.ControllerAdvice;
  6. import org.springframework.web.bind.annotation.ExceptionHandler;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. @ControllerAdvice
  9. public class GlobalException {
  10. private static final Logger logger = LoggerFactory.getLogger(GlobalException.class);
  11. /** * 处理自定义异常 * @param e * @return */
  12. @ResponseBody
  13. @ExceptionHandler(value = ServiceRuntimeException.class)
  14. public ResultGenerator serviceRuntimeException(ServiceRuntimeException e){
  15. logger.error("发生业务异常!原因是:{}",e.getMessage());
  16. return ResultGenerator.error(e.getCode(),e.getMessage());
  17. }
  18. /** * 处理空指针异常 * @param e * @return */
  19. @ResponseBody
  20. @ExceptionHandler(value = NullPointerException.class)
  21. public ResultGenerator exceptionHandler(NullPointerException e){
  22. logger.error("发生空指针异常!原因是:",e);
  23. return ResultGenerator.error(CommonNum.BODY_NOT_MATCH);
  24. }
  25. /** * 其它异常 * @param e * @return */
  26. @ResponseBody
  27. @ExceptionHandler(value = Exception.class)
  28. public ResultGenerator exceptionHandler(Exception e){
  29. logger.error("发生空指针异常!原因是:",e);
  30. return ResultGenerator.error(CommonNum.INTERNAL_SERVER_ERROR);
  31. }
  32. }

六、测试

因为这里我们只是用于做全局异常处理的功能实现以及测试,所以这里我们只需在添加一个实体类和一个控制层类即可。

  1. import java.io.Serializable;
  2. public class User implements Serializable {
  3. private static final long serialVersionUID = 1L;
  4. /** 编号 */
  5. private int id;
  6. /** 姓名 */
  7. private String name;
  8. /** 年龄 */
  9. private int age;
  10. public User(){
  11. }
  12. public int getId() {
  13. return id;
  14. }
  15. public void setId(int id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public int getAge() {
  25. return age;
  26. }
  27. public void setAge(int age) {
  28. this.age = age;
  29. }
  30. }
  31. import com.example.mybatis.demo.entity.User;
  32. import com.example.mybatis.demo.exception.ServiceRuntimeException;
  33. import org.springframework.web.bind.annotation.PostMapping;
  34. import org.springframework.web.bind.annotation.RequestBody;
  35. import org.springframework.web.bind.annotation.RequestMapping;
  36. import org.springframework.web.bind.annotation.RestController;
  37. @RestController
  38. @RequestMapping(value = "/api")
  39. public class UserRestController {
  40. @PostMapping("/userInsert")
  41. public boolean insert(@RequestBody User user) {
  42. System.out.println("开始新增...");
  43. //如果姓名为空就手动抛出一个自定义的异常!
  44. if(user.getName()==null){
  45. throw new ServiceRuntimeException("-1","用户姓名不能为空!");
  46. }
  47. return true;
  48. }
  49. @PostMapping("/userUpdate")
  50. public boolean update(@RequestBody User user) {
  51. System.out.println("开始更新...");
  52. //这里故意造成一个空指针的异常,并且不进行处理
  53. String str=null;
  54. str.equals("111");
  55. return true;
  56. }
  57. @PostMapping("/userDelete")
  58. public boolean delete(@RequestBody User user) {
  59. System.out.println("开始删除...");
  60. //这里故意造成一个异常,并且不进行处理
  61. Integer.parseInt("abc123");
  62. return true;
  63. }
  64. }

注意,用postMan测试传值的时候要传json格式,如图:
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,323人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java全局异常处理-定义异常处理

    > 哈喽!大家好,我是旷世奇才李先生 > 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】更有我为大家准备的福利哟,回复【项目】获取我为大家准备的项