目录
5、BusinessExceptionHandle.class
本篇介绍后端Controller层如何返回统一的数据格式给前端。
因为涉及到异常的处理,所以制作了一个java异常的简略图,如下:
首先定义一个全局返回的类,该类定义了返回给前端的统一格式:状态码+返回数据,具体代码实现如下:
1、CommonReturnType.class
public class CommonReturnType {
/**
* 返回数据
*/
private String status;
/**
* 返回状态码
*/
private Object data;
public static CommonReturnType create(String status,Object data){
CommonReturnType type = new CommonReturnType();
type.setStatus(status);
type.setData(data);
return type;
}
public static CommonReturnType create(Object data){
return CommonReturnType.create("success",data);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
以上全局返回参数只适应于程序没有错误和异常的情况,所以针对错误和异常,我们需要另外再定义其他类来实现,首先定义一个公共错误的接口,接口中需要有获取错误码(errorCode)和错误信息(errorMessage)的方法,另外还需要设计一个设置错误信息的方法,以便我们能自定义异常,代码实现如下:
2、CommonError接口
public interface CommonError {
public Integer getErrorCode();
public String getErrorMsg();
public CommonError setErrorMsg(String errorMsg);
}
然后对于异常的处理,我们需要定义自己能够及时判断错误的信息,准确的明确和找到程序错误,因此我们需要自定义自己的异常类,代码如下:
3、BusinessException.class
public class BusinessException extends RuntimeException implements CommonError{
private CommonError commonError;
public BusinessException(CommonError commonError){
super();
this.commonError = commonError;
}
public BusinessException(CommonError commonError,String errorMsg){
super();
this.commonError = commonError;
// 对errorMsg进行二次修改
this.commonError.setErrorMsg(errorMsg);
}
@Override
public Integer getErrorCode() {
return this.commonError.getErrorCode();
}
@Override
public String getErrorMsg() {
return this.commonError.getErrorMsg();
}
@Override
public CommonError setErrorMsg(String errorMsg) {
this.commonError.setErrorMsg(errorMsg);
return this;
}
}
对于错误信息,随着程序代码的不断增加,我们希望能够把错误信息进行归类整理,以便后期能够方便进行维护和拓展,因此,我们使用枚举类来进行定义,定义格式跟公共错误接口的格式保持一致:错误码+错误信息;代码实现如下:
4、枚举类EnuBusinessError
public enum EnuBusinessError implements CommonError{
// 定义一个通用错误类型
PARAMETER_VILIDATION_ERROR(10000,"参数不合法"),
// 定义未知错误
NUKNOW_ERROR(10002,"未知错误"),
;
private Integer errorCode;
private String errorMsg;
private EnuBusinessError(Integer errorCode,String errorMsg){
this.errorCode = errorCode;
this.errorMsg = errorMsg;
};
@Override
public Integer getErrorCode() {
return this.errorCode;
}
@Override
public String getErrorMsg() {
return this.errorMsg;
}
@Override
public CommonError setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
return this;
}
}
最后,也是最关键的一步,我们要成功捕获控制层(Controller)程序中的异常信息,并把异常信息转化为我们自己定义的信息,我们需要借助Spring中的相关注解
@ControllerAdvice 控制器增强,被该注解标记的类可以作用于全局的Controller上
@ExceptionHandler Controller层异常处理和捕获
5、BusinessExceptionHandle.class
@ControllerAdvice //使用该注解捕获全局异常
public class BusinessExceptionHandle {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)// 自定义异常响应对应的状态码,碰到了某个自定义异常加上了@ResponseStatus,
// 就继续抛出,这样就不会让自定义异常失去加上@ResponseStatus的初衷
public CommonReturnType BusinessExceptionHandle(Exception e){
Map<String,Object> resultMap = new HashMap<>();
if(e instanceof BusinessException){
BusinessException ex = (BusinessException) e;
resultMap.put("errorCode",ex.getErrorCode());
resultMap.put("errorMsg",ex.getErrorMsg());
}else{
resultMap.put("errorCode",EnuBusinessError.NUKNOW_ERROR.getErrorCode());
resultMap.put("errorMsg",EnuBusinessError.NUKNOW_ERROR.getErrorMsg());
}
return CommonReturnType.create(resultMap);
}
}
综合上述,代码使用效果如下图所示:
补充实例代码
import com.x.x.common.core.constant.CommonConstants;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 响应信息主体
*/
@Builder // 自动生成 builder() 方法,并且直接根据字段名称方法进行字段赋值,最后使用 build()方法构建出一个实体对象。
@ToString // 给类自动生成 toString 方法,带上有所非静态字段的属性名称和值
@NoArgsConstructor // 为实体类生成无参的构造器方法
@AllArgsConstructor // 为实体类生成除了static修饰的字段之外带有各参数的构造器方法
@Accessors(chain = true) // 每次使用set方法返回的都是对象本身
@ApiModel(value = "响应信息主体")
public class CommonResponse<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Getter // 生成getter方法
@Setter // 生成setter方法
@ApiModelProperty(value = "返回标记:成功标记=0,失败标记=1")
private int code;
@Getter
@Setter
@ApiModelProperty(value = "返回信息")
private String msg;
@Getter
@Setter
@ApiModelProperty(value = "数据")
private T data;
public static <T> CommonResponse<T> ok() {
return restResult(null, CommonConstants.SUCCESS, null);
}
public static <T> CommonResponse<T> ok(T data) {
return restResult(data, CommonConstants.SUCCESS, null);
}
public static <T> CommonResponse<T> ok(T data, String msg) {
return restResult(data, CommonConstants.SUCCESS, msg);
}
public static <T> CommonResponse<T> failed() {
return restResult(null, CommonConstants.FAIL, null);
}
public static <T> CommonResponse<T> failed(String msg) {
return restResult(null, CommonConstants.FAIL, msg);
}
public static <T> CommonResponse<T> failed(T data) {
return restResult(data, CommonConstants.FAIL, null);
}
public static <T> CommonResponse<T> failed(T data, String msg) {
return restResult(data, CommonConstants.FAIL, msg);
}
private static <T> CommonResponse<T> restResult(T data, int code, String msg) {
CommonResponse<T> apiResult = new CommonResponse<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
}
参考链接:实体类测试技巧:@Accessors注解的使用_QR_adaptor的博客-CSDN博客_accessors注解