用户中心3
大约 3 分钟约 961 字
用户中心
用户注销
后端代码:
@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;
}
}
封装全局异常处理
- 定义业务异常类
- 相对于Java的异常类,支持更多的字段
- 自定义构造函数,更灵活/快捷的设置字段
- 全局异常处理器
- 捕获代码中所有的异常,集中处理,不然前端感受到异常
- 同时屏蔽掉项目框架本身的异常
实现:
- 使用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;
}
修改原本接口的返回结果类型:
使用自己的request,而不是umi的request
成功完成对接: