7.数据统一返回和分页处理

日拱一卒-CSDN博客,统一返回格式:https://blog.csdn.net/qidasheng2012/article/details/86736351

工具类

RequestResult统一返回实体类

package com.lcywings.sbt.Util;

import lombok.Data;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 请求结果统一返回类
 */
@Data
public class RequestResult<T> {
    /**
     * 返回状态码
     */
    private String code;

    /**
     * 返回状态说明
     */
    private String msg;

    /**
     * 返回数据
     */
    private T data;
}

ResultBuildUtil返回结果统一处理工具类

package com.lcywings.sbt.Util;

import com.lcywings.sbt.beans.Books;
import com.lcywings.sbt.constant.SystemConstant;
import oracle.jrockit.jfr.events.RequestableEventEnvironment;

import java.util.List;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 返回结果统一处理工具类
 */
public class ResultBuildUtil {

    /**
     * @author : Lcywings
     * @date : 2021/7/27 10:04
     * @acl : true
     * @description : 返回成功,不带参数
     */
    public static <T> RequestResult<T> success() {
        return success(null);
    }

    /**
     * @author : Lcywings
     * @date : 2021/7/27 10:04
     * @acl : true
     * @description : 返回成功,带参数
     */
    public static <T> RequestResult<T> success(T t) {
        // 创建统一返回类
        RequestResult<T> requestResult = new RequestResult<>();
        requestResult.setCode(SystemConstant.SYS_UNIFY_RETURN_SUCCESS_CODE);
        requestResult.setMsg(SystemConstant.SYS_UNIFY_RETURN_SUCCESS_MSG);

        // 调用业务接口查询数据
        requestResult.setData(t);

        return requestResult;
    }


    /**
     * @author : Lcywings
     * @date : 2021/7/27 10:04
     * @acl : true
     * @description : 返回失败,不带参数
     */
    public static <T> RequestResult<T> fail() {
        return fail(SystemConstant.SYS_UNIFY_RETURN_FAIL_CODE, SystemConstant.SYS_UNIFY_RETURN_FAIL_MSG);
    }

    /**
     * @author : Lcywings
     * @date : 2021/7/27 10:04
     * @acl : true
     * @description : 返回失败,带参数,不是数据
     */
    public static <T> RequestResult<T> fail(String errCode, String errMsg) {
        // 创建统一返回类
        RequestResult<T> requestResult = new RequestResult<>();
        requestResult.setCode(errCode);
        requestResult.setMsg(errMsg);

        // 调用业务接口查询数据
        requestResult.setData(null);

        return requestResult;
    }
}

把数据存入工具类的返回data中,然后工具类帮你加上状态码和状态码说明,发回给你工具类对象,你直接把工具类返回就可以了。

常量类

因为状态码、状态信息、分页数据都是固定死的,所以需要常量类去存储

package com.lcywings.sbt.constant;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 系统常量类
 */
public class SystemConstant {
    /**
     * 统一成功返回状态码
     */
    public static final String SYS_UNIFY_RETURN_SUCCESS_CODE = "0000";
    /**
     * 统一成功返回状态说明
     */
    public static final String SYS_UNIFY_RETURN_SUCCESS_MSG = "SUCCESS";
    /**
     * 统一失败返回状态码
     */
    public static final String SYS_UNIFY_RETURN_FAIL_CODE = "9999";
    /**
     * 统一失败返回状态说明
     */
    public static final String SYS_UNIFY_RETURN_FAIL_MSG = "FAIL";
    /**
     * 默认统一分页当前页码
     */
    public static final int SYS_INIT_PAGE_NO = 1;
    /**
     * 默认统一分页页面容量
     */
    public static final int SYS_INIT_PAGE_SIZE = 3;

}

异常类

自定义异常,当返回失败时,自定义的返回异常状态码

除了继承RuntimeException的五个构造器之外,还需要自行写带一个异常枚举参数的构造器,方便返回异常状态信息

package com.lcywings.sbt.excpt;

import com.lcywings.sbt.constant.BookExcptEnum;

import java.awt.print.Book;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description :
 */
public class BookException extends RuntimeException {

    /**
     * 序列号
     */
    private static final long serialVersionUID = -7034891190245466539L;
    
    /**
     * 异常枚举
     */
    BookExcptEnum bookExcptEnum;

    public BookException() {
    }

    public BookException(String message) {
        super(message);
    }

    public BookException(String message, Throwable cause) {
        super(message, cause);
    }

    public BookException(Throwable cause) {
        super(cause);
    }

    public BookException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    public BookException(BookExcptEnum bookExcptEnum) {
        this.bookExcptEnum = bookExcptEnum;
    }

    public BookExcptEnum getBookExcptEnum() {
        return bookExcptEnum;
    }
}

异常枚举

约等于常量类,用于方便的返回异常

package com.lcywings.sbt.constant;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 异常枚举信息类
 */
public enum BookExcptEnum {

    /**
     * 系统异常
     */
    SYSTEM_EXCPT("9000", "图书系统异常"),

    /**
     * 传入参数为空
     */
    REQUEST_PARAM_EMPTY("1001", "传入参数为空"),

    /**
     * 传入参数非法
     */
    REQUEST_PARAM_ILLEGAL("1002", "传入参数非法"),

    /**
     * 数据库访问异常
     */
    DATABASE_VISIT_EXCPT("2001", "数据库访问异常"),

    /**
     * 网络异常异常
     */
    NETWORK_CONNECT_EXCPT("3001", "网络连接异常");

    /**
     * 异常码
     */
    private String errCode;

    /**
     * 异常说明
     */
    private String errMsg;

    /**
     * 带参构造方法
     */
    BookExcptEnum(String errCode, String errMsg) {
        this.errCode = errCode;
        this.errMsg = errMsg;
    }

    public String getErrCode() {
        return errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

}

异常统一处理类

说明:针对可能出问题的Controller,新增注解方法@ExceptionHandler

注意事项:

  1. 一个Controller下多个@ExceptionHandler上的异常类型不能出现一样的,否则运行时抛异常.Ambiguous @ExceptionHandler method mapped for;
  2. @ExceptionHandler下方法返回值类型支持多种,常见的ModelAndView,@ResponseBody注解标注,ResponseEntity等类型都OK.
  3. 一共三种解决方法:https://www.cnblogs.com/lvbinbin2yujie/p/10574812.html#type1
    1. 异常处理方式一. @ExceptionHandler
    2. 异常处理方式二. 实现HandlerExceptionResolver接口
    3. 异常处理方式三. @ControllerAdvice+@ExceptionHandler
    4. 三种方式比较说明(强烈推荐各位看一下,我觉得自己总结的比较多,嘿嘿,不对之处请指出)https://www.cnblogs.com/lvbinbin2yujie/p/10574812.html#type4
package com.lcywings.sbt.excpt;

import com.lcywings.sbt.Util.RequestResult;
import com.lcywings.sbt.Util.ResultBuildUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.awt.print.Book;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description :
 */
@ControllerAdvice
@Slf4j
public class BookExcptHandler {

    /**
     * @author : Lcywings
     * @date : 2021/7/27 11:13
     * @acl : true
     * @description : 所有抛出自定义异常的统一处理方法,进行统一返回
     */
    @ResponseBody
    @ExceptionHandler(BookException.class)
    public RequestResult<String> handBookExcpt(BookException bookException) {
        log.error("------ 获取自定义异常,异常码:{} ------", bookException.getBookExcptEnum().getErrMsg());
        return ResultBuildUtil.fail(bookException.getBookExcptEnum().getErrCode(), bookException.getBookExcptEnum().getErrMsg());
    }

}

@ControllerAdvice:增强Controller,功能:

  1. 全局异常处理
  2. 全局数据绑定
  3. 全局数据预处理

实际返回Controller具体实现

前提:

  • 已经使用springboot连接好数据库
  • 使用插件导入好mapper持久层的接口、实体类、实体查询工具类

controller类

import java.util.List;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 图书操作入口
 */
@RestController
@Slf4j
public class BooksController {


    @Autowired
    BooksService booksService;

    /**
     * @author : Lcywings
     * @date : 2021/7/27 9:17
     * @acl : true
     * @description : 抛出自定义异常的统—处理方法,进行统一返回
     */
    @GetMapping("/bookList")
    public RequestResult<List<Books>> bookList(@RequestParam String publish) {

        try {
            log.info("------ 根据出版社:{},查询图书列表", publish);

            // 调用业务接口查询数据,统一返回
            return ResultBuildUtil.success(booksService.queryBookListByPubilsh(publish));
        } catch (Exception e) {
            log.error("****** 查询图书异常,异常信息为:{}", e.getLocalizedMessage());

            //修改数据库配置,模拟,手动抛出数据库访问异常
            throw new BookException(BookExcptEnum.DATABASE_VISIT_EXCPT);
        }

    }
}

service的实现

@Autowired(required = false)
private BooksMapper booksMapper;

@Override
public List<Books> queryBookListByPubilsh(String publish) {
    // 创建查询条件
    BooksExample booksExample = new BooksExample();
    booksExample.setOrderByClause(" id desc ");

    // 出版社查询条件
    BooksExample.Criteria criteria = booksExample.createCriteria();
    criteria.andPublishEqualTo(publish);


    return booksMapper.selectByExample(booksExample);
}

以上是统一返回的处理


统一分页返回

分页支持工具类

声明相应的分页属性:

  • ​ 当前页currPageNo
  • ​ 起始行pageIndex
  • ​ 分页显示条数pageSize
  • ​ 总条数totalCount
  • ​ 总页数totalPage
  • ​ 分页数据Collection data

前端传参:

  • ​ 当前页currPageNo
  • ​ 分页显示条数pageSize

实现直接搞定一些数据:

  • pageIndex:当设置当前页(currPageNo)时,可以确定起始行
  • totalPage:当设置总条数(totalCount)时,可以确定总页数
package com.lcywings.sbt.Util;

import com.lcywings.sbt.constant.SystemConstant;
import lombok.Data;

import java.util.Collection;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 统一分页处理类
 */
@Data
public class PageSupport<T> {
    /**
     * 当前页码
     */
    private int currPageNo = SystemConstant.SYS_INIT_PAGE_NO;

