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
注意事项:
- 一个Controller下多个@ExceptionHandler上的异常类型不能出现一样的,否则运行时抛异常.Ambiguous @ExceptionHandler method mapped for;
- @ExceptionHandler下方法返回值类型支持多种,常见的ModelAndView,@ResponseBody注解标注,ResponseEntity等类型都OK.
- 一共三种解决方法:https://www.cnblogs.com/lvbinbin2yujie/p/10574812.html#type1
- 异常处理方式一. @ExceptionHandler
- 异常处理方式二. 实现HandlerExceptionResolver接口
- 异常处理方式三. @ControllerAdvice+@ExceptionHandler
- 三种方式比较说明(强烈推荐各位看一下,我觉得自己总结的比较多,嘿嘿,不对之处请指出)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,功能:
- 全局异常处理
- 全局数据绑定
- 全局数据预处理
实际返回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.