前言
目前大部分系统都是前后端分离架构,后端提供接口并返回 JSON 数据,前端接收数据后进行处理展示。为了提高前后端协作效率,后端接口返回值采用固定格式十分必要。
后端接口返回值通用格式
通用返回值通常包含 4 个核心字段,代码定义如下:
java
public class Result<T> {
/**
* 请求是否处理成功
*/
private boolean success;
/**
* 数据,泛型类型,存储后端返回给前端的业务数据
*/
private T data;
/**
* 提示消息,当success为false时给用户的提示信息
*/
private String msg;
/**
* 错误编码,提供详细错误标识,便于前端根据不同编码做差异化处理
*/
private String code;
}
接口示例
java
@RestController
public class TestController {
@GetMapping("/hello")
public Result<String> hello() {
return ResultUtils.success("hello");
}
}
前端接收结果
java
{
"success": true,
"data": "hello",
"msg": null,
"code": null
}
异常情况处理
后端接口通常包含校验逻辑,如登录接口需要验证用户名和密码。当验证不通过时,应返回标准化的错误信息:
java
{
"success": false,
"data": null,
"msg": "用户名或密码错误",
"code": "1001"
}
实现方式:后端校验不通过时抛出业务异常,通过全局异常处理器统一处理并返回通用格式结果。
具体实现步骤
1. 自定义业务异常类
java
public class BusinessException extends RuntimeException {
private String code;
/**
* @param code 错误编码
* @param message 错误提示信息
*/
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
public BusinessException(String code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
2. 接口中抛出业务异常
以登录接口为例,当用户名验证不通过时抛出异常:
java
@GetMapping("/login")
public Result<String> login(String name) {
if (!"chen".equals(name)) {
throw new BusinessException("1001", "用户名错误");
} else {
return ResultUtils.success("登录成功");
}
}
3. 全局异常处理 BusinessException
使用 SpringBoot 的全局异常处理器处理业务异常,通过@RestControllerAdvice和@ExceptionHandler注解实现:
java
@RestControllerAdvice
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理业务异常
*
* @param e 业务异常对象
* @param request 请求对象
* @return 通用返回结果
*/
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e, HttpServletRequest request) {
logger.info("请求:{},发生异常:{}", request.getRequestURL(), e.getMessage(), e);
return ResultUtils.error(e.getCode(), e.getMessage());
}
}
4. 验证效果
- 正常情况(访问:http://localhost:8080/login?name=chen):
java
{
"success": true,
"data": "登录成功",
"msg": null,
"code": null
}
- 异常情况(访问:http://localhost:8080/login?name=张三):
java
{
"success": false,
"data": null,
"msg": "用户名错误",
"code": "1001"
}
案例:SpringBoot 参数校验异常处理
SpringBoot 提供参数自动校验功能,以下是具体实现:
1. 用户注册接口
java
@PostMapping("/userRegister")
public Result<Void> userRegister(@Validated @RequestBody UserRegisterRequest req) {
return ResultUtils.success();
}
2. 参数校验异常处理
当参数校验不通过时,SpringBoot 会抛出BindException异常,在全局异常处理器中添加对应处理方法:
java
@ExceptionHandler(BindException.class)
public Result handleBindException(BindException e, HttpServletRequest request) {
logger.info("请求:{},发生异常:{}", request.getRequestURL(), e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return ResultUtils.error(message);
}
全局其他异常处理
添加兜底异常处理方法,处理所有未被专门捕获的异常:
java
/**
* 处理其他未明确捕获的异常
*
* @param e 异常对象
* @param request 请求对象
* @return 通用返回结果
*/
@ExceptionHandler(Exception.class)
public Result handleException(Exception e, HttpServletRequest request) {
logger.info("请求:{},发生异常:{}", request.getRequestURL(), e.getMessage(), e);
return ResultUtils.error(ErrorCode.SERVER_ERROR, "系统异常,请稍后重试");
}
提供的工具类
ResultUtils
java
public class ResultUtils {
public static final String SUCCESS = "1";
public static final String ERROR = "0";
public static <T> Result<T> ok()
{
return result(SUCCESS, null, null);
}
public static <T> Result<T> ok(T data)
{
return result(SUCCESS, data, null);
}
public static <T> Result<T> error(String msg)
{
return result(ERROR, null, msg);
}
public static <T> Result<T> result(String code, T data, String msg)
{
Result<T> r = new Result<>();
r.setCode(code);
r.setData(data);
r.setMsg(msg);
return r;
}
}
BusinessExceptionUtils
java
public class BusinessExceptionUtils
{
/**
* 创建 BusinessException
*/
public static BusinessException businessException(String code, String msg)
{
return new BusinessException(code, msg);
}
}
ErrorCode
java
public class ErrorCode
{
public static final String SERVER_ERROR = "500";
}