import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse<T> implements Serializable {
private int code;
private String msg;
private T data;
public ApiResponse(Code err) {
this.code = err.getCode();
this.msg = err.getFixTips();
}
public ApiResponse(BaseException ex) {
this.code = ex.getCode();
this.msg = ex.getMsg();
}
public ApiResponse(int code, String msg) {
this.code = code;
this.msg = msg;
}
public ApiResponse<T> success() {
this.code = BaseCode.SUCCESS.getCode();
this.msg = BaseCode.SUCCESS.getInfo();
return this;
}
public ApiResponse<T> success(T data) {
this.code = BaseCode.SUCCESS.getCode();
this.msg = BaseCode.SUCCESS.getInfo();
this.data = data;
return this;
}
public ApiResponse<T> error(Code code, T data) {
this.code = code.getCode();
this.msg = code.getInfo();
this.data = data;
return this;
}
public ApiResponse<T> error(Code code) {
this.code = code.getCode();
this.msg = code.getInfo();
this.data = null;
return this;
}
public ApiResponse<T> error(int code, String msg) {
this.code = code;
this.msg = msg;
this.data = null;
return this;
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
/**
* controller统一参数异常切面通知
* @author 异常处理
*/
@ControllerAdvice
@Slf4j
@SuppressWarnings("rawtypes")
public class ExceptionAdvice {
private static final String REQ_PARAM_EXCEPTION = "请求参数校验异常";
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiResponse handleException(Exception e) {
LoggerUtil.error(log, "未知异常", e);
ApiResponse response = new ApiResponse(BaseCode.SYSTEM_FAILD);
response.setData(e.getMessage());
return response;
}
@ExceptionHandler(BizException.class)
@ResponseBody
public ApiResponse handleBizException(HttpServletResponse resp, BizException e) {
LoggerUtil.info(log, "服务业务异常", e.getCode(), e.getMsg());
return new ApiResponse(e);
}
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public ApiResponse handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
LoggerUtil.error(log, "请求必传参数为空", e, e.getMessage());
return new ApiResponse(BaseCode.PARAM_ERROR);
}
/***
* 拦截HttpMessageNotReadableException
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public ApiResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
LoggerUtil.error(log, "请求必传参数为空", e, e.getMessage());
return new ApiResponse(BaseCode.PARAM_ERROR);
}
/**
* 拦截MethodArgumentNotValidException
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ApiResponse handleBindException(MethodArgumentNotValidException e) {
StringBuilder builder = new StringBuilder();
e.getBindingResult().getFieldErrors().forEach(x -> {
builder.append(x.getField()).append(":").append(x.getDefaultMessage()).append(";");
});
LoggerUtil.error(log, REQ_PARAM_EXCEPTION, e, builder.toString());
return new ApiResponse(BaseCode.PARAM_ERROR.getCode(), builder.toString());
}
/**
* 拦截BindException
*/
@ExceptionHandler(BindException.class)
@ResponseBody
public ApiResponse handleBindException(BindException e) {
StringBuilder builder = new StringBuilder();
e.getFieldErrors().forEach(x -> builder.append(x.getField())
.append(":")
.append(x.getDefaultMessage())
.append(";"));
LoggerUtil.error(log, REQ_PARAM_EXCEPTION, e, builder.toString());
return new ApiResponse(BaseCode.PARAM_ERROR.getCode(), builder.toString());
}
/**
* 拦截SQLException
*
* @param e
* @return
*/
@ExceptionHandler(SQLException.class)
@ResponseBody
public ApiResponse handleBindException(SQLException e) {
LoggerUtil.error(log, "sql异常", e);
return new ApiResponse(BaseCode.SQL_ERROR.getCode(), e.getMessage());
}
@ExceptionHandler(SQLSyntaxErrorException.class)
@ResponseBody
public ApiResponse handleBindException(SQLSyntaxErrorException e) {
LoggerUtil.error(log, "sql解析异常", e);
return new ApiResponse(BaseCode.SQL_ERROR.getCode(), e.getMessage());
}
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public ApiResponse handleBindException(ConstraintViolationException e) {
StringBuilder builder = new StringBuilder();
e.getConstraintViolations().forEach(x -> {
builder.append(x.getPropertyPath().toString().split("\\.")[1]).append(":").append(x.getMessage()).append(";");
});
LoggerUtil.error(log, REQ_PARAM_EXCEPTION, e, e.getMessage());
return new ApiResponse(BaseCode.PARAM_ERROR.getCode(), builder.toString());
}
}
public interface Code {
int getCode();
String getInfo();
String getFixTips();
}
public enum BaseCode implements Code {
SUCCESS(10000, "业务处理成功", "业务处理成功"),
SYSTEM_FAILD(10001, "系统异常", "系统异常,请稍后重试"),
TIMED_OUT(10002, "业务处理超时", "系统处理超时,请重试"),
PARAM_ERROR(10003, "参数错误", "请检查参数是否正确"),
SQL_ERROR(10004, "SQL脚本异常", "请稍后重试"),
private final int code;
private final String info;
private final String fixTips;
private BaseCode(int code, String info, String fixTips) {
this.code = code;
this.info = info;
this.fixTips = fixTips;
}
public int getCode() {
return this.code;
}
public String getInfo() {
return this.info;
}
public String getFixTips() {
return this.fixTips;
}
}
public class BaseException extends RuntimeException {
private static final long serialVersionUID = 1L;
private int code;
private String msg;
public BaseException(Code code) {
super(code.getFixTips());
this.code = code.getCode();
this.msg = code.getFixTips();
}
public BaseException(Code code, Throwable e) {
super(code.getFixTips(), e);
this.code = code.getCode();
this.msg = code.getFixTips();
}
public BaseException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public BaseException(int code, String msg, Throwable e) {
super(msg, e);
this.code = code;
this.msg = msg;
}
public int getCode() {
return this.code;
}
public String getMsg() {
return this.msg;
}
public BaseException() {
}
}
public class BizException extends BaseException {
public BizException(Code code) {
super(code);
}
public BizException(Code code, Throwable e) {
super(code, e);
}
public BizException(int code, String msg) {
super(code, msg);
}
public BizException(int code, String msg, Throwable e) {
super(code, msg, e);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix