学成异常处理
1、定义枚举类
- 定义通用返回消息
- 每个错误类型都有一个私有的构造函数,用于初始化对应的错误消息。通过公共的
getErrMessage()
方法,可以获取到每个错误类型对应的错误消息。 - 通过
CommonError.PARAMS_ERROR.getErrMessage();
获取
public enum CommonError {
UNKOWN_ERROR("执行过程异常,请重试。"),
PARAMS_ERROR("非法参数"),
OBJECT_NULL("对象为空"),
QUERY_NULL("查询结果为空"),
REQUEST_NULL("请求参数为空");
// 获取枚举类
private String errMessage;
public String getErrMessage() {
return errMessage;
}
// 构造方法
private CommonError(String errMessage) {
this.errMessage = errMessage;
}
}
2、自定义异常
- 1、定义自定义异常类 PrivateException,继承自 RuntimeException。
- 2、
getErrMessage()
方法:这个方法用于获取errMessage
属性的值,供外部访问该异常对象的异常消息。 - 3、无参/有参 构造 调用父类的带有异常消息参数的构造函数,并设置
errMessage
字段。
cast(CommonError commonError)
根据枚举类,抛出异常
CommonError error = CommonError.PARAMS_ERROR;
PrivateException.cast(error);
cast(String errMessage)
根据传入的字符串,抛出异常
PrivateException.cast("Custom error message");
public class PrivateException extends RuntimeException {
private String errMessage;
public String getErrMessage() {
return errMessage;
}
public PrivateException() {
super();
}
public PrivateException(String errMessage) {
super(errMessage);
this.errMessage = errMessage;
}
public static void cast(CommonError commonError){
throw new PrivateException(commonError.getErrMessage());
}
public static void cast(String errMessage){
throw new PrivateException(errMessage);
}
}
3、定义错误响应参数
- 这个文件定义了一个简单的错误响应参数包装类 RestErrorResponse,用于包装错误消息。它包含了一个存储错误消息的字段,并提供了相应的 getter 和 setter 方法。
200 OK
:HttpStatus.OK
201 Created
:HttpStatus.CREATED
204 No Content
:HttpStatus.NO_CONTENT
400 Bad Request
:HttpStatus.BAD_REQUEST
401 Unauthorized
:HttpStatus.UNAUTHORIZED
403 Forbidden
:HttpStatus.FORBIDDEN
404 Not Found
:HttpStatus.NOT_FOUND
500 Internal Server Error
:HttpStatus.INTERNAL_SERVER_ERROR
表示 RESTful API 返回的错误响应信息:
return new ResponseEntity<>("响应状态内容", HttpStatus.UNAUTHORIZED);
public class RestErrorResponse implements Serializable {
private String errMessage;
public RestErrorResponse(String errMessage){
this.errMessage= errMessage;
}
public String getErrMessage() {
return errMessage;
}
public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}
}
4、全局异常处理
@ControllerAdvice
:这是 Spring Framework 提供的注解,用于声明该类为全局异常处理器。全局异常处理器可以捕获应用程序中抛出的异常,并进行统一的处理。customException
方法:处理自定义的PrivateException
异常的方法。在方法内部,首先记录异常信息到日志中,然后返回一个自定义的错误响应RestErrorResponse
对象,其中包含了异常的错误消息。exception
方法:这是用来处理其他类型的异常的方法,例如通用的Exception
。在方法内部,同样记录异常信息到日志中,然后返回一个通用的错误响应RestErrorResponse
对象,其中包含了一个预定义的错误消息。
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理 XueChengPlusException 异常
*/
@ResponseBody
@ExceptionHandler(PrivateException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse customException(PrivateException e) {
log.error("【系统异常】{}",e.getErrMessage(),e);
return new RestErrorResponse(e.getErrMessage());
}
/**
* 处理其他异常
*/
@ResponseBody
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse exception(Exception e) {
log.error("【系统异常】{}",e.getMessage(),e); // 记录异常信息到日志中
return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());
}
/**
* 处理检验异常(JSR-303)
* methodArgumentNotValidException */
@ResponseBody // 返回值作为响应体返回
@ExceptionHandler(MethodArgumentNotValidException.class) // 标记该方法处理 Exception 异常
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 返回状态码 500,表示服务器内部错误
public RestErrorResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {
// 解析异常
BindingResult bindingResult = e.getBindingResult();
// 存放错误信息
List<String> errors = new ArrayList<>();
bindingResult.getFieldErrors().stream().forEach(item->{
errors.add(item.getDefaultMessage());
});
// 拼接错误信息
String errMessage = StringUtils.join(errors, ",");
// 记录异常信息到日志中
log.error("【系统异常】{}",e.getMessage(),errMessage);
// 返回通用的错误响应
RestErrorResponse restErrorResponse = new RestErrorResponse(errMessage);
return restErrorResponse;
}
}
中州养老异常处理
-
BaseException.java
:- 这个类定义了一个基本的异常类,其中包含了模块、错误码、错误消息等信息。
- 通过构造方法可以设置异常的模块、错误码、参数和默认消息。
- 用于自定义具体业务异常的基类,在具体业务异常类中可以继承该类并设置具体的异常信息。
-
ProjectException.java
:- 这个类是自定义异常类,继承了
RuntimeException
,用于表示项目中发生的异常情况。 - 包含了错误编码、提示信息等属性,以及对应的接口信息。
- 可以通过不同的构造方法设置异常的错误码和提示信息,方便在项目中抛出自定义异常并传递相关信息。
- 这个类是自定义异常类,继承了
-
GlobalExceptionHandler.java
:- 这个类是全局异常处理器,使用
@RestControllerAdvice
注解标记为全局异常处理类。 - 包含了多个异常处理方法,针对不同类型的异常进行处理并返回相应的响应数据。
- 通过各个
@ExceptionHandler
方法捕获特定类型的异常,并返回对应的响应数据,例如设置HTTP响应状态码、错误消息等。
- 这个类是全局异常处理器,使用
1、自定义异常`BaseException
package com.zzyl.exception;
import lombok.Data;
/**
* BaseException * @author itheima
**/@Data
public class BaseException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 所属模块
*/
private String module;
/**
* 错误码
*/
private String code;
/**
* 错误码对应的参数
*/
private Object[] args;
/**
* 错误消息
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) {
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args) {
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage) {
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args) {
this(null, code, args, null);
}
public BaseException(String defaultMessage) {
this(null, "500", null, defaultMessage);
}
public String getModule() {
return module;
}
public String getCode() {
return code;
}
public Object[] getArgs() {
return args;
}
public String getDefaultMessage() {
return defaultMessage;
}
}
1-1、使用示例
构造方法
BaseException(String module, String code, Object[] args, String defaultMessage)
:
throw new BaseException("ModuleA", "401", new Object[]{"arg1", "arg2"}, "Default error message");
构造方法
BaseException(String module, String code, Object[] args)
:
throw new BaseException("ModuleB", "404", new Object[]{"arg3", "arg4"});
构造方法
BaseException(String module, String defaultMessage)
:
throw new BaseException("ModuleC", "Custom error message");
构造方法
BaseException(String code, Object[] args)
:
throw new BaseException("500", new Object[]{"arg5"});
构造方法
BaseException(String defaultMessage)
:
throw new BaseException("Default error message");`
以上示例展示了不同构造方法在创建BaseException
对象时的用法,根据传入的参数设置了模块、错误码、参数以及默认消息等属性。这些方法可以根据具体业务场景中异常的情况来灵活使用,以便准确传达异常信息并进行处理。
2、自定义异常`ProjectException
package com.zzyl.exception;
import com.zzyl.base.IBasicEnum;
/**
* 自定义异常
*/
public class ProjectException extends RuntimeException {
//错误编码
private int code;
//提示信息
private String message;
//异常接口
private IBasicEnum basicEnumIntface;
public ProjectException() {
}
public ProjectException(int code, String message) {
this.code = code;
this.message = message;
}
public ProjectException(IBasicEnum errorCode) {
setBasicMsg(errorCode);
}
public ProjectException(IBasicEnum errorCode, String throwMsg) {
super(throwMsg);
setBasicMsg(errorCode);
}
public ProjectException(IBasicEnum errorCode, Throwable throwable) {
super(throwable);
setBasicMsg(errorCode);
}
private void setBasicMsg(IBasicEnum basicEnumIntface) {
this.code = basicEnumIntface.getCode();
this.message = basicEnumIntface.getMsg();
this.basicEnumIntface = basicEnumIntface;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public IBasicEnum getBasicEnumIntface() {
return basicEnumIntface;
}
public void setBasicEnumIntface(IBasicEnum basicEnumIntface) {
this.basicEnumIntface = basicEnumIntface;
}
@Override
public String toString() {
return "ProjectException{" +
"code='" + code + '\'' +
", message='" + message + '\'' +
", basicEnumIntface=" + basicEnumIntface +
'}';
}
}
3、全局异常`GlobalExceptionHandler
package com.zzyl.exception;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import java.io.FileNotFoundException;
import java.nio.file.AccessDeniedException;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 处理自定义异常BaseException。
* 返回自定义异常中的错误代码和错误消息。
*
* @param exception 自定义异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(BaseException.class)
public ResponseEntity<Object> handleBaseException(BaseException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("自定义异常处理 -> ", exception);
}
return ResponseEntity.ok(MapUtil.<String, Object>builder()
.put("code", exception.getCode())
.put("msg", exception.getDefaultMessage())
.build());
}
/**
* 处理文件上传超过最大限制异常。
* 返回HTTP响应状态码500,包含错误代码和错误消息。
*
* @param exception 文件上传异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
public ResponseEntity<Object> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("文件上传超过最大限制异常 -> ", exception);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value())
.put("msg", "上传图片大小不能超过5M,格式需为jpg、png、gif")
.build());
}
/**
* 处理其他未知异常。
* 返回HTTP响应状态码500,包含错误代码和异常堆栈信息。
*
* @param exception 未知异常
* @return 响应数据,包含错误代码和异常堆栈信息
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleUnknownException(Exception exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("其他未知异常 -> ", exception);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value())
.put("msg", ExceptionUtil.stacktraceToString(exception))
.build());
}
/**
* 处理FileNotFoundException异常。
* 返回HTTP响应状态码400,包含错误代码和错误消息。
*
* @param exception 文件未找到异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(FileNotFoundException.class)
public ResponseEntity<Object> handleFileNotFoundException(FileNotFoundException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("文件不存在 -> ", exception);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.BAD_REQUEST.value())
.put("msg", exception.getMessage())
.build());
}
/**
* 处理没有权限访问接口异常。
* 返回HTTP响应状态码401,包含错误代码和错误消息。
*
* @param exception 权限访问异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<Object> handleAccessDeniedException(AccessDeniedException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("没有权限访问接口异常 -> ", exception);
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.UNAUTHORIZED.value())
.put("msg", "没有权限访问接口")
.build());
}
/**
* 处理运行时异常。
* 返回HTTP响应状态码500,包含错误代码和错误消息。
*
* @param exception 运行时异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleRuntimeException(RuntimeException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("其他未知异常 -> ", exception);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value())
.put("msg", exception.getMessage())
.build());
}
/**
* 处理key重复异常。
* 返回HTTP响应状态码200,包含错误代码和错误消息。
*
* @param exception key重复异常
* @return 响应数据,包含错误代码和错误消息
*/
@ExceptionHandler(DuplicateKeyException.class)
public ResponseEntity<Object> handleDuplicateKeyException(DuplicateKeyException exception) {
exception.printStackTrace();
if (ObjectUtil.isNotEmpty(exception.getCause())) {
log.error("其他未知异常 -> ", exception);
}
return ResponseEntity.status(HttpStatus.OK)
.body(MapUtil.<String, Object>builder()
.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value())
.put("msg", "操作失败,数据重复")
.build());
}
}