跳到主要内容

通用结构封装

后端优化

封装通用返回对象

目的:给对象补充一些信息,告诉前端这个请求在业务层面上是成功还是失败了

{
"code":xxx,
"data":{

},
"msg":xxx
}

定义统一返回结果Result

package com.yunfei.usercenterback.common;

import lombok.Data;

import java.io.Serializable;


@Data
public class Result<T> implements Serializable {
private Integer code;
private T data;
private String message;
private String description;

public Result(Integer code, T data, String message,String description) {
this.code = code;
this.data = data;
this.message = message;
this.description = description;
}

public Result(Integer code, T data,String message) {
this(code,data,message,"");
}

public Result(Integer code,T data){
this(code,data,"","");
}

public Result(Code code) {
this(code.getCode(),null,code.getMessage(),code.getDescription());

}
}

定义创建Result对象的ResultUtils

package com.yunfei.usercenterback.common;

public class ResultUtils {
public static <T> Result<T> success(T data) {
return new Result<>(0, data, "ok");
}

public static Result error(Integer code, String message, String description) {
return new Result(code, null, message, description);
}

public static Result error(Code code, String message, String description) {
return new Result(code.getCode(), message, description);
}

public static Result error(Code code, String description) {
return new Result(code.getCode(), code.getMessage(), description);
}
}

定义Code枚举类

package com.yunfei.usercenterback.common;

/**
* 错误码
*/
public enum Code {

SUCCESS(0, "ok", ""),
PARAMS_ERROR(40000, "请求参数错误", ""),
PARAMS_NULL_ERROR(40001,"请求参数为空",""),

NO_AUTH(40100, "没有权限", ""),
NOT_LOGIN(40101, "未登录", ""),

SYSTEM_ERROR(50000, "系统内部异常", ""),

;
private final Integer code;
private final String message;
private final String description;

Code(Integer code, String message, String description) {
this.code = code;
this.message = message;
this.description = description;
}

public Integer getCode() {
return code;
}

public String getMessage() {
return message;
}

public String getDescription() {
return description;
}
}

封装全局异常处理

  1. 定义业务异常类
    1. 相对于Java的异常类,支持更多的字段
    2. 自定义构造函数,更灵活/快捷的设置字段
  2. 全局异常处理器
    1. 捕获代码中所有的异常,集中处理,不然前端感受到异常
    2. 同时屏蔽掉项目框架本身的异常

实现:

  • 使用Spring AOP 在调用方法前后进行额外的处理

BussinessException类:

package com.yunfei.usercenterback.exception;

import com.yunfei.usercenterback.common.Code;

/**
* 自定义异常 业务异常
*/
public class BussinessException extends RuntimeException {
private final Integer code;
private final String description;

public BussinessException(Integer code, String message, String description) {
super(message);
this.code = code;
this.description = description;
}

public BussinessException(Code code) {
super(code.getMessage());
this.code = code.getCode();
this.description = code.getDescription();
}

public BussinessException(Code code, String description) {
super(code.getMessage());
this.code = code.getCode();
this.description = description;
}

public Integer getCode() {
return code;
}

public String getDescription() {
return description;
}
}

GlobalExceptionHandler类

package com.yunfei.usercenterback.exception;

import com.yunfei.usercenterback.common.Code;
import com.yunfei.usercenterback.common.Result;
import com.yunfei.usercenterback.common.ResultUtils;
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(BussinessException.class)
public Result businessExceptionHandler(BussinessException e) {
log.error("businessException:" + e.getMessage(), e);
return ResultUtils.error(e.getCode(), e.getMessage(), e.getDescription());
}

@ExceptionHandler(RuntimeException.class)
public Result runtimeExceptionHandler(RuntimeException e) {
log.error("runtimeException", e);
return ResultUtils.error(Code.SYSTEM_ERROR, e.getMessage(), "");
}
}

前端优化

全局响应处理

需要对接口的 通用响应 进行统一处理,比如从 response 中取出 data;或者根据 code 去集中处理错误,比如用户未登录、没权限之类的。

优点:不需要在每个接口请求中都去写相同的逻辑

参考文档:https://blog.csdn.net/huantai3334/article/details/116780020

新建一个自己的request.ts文件:

/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import {extend} from 'umi-request';
import {message} from "antd";
import {stringify} from "querystring";
import {history} from "umi";

/**
* 配置request请求时的默认参数
*/
const request = extend({
credentials: 'include', // 默认请求是否带上cookie
});

/**
* 所以请求拦截器
*/
request.interceptors.request.use((url, options): any => {
console.log(`do request url=${url}`)


return {
url,
options: {
...options,
headers: {},
},
};
});

/**
* 所有响应拦截器
*/
request.interceptors.response.use(async (response, options): Promise<any> => {
const res = await response.clone().json();
if (res.code === 0) {
return res.data
}

if (res.code === 40100) {
message.error("请先登录")
//跳转到登录页面
history.replace({
pathname: '/user/login',
search: stringify({
redirect: location.pathname
}),
})
}else{
message.error(res.description)
return null;
}
return res;
});

export default request;

定义一个统一结果返回类型:

  type Result<T> = {
code: number;
data: T;
message: string;
description: string;
}

修改原本接口的返回结果类型:

image-20231018161304023

使用自己的request,而不是umi的request

image-20231018161330509

成功完成对接:

image-20231018162848221