在Spring Boot项目中可以完成全局异常的统一处理,能够给用户提供友好的错误提示信息。下面演示本项目的异常处理过程。首先自定义异常:
package com.example.thymeleafdemo.exception;import lombok.Data;/*** 自定义异常*/@Datapublic class MyBusinessException extendsRuntimeException { privatestatic final long serialVersionUID = 1L; private intcode; privateString message; publicMyBusinessException(String message) {super(message);this.message = message; } publicMyBusinessException(int code, String message) { super(message);this.code = code;this.message = message; }}
然后设置全局异常的捕获处理方法,代码如下:
package com.example.thymeleafdemo.exception;import com.example.thymeleafdemo.event.Result;import lombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.MissingServletRequestParameterException;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.RestControllerAdvice;import java.util.StringJoiner;/*** 全局异常处理*/@Slf4j@RestControllerAdvicepublic classGlobalExceptionHandler {/** * 处理自定义异常 */@ExceptionHandler(MyBusinessException.class)public Result handleBizException(MyBusinessException ex) { Result<Object> result = newResult<>(); result.setCode(ex.getCode()); result.setMessage(ex.getMessage()); return result;}
/** * 参数校验不通过异常 */ @ExceptionHandler(MethodArgumentNotValidException.class)public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { StringJoiner sj = newStringJoiner(";");ex.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage())); Result<Object> result = newResult<>(); result.setCode(505); result.setMessage(sj.toString()); return result;}/** * Controller参数绑定错误 */@ExceptionHandler(MissingServletRequestParameterException.class)public Result handleMissingServletRequestParameterException(MissingServletRequestParameterExceptionex) { Result<Object> result = newResult<>(); result.setCode(506); result.setMessage(ex.getMessage()); return result;}
/** * 其他未知异常 */@ExceptionHandler(value = Exception.class)public Result handleException(Exception ex) { log.error(ex.getMessage(), ex); Result<Object> result = newResult<>(); result.setCode(507); result.setMessage("服务器内部错误"); return result;}}
以上处理方法中分别处理了MyBusinessException类的异常,又针对参数校验不通过的异常分别进行了不同的处理。下面再写一个Controller入口,分别处理系统中可能发生的两种不同的异常,即产品空指针的异常和自定义异常:
package com.example.thymeleafdemo.exception;import com.example.thymeleafdemo.event.Result;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublic class ExceptionController { /** * 系统内部错误 */@GetMapping("/exception") publicResult testException() { int i =1 / 0;Result<Object> result = new Result<>();result.setCode(200);result.setMessage("success");result.setData("cc"); returnresult; } /** * 自定义异常 */ @GetMapping("/myException") publicResult testMyexception() { thrownew MyBusinessException(508, "自定义的异常"); } }
启动当前项目,访问localhost:8080/exception,接口返回的异常信息如图1所示。再访问localhost:8080/myException得到自定义异常的错误提示,如图2所示。全局的异常处理完成后,对用户屏蔽服务器内部错误,只给用户简单的提示。
图1 服务器内部错误提示
图2 自定义异常的错误提示
统一异常处理通过@ControllerAdvice注解向控制器发送通知,并接收所有Controller层的通知,再结合@ExceptionHandler注解对指定的异常进行捕获处理,最后将结果返回给用户。
声明:本文选自机械工业出版社的《Spring Boot企业级项目开发实战》一书,略有修改,经出版社授权刊登于此。
送书环节
代码语言:javascript复制感谢大家一直以来的陪伴与支持
送书活动参与方法