统一结果返回

数据返回

一般项目中为了便于交互,都会将相应结果封装为json字符串进行返回,同时还需要统一返回数据格式,一般都有以下几种基础的数据返回场景
列表:

{
  "success": true,
  "code": 20000,
  "message": "成功",
  "data": {
    "items": [
      {
        "id": "1",
        "name": "刘德华",
        "intro": "毕业于师范大学数学系,热爱教育事业,执教数学思维6年有余"
      }
    ]
  }
}

分页

{
  "success": true,
  "code": 20000,
  "message": "成功",
  "data": {
    "total": 17,
    "rows": [
      {
        "id": "1",
        "name": "刘德华",
        "intro": "毕业于师范大学数学系,热爱教育事业,执教数学思维6年有余"
      }
    ]
  }
}

没有数据返回时也需要有响应体:

{
  "success": true,
  "code": 20000,
  "message": "成功",
  "data": {}
}
失败:
{
  "success": false,
  "code": 20001,
  "message": "失败",
  "data": {}
}
因此,我们定义统一结果
{
  "success": 布尔, //响应是否成功
  "code": 数字, //响应码
  "message": 字符串, //返回消息
  "data": HashMap //返回数据,放在键值对中
}

统一结果返回实现

一般统一结果返回都会在项目中创建一个公共模块来进行实现,然后其他模块使用的时候直接引入公共模块依赖即可.
首先在公共模块创建一个基础接口,用于声明响应状态码:

public interface ResultCode {
    Integer SUCCESS = 20000; //成功
    Integer ERROR = 20001;   //失败
}

然后创建一个工具类

@Data
@Accessors(chain = true)  //链式编程注解
public class Result {

    @ApiModelProperty(value = "是否成功") //swagger注解
    private Boolean success;

    @ApiModelProperty(value = "返回状态码")
    private Integer code;

    @ApiModelProperty(value = "返回消息")
    private String message;

    @ApiModelProperty(value = "返回数据")
    private Map<String,Object> data = new HashMap<String,Object>();

    //构造方法私有化,使其他类不能new 只能使用类中固定的方法
    private Result(){}

    //成功静态方法
    @NotNull
    public static Result succeed(){
        Result resultReturn = new Result();
        resultReturn
                .setSuccess(true)
                        .setCode(ResultCode.SUCCESS) //直接引用状态码接口
                                .setMessage("执行成功");
        return resultReturn;
    }

    //失败静态方法
    @NotNull
    public static Result error(){
        Result resultReturn = new Result();
        resultReturn.setSuccess(false);
        resultReturn.setCode(ResultCode.ERROR); //直接引用状态码接口
        resultReturn.setMessage("执行失败");
        return resultReturn;
    }

    public Result success(Boolean success){
        this.setSuccess(success);
        return this;
    }
    public Result message(String message){
        this.setMessage(message);
        return this;
    }
    public Result code(Integer code){
        this.setCode(code);
        return this;
    }

    public Result Data(String key, Object value){
        this.data.put(key,value);
        return this;
    }

    public Result Data(Map<String,Object> map){
        this.setData(map);
        return this;
    }
}

在这个工具类中已经定义好了几个相应的基础数据类型,这个时候可以直接将控制层的返回类型全部定义为Result,方便进行统一的管理和其他附加操作:

    //查询所有教师
    @ApiOperation("查询所有讲师")
    @GetMapping("findAll")
    private Result findAll(){
        List<EduTeacher> list = eduTeacherService.list(null);

        return Result.succeed().Data("items",list).setCode(2001)  ;
    }

    //实现教师的逻辑删除 id通过路径来进行传递,并且通过@PathVariable 来直接获取路径中传递过来的值
    @ApiOperation("逻辑删除讲师")
    @DeleteMapping("{id}")
    private Result delete(
            @ApiParam(name = "id",value = "讲师id",required = true)
            @PathVariable String id){
        if (eduTeacherService.getById(id) == null) {
            return Result.error().setMessage("ID不存在,请重新确认");
        }else {
            Boolean b = eduTeacherService.removeById(id);
            return b? Result.succeed():Result.error();
        }

    }

分页查询

springboot整合3.5.1版本mybatisPlus需要用最新的分页拦截器插件:

//    最新mybatisplus分页需要实现分页拦截器
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }

分页查询使用到了Page类,控制层具体的实现方法如下:

