兰州网站外包,鞍山高新区网站,图书购物网站开发总结,网站自助建站系统在 Spring Boot 中#xff0c;可以通过使用 ControllerAdvice 注解和 ExceptionHandler 注解来实现全局异常拦截。
RestControllerAdvice
RestControllerAdvice 是 Spring Framework 提供的注解#xff0c;用于定义全局异常处理类#xff0c;并且结合 ExceptionHandler 注…在 Spring Boot 中可以通过使用 ControllerAdvice 注解和 ExceptionHandler 注解来实现全局异常拦截。
RestControllerAdvice
RestControllerAdvice 是 Spring Framework 提供的注解用于定义全局异常处理类并且结合 ExceptionHandler 注解来处理异常。与 ControllerAdvice 不同的是RestControllerAdvice 默认情况下会将返回值转换为 JSON 格式。
RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法}
ResponseStatus(...)
ResponseStatus(HttpStatus.BAD_REQUEST) 是一个注解用于在异常处理方法上指定特定的HTTP状态码。当该异常被抛出时将返回指定的HTTP状态码给客户端。
RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法/*** 缺少请求体异常处理器* param e 缺少请求体异常 使用get方式请求 而实体使用RequestBody修饰*/ResponseStatus(HttpStatus.BAD_REQUEST)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},请求体缺失{}, requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}
}
ExceptionHandler(...)
ExceptionHandler(...) 是一个异常处理注解用于捕获请求的异常。当客户端发送的请求消息无法被框架正确解析时将抛出该异常并调用对应的异常处理方法。
RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法/*** 缺少请求体异常处理器* param e 缺少请求体异常 使用get方式请求 而实体使用RequestBody修饰*/ResponseStatus(HttpStatus.BAD_REQUEST)ExceptionHandler(HttpMessageNotReadableException.class)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},请求体缺失{}, requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}
}
RuntimeException
RuntimeException 是 Java 提供的一个运行时异常类。与受检查异常不同运行时异常不需要在方法声明中显式地声明或捕获并且在运行时抛出时也不需要强制捕获或处理。所以我们可以在全局异常捕获中去捕获这个异常
public class BusinessException extends RuntimeException {private int code;//使用枚举构造public BusinessException(HttpCodeEnum httpCodeEnum){super(httpCodeEnum.getMsg());this.codehttpCodeEnum.getCode();}//使用自定义消息体public BusinessException(HttpCodeEnum httpCodeEnum, String msg){super(msg);this.codehttpCodeEnum.getCode();}//根据异常构造public BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg){super(msg);this.codehttpCodeEnum.getCode();}} 上述代码定义了一个名为 BusinessException 的自定义异常类它继承自 RuntimeException。
这个自定义异常类具有以下特点
包含了一个 code 字段用于表示异常的错误码。提供了不同的构造方法以方便在抛出异常时指定错误码和错误信息。
BusinessException(HttpCodeEnum httpCodeEnum) 构造方法使用枚举类型 HttpCodeEnum 来设置异常的错误码和错误信息。BusinessException(HttpCodeEnum httpCodeEnum, String msg) 构造方法使用自定义的错误信息来设置异常的错误码和错误信息。BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg) 构造方法使用其他异常的实例来设置异常的错误码并可选地提供通过 Throwable 获取的错误信息。
HttpCodeEnum 枚举类
我们还需要一个类表示 HTTP 响应的状态码和对应的消息 以下为基本的举例查考。
public enum HttpCodeEnum {// 成功SUCCESS(200, 操作成功),// 登录NEED_LOGIN(401, 需要登录后操作),NO_OPERATOR_AUTH(403, 无权限操作),SYSTEM_ERROR(500, 出现错误),USERNAME_EXIST(501, 用户名已存在),PHONENUMBER_EXIST(502, 手机号已存在), EMAIL_EXIST(503, 邮箱已存在),REQUIRE_USERNAME(504, 必需填写用户名),CONTENT_NOT_NULL(506, 评论内容不能为空),FILE_TYPE_ERROR(507, 文件类型错误),USERNAME_NOT_NULL(508, 用户名不能为空),NICKNAME_NOT_NULL(509, 昵称不能为空),PASSWORD_NOT_NULL(510, 密码不能为空),EMAIL_NOT_NULL(511, 邮箱不能为空),NICKNAME_EXIST(512, 昵称已存在),LOGIN_ERROR(505, 用户名或密码错误);int code;String msg;HttpCodeEnum(int code, String errorMessage) {this.code code;this.msg errorMessage;}public int getCode() {return code;}public String getMsg() {return msg;}
}上述代码定义了一个 HttpCodeEnum 枚举类用于表示 HTTP 响应的状态码和对应的消息。
这个枚举类具有以下特点
包含一组枚举常量每个常量代表一个 HTTP 响应状态。每个常量都有一个整型的 code 和一个字符串类型的 msg分别表示状态码和对应的消息。提供了相应的构造方法、获取 code 和 msg 的方法。
ResponseResult类
该类的主要作用是封装接口返回的数据统一格式化输出方便前端调用和展示。
import lombok.Data;import java.io.Serializable;
Data
public class ResponseResultT implements Serializable {private Boolean success;private Integer code;private String msg;private T data;public ResponseResult() {this.successtrue;this.code HttpCodeEnum.SUCCESS.getCode();this.msg HttpCodeEnum.SUCCESS.getMsg();}public ResponseResult(Integer code, T data) {this.code code;this.data data;}public ResponseResult(Integer code, String msg, T data) {this.code code;this.msg msg;this.data data;}public ResponseResult(Integer code, String msg) {this.code code;this.msg msg;}public static ResponseResult errorResult(int code, String msg) {ResponseResult result new ResponseResult();return result.error(code, msg);}public static ResponseResult okResult() {ResponseResult result new ResponseResult();return result;}public static ResponseResult okResult(int code, String msg) {ResponseResult result new ResponseResult();return result.ok(code, null, msg);}public static ResponseResult setHttpCodeEnum(HttpCodeEnum enums) {return okResult(enums.getCode(), enums.getMsg());}public ResponseResult? error(Integer code, String msg) {this.successfalse;this.code code;this.msg msg;return this;}public ResponseResult? ok(Integer code, T data) {this.successtrue;this.code code;this.data data;return this;}public ResponseResult? ok(Integer code, T data, String msg) {this.successtrue;this.code code;this.data data;this.msg msg;return this;}public ResponseResult? ok(T data) {this.successtrue;this.data data;return this;}}全局异常捕获
全局异常捕获是一种处理应用程序中未处理的异常的机制它可以统一处理应用程序中的异常避免异常导致程序崩溃或向用户显示不友好的错误信息。我们可以通过上述的解释去捕获异常定义code类型枚举返回ResponseResult给前端
import com.example.demo.util.HttpCodeEnum;
import com.example.demo.util.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.servlet.http.HttpServletRequest;
import java.util.List;RestControllerAdvice
public class GlobalExceptionHandler {private static final Logger log LoggerFactory.getLogger(GlobalExceptionHandler.class);Autowiredprivate HttpServletRequest httpServletRequest;private final String sysError系统出错;/*** 缺少请求体异常处理器* param e 缺少请求体异常 使用get方式请求 而实体使用RequestBody修饰*/ResponseStatus(HttpStatus.BAD_REQUEST)ExceptionHandler(HttpMessageNotReadableException.class)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},请求体缺失{}, requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}/** Description: 捕获请求方法异常比如post接口使用了get*/ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)ExceptionHandler(HttpRequestMethodNotSupportedException.class)public ResponseResult methodNotAllowedHandler(HttpRequestMethodNotSupportedException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},请求方法不被允许{}, requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}// get请求的对象参数校验异常ResponseStatus(HttpStatus.BAD_REQUEST)ExceptionHandler({MissingServletRequestParameterException.class})public ResponseResult bindExceptionHandler(MissingServletRequestParameterException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},get方式请求参数{}必传, requestURI, e.getParameterName());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}// post请求的对象参数校验异常ResponseStatus(HttpStatus.BAD_REQUEST)ExceptionHandler({MethodArgumentNotValidException.class})public ResponseResult methodArgumentNotValidHandler(MethodArgumentNotValidException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},post方式请求参数异常{}, requestURI, e.getMessage());ListObjectError allErrors e.getBindingResult().getAllErrors();return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), getValidExceptionMsg(allErrors));}// 业务类异常ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)ExceptionHandler(BusinessException.class)public ResponseResult businessExceptionHandler(BusinessException e) {String requestURI httpServletRequest.getRequestURI();System.out.println(e);log.error(请求地址{},捕获业务类异常{}, requestURI,e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}// 运行时异常ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)ExceptionHandler(RuntimeException.class)public ResponseResult runtimeExceptionHandler(RuntimeException e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},捕获运行时异常{}, requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}// 系统级别异常ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)ExceptionHandler(Throwable.class)public ResponseResult throwableExceptionHandler(Throwable e) {String requestURI httpServletRequest.getRequestURI();log.error(请求地址{},捕获系统级别异常{}, requestURI,e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}private String getValidExceptionMsg(ListObjectError errors) {if(!CollectionUtils.isEmpty(errors)){StringBuilder sb new StringBuilder();errors.forEach(error - {if (error instanceof FieldError) {sb.append(((FieldError)error).getField()).append(:);}sb.append(error.getDefaultMessage()).append(;);});String msg sb.toString();msg msg.substring(0, msg.length() -1);return msg;}return null;}}测试
入参不正确时 发出请求 返回结果 捕获异常 运行时错误 发起请求 返回结果 捕获异常 业务异常 发送请求 返回结果 捕获异常