    /**
     * 起始行
     */
    private int pageIndex;

    /**
     * 分页显示条数
     */
    private int pageSize = SystemConstant.SYS_INIT_PAGE_SIZE;

    /**
     * 总条数
     */
    private int totalCount;

    /**
     * 总页数
     */
    private int totalPage;

    /**
     * 分页数据
     */
    private Collection<T> data;

    /**
     * 当设置总条数时,可以确定总页数
     */
    public void setTotalCount(int totalCount) {
        if (totalCount > 0) {
            this.totalCount = totalCount;
            this.totalPage = this.totalCount % this.pageSize == 0 ?
                    this.totalCount / this.pageSize : this.totalCount / this.pageSize + 1;
        }
    }

    /**
     * 当设置当前页码时,可以确定起始行
     */
    public void setCurrPageNo(int currPageNo) {
        if (currPageNo > 0) {
            this.currPageNo = currPageNo;
            this.pageIndex = (this.currPageNo - 1) * this.pageSize;
        }
    }
}

实际返回Controller具体实现

前提:

  • 已经使用springboot连接好数据库
  • 使用插件导入好mapper持久层的接口、实体类、实体查询工具类

controller类

package com.lcywings.sbt.controller;

import com.lcywings.sbt.Util.PageSupport;
import com.lcywings.sbt.Util.RequestResult;
import com.lcywings.sbt.Util.ResultBuildUtil;
import com.lcywings.sbt.beans.Books;
import com.lcywings.sbt.constant.BookExcptEnum;
import com.lcywings.sbt.excpt.BookException;
import com.lcywings.sbt.service.BooksService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * Created on 2021/7/27.
 * <p>
 * Author : Lcywings
 * <p>
 * Description : 图书操作入口
 */
@RestController
@Slf4j
public class BooksController {


    @Autowired
    BooksService booksService;
      /**
     * @author : Lcywings
     * @date : 2021/7/27 9:17
     * @acl : true
     * @description : 抛出自定义异常的统—处理方法,进行统一返回,使用分页
     */
@GetMapping("/bookListPage")
public RequestResult<PageSupport<Books>> bookListUsePage(@RequestParam String publish,
                                                             @RequestParam Integer pageNo,
                                                             @RequestParam Integer pageSize) {
        try {
            log.info("------ 根据出版社:{},查询图书列表,当前页码:{},查询条数{}", publish, pageNo, pageSize);

            // 调用业务接口查询数据,统一返回
            return ResultBuildUtil.success(booksService.queryBookListByPubilsUsePage(publish, pageNo, pageSize));
        } catch (Exception e) {
            log.error("****** 查询图书异常,异常信息为:{}", e.getLocalizedMessage());

            // 抛出系统异常
            throw new BookException(BookExcptEnum.SYSTEM_EXCPT);
        }

    }
}

service实现

@Override
public PageSupport<Books> queryBookListByPubilsUsePage(String publish, Integer pageNo, Integer pageSize) {
    // 创建分页对象
    PageSupport<Books> pageSuppport = new PageSupport<>();

    // 查询条数,对应查询条数
    if (pageSize <= 0) {
        pageSuppport.setPageSize(SystemConstant.SYS_INIT_PAGE_SIZE);
    } else {
        pageSuppport.setPageSize(pageSize);
    }

    // 参数处理,对应页码和查询条数
    if (pageNo <= 0) {
        pageSuppport.setCurrPageNo(SystemConstant.SYS_INIT_PAGE_NO);
    } else {
        pageSuppport.setCurrPageNo(pageNo);
    }

    // 创建查询条件对象
    BooksExample booksExample = new BooksExample();
    BooksExample.Criteria criteria = booksExample.createCriteria();
    criteria.andPublishEqualTo(publish);

    // 查询总数
    pageSuppport.setTotalCount((int) booksMapper.countByExample(booksExample));

    // 设置分页
    booksExample.setOrderByClause(" id ");
    booksExample.setOffset((long) pageSuppport.getPageIndex());
    booksExample.setLimit(pageSuppport.getPageSize());

    // 存入分页数据
    pageSuppport.setData(booksMapper.selectByExample(booksExample));

    return pageSuppport;
}

课后作业:

使用newsdb,练习查询新闻列表

要求:

  • 根据新闻类型cid或者文档标题title模糊动态查询,如果没有参数查询所有,有哪个参数就根据那个参数查询
  • 使用统一分页返回结果,每页展示条数为2
  • 必须使用postman进行测试,演示结果录屏发到群里

使用json格式参数修改新闻

并进行统一结果返回,格式

{"code": "0000","msg": "SUCCESS","data": "修改后的实体数据"}
{"code": "9999","msg": "FAIL","data": "修改参数实体数据"}

注意:json格式参数,必须是post请求才可以

优先完成第一个作业,第二个有时间可以提高做一下

Q.E.D.