优化封装

qian封装通用返回对象

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

{
	“name":"Zwww"
}

变成

{
	"code": 0 //业务状态码
	"data":{
		"name":"Zwww"
	 },
	 "message":"ok"
}

通用返回类

image-0b1cfe59
package com.zwnsyw.bankend.common;

import lombok.Data;

import java.io.Serializable;

/**
 * 通用返回类
 *
 * @author Zwww
 */
@Data
public class BaseResponse<T> implements Serializable {

    /**
     * 状态码
     */
    private int code;

    /**
     * 数据
     */
    private T data;

    /**
     * 消息
     */
    private String message;

    /**
     * 描述
     */
    private String description;

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

    public BaseResponse(int code, T data, String message) {
        this(code, data, message, "");
    }

    public BaseResponse(int code, T data) {
        this(code, data, "", "");
    }

    public BaseResponse(ErrorCode errorCode) {
        this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription());
    }
}

返回工具类

image-0b1cfe59

以免每次调用都要传一堆参数 这里再做一层封装 帮助填这些参数

package com.zwnsyw.bankend.common;

/**
 * 返回工具类
 *
 * @author Zwww
 */
public class ResultUtils {

    /**
     * 成功
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> BaseResponse<T> success(T data) {
        return new BaseResponse<>(0, data, "ok");
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode) {
        return new BaseResponse<>(errorCode);
    }

    /**
     * 失败
     *
     * @param code
     * @param message
     * @param description
     * @return
     */
    public static BaseResponse error(int code, String message, String description) {
        return new BaseResponse(code, null, message, description);
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode, String message, String description) {
        return new BaseResponse(errorCode.getCode(), null, message, description);
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode, String description) {
        return new BaseResponse(errorCode.getCode(), errorCode.getMessage(), description);
    }
}

封装全局异常处理

业务逻辑中 之前遇到判定为错误后 都是返回-1或者false 其实是不明确的 加上一些通用的错误码

image-ce1d6341
package com.zwnsyw.bankend.common;

/**
 * 错误码
 *
 * @author Zwww
 */
public enum ErrorCode {

    SUCCESS(0, "ok", ""),
    PARAMS_ERROR(40000, "请求参数错误", ""),
    NULL_ERROR(40001, "请求数据为空", ""),
    NOT_LOGIN(40100, "未登录", ""),
    NO_AUTH(40101, "无权限", ""),
    SYSTEM_ERROR(50000, "系统内部异常", "");

    private final int code;

    /**
     * 状态码信息
     */
    private final String message;

    /**
     * 状态码描述(详情)
     */
    private final String description;

    ErrorCode(int code, String message, String description) {
        this.code = code;
        this.message = message;
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public String getDescription() {
        return description;
    }
}

全局异常处理

定义一个东西来捕获整个业务中的异常 统一处理

image-f214b3a9

自定义异常类

相较于java的异常类 扩充更多字段

自定义构造函数 更灵活快捷设置字段

package com.zwnsyw.bankend.exception;

import com.zwnsyw.bankend.common.ErrorCode;

/**
 * 自定义异常类
 *
 * @author Zwww
 */
public class BusinessException extends RuntimeException {

    /**
     * 异常码
     */
    private final int code;

    /**
     * 描述
     */
    private final String description;

    public BusinessException(String message, int code, String description) {
        super(message);
        this.code = code;
        this.description = description;
    }

    public BusinessException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.code = errorCode.getCode();
        this.description = errorCode.getDescription();
    }

    public BusinessException(ErrorCode errorCode, String description) {
        super(errorCode.getMessage());
        this.code = errorCode.getCode();
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }
}

全局异常处理器

捕获代码中所有的异常 集中处理 让前端感知更详细的业务报错/信息

package com.zwnsyw.bankend.exception;

import com.zwnsyw.bankend.common.BaseResponse;
import com.zwnsyw.bankend.common.ErrorCode;
import com.zwnsyw.bankend.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 *
 * @author Zwww
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public BaseResponse<?> businessExceptionHandler(BusinessException e) {
        log.error("businessException: " + e.getMessage(), e);
        return ResultUtils.error(e.getCode(), e.getMessage(), e.getDescription());
    }

    @ExceptionHandler(RuntimeException.class)
    public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
        log.error("runtimeException", e);
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage(), "");
    }
}

前端对应接口

image-56a9e883

api.ts

import request from '@/plugins/globalRequest';

/** 获取当前的用户 GET /api/user/current */
export async function currentUser(options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.CurrentUser>>('/api/user/current', {
    method: 'GET',
    ...(options || {}),
  });
}

/** 退出登录接口 POST /api/user/logout */
export async function outLogin(options?: { [key: string]: any }) {
  return request<API.BaseResponse<number>>('/api/user/logout', {
    method: 'POST',
    ...(options || {}),
  });
}

/** 登录接口 POST /api/user/login */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.LoginResult>>('/api/user/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    data: body,
    ...(options || {}),
  });
}

/** 注册接口 POST /api/user/register */
export async function register(body: API.RegisterParams, options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.RegisterResult>>('/api/user/register', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    data: body,
    ...(options || {}),
  });
}

/** 搜索用户 GET /api/user/search */
export async function searchUsers(options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.CurrentUser[]>>('/api/user/search', {
    method: 'GET',
    ...(options || {}),
  });
}
image-00c5f3c3
/**

 * request 网络请求工具

 * 更详细的 api 文档: https://github.com/umijs/umi-request

 */

import {extend} from 'umi-request';

import {message} from "antd";

import {history} from "@@/core/history";

import {stringify} from "querystring";

/**

 * 配置request请求时的默认参数

 */

const request = extend({

  credentials: 'include', // 默认请求是否带上cookie

  prefix: process.env.NODE_ENV === 'production' ? 'http://user-backend.code-nav.cn' : undefined

  // requestType: 'form',

});

/**

 * 所以请求拦截器

 */

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 res.data;

});

export default request;

项目分区导航:⬅️ 15-逻辑删除mybatis-plus配置原理 | 16-优化封装 | ➡️ 17-部署