//分页查询讲师方法
@ApiOperation("讲师分页")
@GetMapping("pageTeacher/{current}/{limit}")
public Result pageListTeacher(@PathVariable long current,
                              @PathVariable long limit){

    //创建page对象  1代表当前页,3代表页面记录数量 通过路径来传递值
    Page<EduTeacher> page = new Page<>(current, limit);

    //调用方法,把所有数据封装到pageTeacher中
    eduTeacherService.page(page,null);

    long total = page.getTotal();//获取总记录数
    List<EduTeacher> records = page.getRecords();//获取分页后的list集合
    long pages = page.getPages(); //总页数
    long current1 = page.getCurrent(); //当前是第几个分页
    long size = page.getSize(); //分页中最大行数
    boolean hasNext = page.hasNext(); //是否有下一页
    boolean hasPrevious = page.hasPrevious(); //是否还有上一页

    //HashMap<String, Object> map = new HashMap<>();
    //map.put("total", total);
    //map.put("rows", records);
    return Result
            .succeed()
            .data("当前分页数据集合",records)
            .data("总记录数",total)
            .data("总页数",pages)
            .data("当前页码",current1)
            .data("分页最大行数",size)
            .setMessage("分页查询成功");
}

TMD卡了我一晚上,焯! 我想到了版本的问题,但是我就是不想降低版本迁就,我就是想用这个高版本来实现功能

条件分页查询

多了一个wrapper条件构造器,在正常情况下为了方便与前端交互,会专门在实体包中在创建一个vo实体类:

@Data
public class TeacherQuery {
    //串行版本UID 不知道是什么玩意 老师用了,我注释掉后也能用
    //private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "教师名称,模糊查询")
    private String name;
    @ApiModelProperty(value = "头衔 1代表高级讲师 2代表首席讲师")
    private Integer level;
    //这里swagger的example(示例),代表如果没有特别输入,就按照这个来当做默认值
    @ApiModelProperty(value = "查询开始时间", example = "2019-01-01 10:10:10")
    private String begin;//注意,这里使用的是String类型,前端传过来的数据无需进行类型转换
    @ApiModelProperty(value = "查询结束时间", example = "2019-12-01 10:10:10")
    private String end;
}

这个vo实体类是专门接收用来条件查询的关键字段的,比如这里可以通过使用姓名和头衔之类来进行查询,没有标明的关键字段,比如讲师的介绍之类的,就无法通过这个查询.
然后就直接在控制层来写方法:

    //条件查询带分页的方法
    @GetMapping("pageTeacherCondition/{current}/{limit}")
    public Result pageTeacherCondition(
            @PathVariable long current,
            @PathVariable long limit,
            TeacherQuery teacherQuery){
        //创建page对象
        Page<EduTeacher> page = new Page<>(current, limit);
        //再新建一个条件构造器
        QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
        String name = teacherQuery.getName();
        Integer level = teacherQuery.getLevel();
        String begin = teacherQuery.getBegin();
        String end = teacherQuery.getEnd();
        
        //非空判断.注意是springframework的依赖,同名的太多了
        if (!StringUtils.isEmpty(name)){
            wrapper.like("name",name);
        }
        if (!StringUtils.isEmpty(level)){
            wrapper.eq("level",level); //eq代表等于
        }
        if (!StringUtils.isEmpty(begin)){ //wrapper构造器中ge代表大于等于
            wrapper.ge("gmt_create",begin);
        }
        if (!StringUtils.isEmpty(end)){ //gt代表小于等于
            wrapper.gt("gmt_modified",end);
        }

        //将写好的wrapper构造器注入进去
        eduTeacherService.page(page,wrapper);

        long total = page.getTotal();//获取总记录数
        List<EduTeacher> records = page.getRecords();//获取分页后的list集合
        long pages = page.getPages(); //总页数
        long current1 = page.getCurrent(); //当前是第几个分页
        long size = page.getSize(); //分页中最大行数
        boolean hasNext = page.hasNext(); //是否有下一页
        boolean hasPrevious = page.hasPrevious(); //是否还有上一页

        Map<String, Object> map = new HashMap<>();
        map.put("总记录数", total);
        map.put("当前分页数据集合",records);
        map.put("总页数",pages);
        map.put("当前页码",current1);
        map.put("分页最大行数",size);
        map.put("是否含有上一页",hasPrevious);
        map.put("是否含有下一页",hasNext);
        return Result
                .succeed()
                .data(map)
                .setMessage("分页查询成功");
    }

swagger页面是这样的:
在这里插入图片描述

控制层的请求头还可以改成:

@PostMapping("pageTeacherCondition/{current}/{limit}")
    public Result pageTeacherCondition(
            @PathVariable long current,
            @PathVariable long limit,
            @RequestBody(required = false) TeacherQuery teacherQuery){

这样在swagger页面中需要进入整体的编辑栏进行编辑wrapper条件,不能像最上面一样直接在分好的编辑栏中编辑
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值