携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情
大家好! 我是慕歌,一只想教你学习 Spring Boot的野生coder! 欢迎来到慕歌的 Sping boot系列教程,希望通过这个教程带大家搭建基础的 Spring Boot项目,该教程所有知识点均来源于本人的真实开发!
前言
在前一节的学习中,慕歌向大家介绍了在idea 开发工具中集成 Git版本控制器,进行版本控制处理。希望大家能在自己的开发过程中,也学习使用git 版本控制,进行团队开发,或者对自己的项目进行版本控制。我们在进行开发的过程中,通过查看不同的代码版本,进行代码对比,不断优化我们的开发。并且可以通过gitee 获取优质的开源项目,学习优秀的开源项目,并进行自己的二次开发。那么在这一节中,慕歌将向大家带来优雅的结果集返回。
引入:
这里的结果集返回,将会广泛引用到我们的全局结果返回,用于数据的返回,前端通过我们返回的数据在进行渲染,所有一个统一的结果集返回就显得格外的重要。
<!-- web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
开发:
使用该结果集作为统一结果集,他需要满足我们的多种数据格式的放入,并且作为与前端交互的接口,我们需要与前端进行一定的协调,确定如何确定返回数据的格式,以及状态码。
这里我认为有几个重要的规范:
- 状态码:尽可能准确的状态码,以及尽可能少的状态码,每个状态码有具体的描述,准确的使用场景,不能出现过多的状态码,以及状态码的状态进行混用。
- 状态码描述:我们可以将状态码信息放入这个字段中,一同返回前端,前端能够清晰的了解该状态码是何种作用,在某些特殊的接口中还可以将后端的提示信息放入其中。
- 数据:将数据包放在该字段下,这样前端通过该字段统一获取数据。
{3 items
"msg":"success"
"code":200
"data":{11 items
"id":12
"type":1
"uid":1001
"createTime":"2022-07-20 17:22:50"
"updateTime":"2022-07-27 17:08:52"
}
}
那么如何在后端生成这样的数据返回,我们需要使用自己的工具类,以及状态码定义:
import channel.cret.exception.StatusCode;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 全局请求返回接口
* @param <T>
*/
public class R<T> extends HashMap<String, Object> implements Serializable {
//序列化
private static final long serialVersionUID = 1L;
// 状态码
private Integer code;
// 返回信息
private String msg;
// 返回数据,因为返回数据是不确定类型,所以只能考虑Object或者泛型
private T data;
//默认成功code
private static final int OK_CODE = 200;
//默认成功msg
private static final String OK_MSG = "success";
public R() {
put("code", OK_CODE);
put("msg", OK_MSG);
}
//无参返回成功
public static R success(){
R r = new R();
return r;
}
//返回信息
public static R success(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
//无参返回成功
public static <T> R success(T data){
R r = new R();
r.put("data",data);
return r;
}
//返回信息
public static <T> R success(String msg,T data) {
R r = new R();
r.put("msg", msg);
r.put("data",data);
return r;
}
//返回信息
public static <T> R success(ResultCode resultCode,T data) {
R r = new R();
r.put("msg", resultCode.getMsg());
r.put("data",data);
return r;
}
//返回多参数
public static R success(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
//默认错误
public static R error(){
R r = new R();
r.put("code",105);
r.put("msg","未知错误,请联系管理员");
return r;
}
//自定义 错误信息
public static R error(String msg) {
return error(101,msg);
}
//自定义 错误码 错误信息
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
//定义错误枚举
public static R error(StatusCode statusCode){
R r = new R();
r.put("code",statusCode.getCode());
r.put("msg",statusCode.getMsg());
return r;
}
//追加信息
public R<T> put(String key, Object value) {
super.put(key, value);
return this;
}
}
状态码的使用需要我们与前端进行协调:
public interface StatusCode {
//状态码
public int getCode();
//状态信息描述
public String getMsg();
}
这里的状态码是一部分,大家可根据自己的需求进行拓展:
import channel.cret.exception.StatusCode;
import lombok.Getter;
/**
* 枚举状态码
* 状态名,状态码,状态信息
*/
@Getter
public enum ResultCode implements StatusCode {
SUCCESS(200, "请求成功"),
FAILED(101, "请求失败"),
NEED_USER_NAME(101,"用户名不能为空"),
NEED_USER_PWD(101,"密码不能为空"),
NEED_USER_PWDS(101,"重复密码不能为空"),
NEED_MOBILE(101,"手机号码不能为空"),
ERROR_PASSWORD(101,"账号或密码错误"),
ERROR_USERNAME(101,"用户名不可用"),
ERROR_FROZE(101,"用户已被注销或冻结"),
ERROR_UNFROZE(101,"用户已被注销或未被冻结"),
REPEAT_PASSWORD(101,"密码不能与之前密码相同"),
NEED_SMSCODE(101,"短信验证码不能为空"),
NEED_CODE(101,"验证码不能为空"),
VALIDATE_ERROR(101,"表单信息不能为空"),
USER_LOGIN_IS_FAILURE(102,"登录状态已过期"),
RESPONSE_PACK_ERROR(105, "服务器状态异常");
private int code;
private String msg;
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
这里的使用可参考,以下登录示例:
/**
* 登录
* @param loginVo 登录表单
* @return
*/
@RequestMapping("/login")
public R login(@RequestBody @Validated AdminLoginVo loginVo){
//登录
boolean login = adminUserService.login(loginVo);
if(login){
// 获取指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
if(StpUtil.isDisable(Constant.USER_ID)){
return R.error("账号被封禁");
}
log.info("{}登录成功",loginVo.getUsername());
//日志
adminLogService.log("登录","登录成功"+loginVo.getUsername());
// 获取 Token 相关参数
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
//返回token信息
return R.success(tokenInfo);
}
//登录失败
return R.error(ResultCode.ERROR_PASSWORD);
}
结语
这一章的分享到这里就结束了,下一节中还将带来异常控制的分享!
如果您觉得本文不错,欢迎点赞支持,您的关注是我坚持的动力!