在我们开发SpringBoot后端服务时,一般需要给前端统一响应格式,方便前端调试及配置错误提示等等。这篇文章讲讲实际工作中统一响应格式及统一异常处理是如何做的。
一、统一响应基础类
在项目中对应工具类或Vo层来创建我们的统一响应类
ResponseResult
:
import com.fasterxml.jackson.annotation.JsonInclude; import com.zhang.enums.AppHttpCodeEnum; import java.io.Serializable; @JsonInclude(JsonInclude.Include.NON_NULL) public class ResponseResult<T> implements Serializable { private Integer code; private String msg; private T data; public ResponseResult() { this.code = AppHttpCodeEnum.SUCCESS.getCode(); this.msg = AppHttpCodeEnum.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 okResult(Object data) { ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg()); if (data != null) { result.setData(data); } return result; } public static ResponseResult errorResult(AppHttpCodeEnum enums) { return setAppHttpCodeEnum(enums, enums.getMsg()); } public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg) { return setAppHttpCodeEnum(enums, msg); } public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) { return okResult(enums.getCode(), enums.getMsg()); } private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg) { return okResult(enums.getCode(), msg); } public ResponseResult<?> error(Integer code, String msg) { this.code = code; this.msg = msg; return this; } public ResponseResult<?> ok(Integer code, T data) { this.code = code; this.data = data; return this; } public ResponseResult<?> ok(Integer code, T data, String msg) { this.code = code; this.data = data; this.msg = msg; return this; } public ResponseResult<?> ok(T data) { this.data = data; return this; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
里面还有用到一个响应的枚举类AppHttpCodeEnum
,接下来我们创建这个枚举类
二、响应枚举类
AppHttpCodeEnum
:
public enum AppHttpCodeEnum { // 成功 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; AppHttpCodeEnum(int code, String errorMessage) { this.code = code; this.msg = errorMessage; } public int getCode() { return code; } public String getMsg() { return msg; } }
一般我们在这个枚举类中管理需要响应的错误code
及msg
三、统一响应格式使用
在对应的controller或者service里面使用统一响应类
- 成功:
ResponseResult.okResult()
- 失败:
ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR)
, 参数传入我们定义的响应枚举类
四、统一异常处理
1. 自定义异常
为什么我们需要自定义异常?因为在某些情况下,我们需要返回我们自定义的响应格式非常不方便,如在处理用户鉴权或token校验的时候,因为像这些部分我们一般都是在单独的工具类中去处理,这时候如果报错其实就可以抛出我们自定义的异常,交由我们全局的异常处理去统一返回响应。
- 在
exception
包下新建SystemException
类 -
SystemException
继承RuntimeException
具体实现代码如下
exception.SystemException:
import com.jk.enums.AppHttpCodeEnum; public class SystemException extends RuntimeException{ private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } public SystemException(AppHttpCodeEnum appHttpCodeEnum) { super(appHttpCodeEnum.getMsg()); this.code = appHttpCodeEnum.getCode(); this.msg = appHttpCodeEnum.getMsg(); } }
目前只是自定义了异常,我们还需要对自定义的异常进行处理,返回统一的响应格式。
2.异常处理
- 在
handler.exception
包下新建GlobalExceptionHandler
处理类 -
@RestControllerAdvice
是组合注解,由@ControllerAdvice
、@ResponseBody
组成,标明是一个统一异常处理的类,并把返回结果封装在ResponseBody
中 -
@Slf4j
是Lombok
实现日志输出的注解 -
@ExceptionHandler
标明该方法处理哪些异常
具体代码实现如下:
handler.exception.GlobalExceptionHandler:
import com.jk.enums.AppHttpCodeEnum; import com.jk.exception.SystemException; import com.jk.vo.ResponseResult; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(SystemException.class) public ResponseResult systemExceptionHandler(SystemException e) { log.error("出现了异常! {}", e); return ResponseResult.errorResult(e.getCode(), e.getMsg()); } @ExceptionHandler(Exception.class) public ResponseResult exceptionHandler(Exception e) { log.error("出现了异常! {}", e); return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage()); } }
可以看到我们除了处理自定义异常SystemException
外,还对Exception
就是其他我们无法预料到的异常做了一个兜底。
3.自定义异常使用
在需要抛出异常的地方:
throw new SystemException(AppHttpCodeEnum.LOGIN_ERROR);
前端接收到的响应是:
{ "code": 505, "msg": "用户名或密码错误" }
这样就比接收到500错误也不知道错误原因好多了。
版权声明:除特别声明外,本站所有文章皆是本站原创,转载请以超链接形式注明出处!