跳至主要內容

用户中心3

项目实战用户中心项目实战用户中心大约 3 分钟约 961 字全民制作人ikun

用户中心

用户注销

后端代码:

    @PostMapping("/logout")
    public Integer logout(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        return userService.logout(request);
    }

    @Override
    public Integer logout(HttpServletRequest request) {
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return 1;
    }

前端接口:

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

后端优化

封装通用返回对象

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

{
  "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/116780020open in new window

新建一个自己的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
image-20231018161304023

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

image-20231018161330509
image-20231018161330509

成功完成对接:

image-20231018162848221
image-20231018162848221
上次编辑于:
贡献者: yunfeidog