四、统一返回结果对象
1、统一返回数据格式
项目中我们会将响应封装成json返回,一般我们会将所有接口的数据格式统一, 使前端(iOS Android, Web)对数据的操作更一致、轻松。
一般情况下,统一返回数据格式没有固定的格式,只要能描述清楚返回的数据状态以及要返回的具体数据就可以。但是一般会包含状态码、返回消息、数据这几部分内容
例如,我们的系统要求返回的基本数据格式如下:
携带数据成功
{ "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 //返回数据,放在键值对中 }
2、统一结果返回类
- 在common模块下创建子模块common_utils
- 创建接口 定义返回码—创建包 com.rg.commonutils,创建接口
ResultCode
public interface ResultCode { public static Integer SUCCESS = 20000;//成功 public static Integer ERROR = 20001;//失败 }
- 创建结果类—创建
R
类
@Data public class R { @ApiModelProperty(value = "是否成功") private Boolean success; @ApiModelProperty(value = "返回码") private Integer code; @ApiModelProperty(value = "返回消息") private String message; @ApiModelProperty(value = "返回数据") private Map <String, Object> data = new HashMap <String, Object>(); private R(){} //构造方法私有化. 目的:禁止随意new 方法,只能使用我们定义的方法. public static R ok(){//定义成功方法 R r = new R(); r.setSuccess(true); r.setCode(ResultCode.SUCCESS); r.setMessage("成功"); return r;//为了链式编程 } public static R error(){//定义失败方法 R r = new R(); r.setSuccess(false); r.setCode(ResultCode.ERROR); r.setMessage("失败"); return r;//为了链式编程 } //自定义属性的相关方法(带链式编程功能) public R success(Boolean success){ this.setSuccess(success); return this; } public R message(String message){ this.setMessage(message); return this; } public R code(Integer code){ this.setCode(code); return this; } public R data(String key, Object value){ this.data.put(key, value); return this; } public R data(Map<String,Object> map){ this.setData(map); return this; } }
3、统一返回结果的使用
- 在service模块中添加依赖—common_utils
- 修改Controller中的返回结果
//1.查询讲师所有数据 使用Rest风格.. @ApiOperation("所有讲师列表") @GetMapping("findAll") public List <EduTeacher> findAll() { List <EduTeacher> eduTeacherList = eduTeacherService.list(null); return eduTeacherList; } //2.通过id逻辑删除讲师 @ApiOperation("根据ID删除讲师") @DeleteMapping("removeById/{id}") public R removeById(@ApiParam(name = "id", value = "讲师ID", required = true) @PathVariable String id) { boolean flag = eduTeacherService.removeById(id); if (flag) { return R.ok(); } else { return R.error(); } }
五、讲师分页查询
1、EduConfig中配置分页插件
/** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor(); }
2、EduTeacherController中添加分页方法
//3.分页查询讲师 @ApiOperation("分页查询讲师") @GetMapping("pageList/{current}/{limit}") public R pageList(@ApiParam(name = "current", value = "当前页码", required = true) @PathVariable("current") Integer current, @ApiParam(name = "limit", value = "每页记录数", required = true) @PathVariable("limit") Integer limit) { Page <EduTeacher> page = new Page <>(current, limit); //进行分页查询 eduTeacherService.page(page, null);//最后这些属性既可以通过page也可以通过iPage获取,因为分页后的数据会被重新封装到这些对象里面. // Map <String, Object> map = new HashMap <>(); // map.put("total",page.getTotal()); // map.put("rows", page.getRecords()); // return R.ok().data(map); return R.ok().data("total", page.getTotal()).data("rows", page.getRecords()); }
六、讲师条件查询带分页
要求:根据讲师名称name,讲师头衔level、讲师入驻时间查询
1、创建查询对象
创建com.rg.eduservice.entiy.vo包,创建TeacherQuery
类查询对象
@ApiModel(value = "Teacher查询对象",description = "讲师查询对象封装") @Data public class TeacherQuery implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "教师名称,模糊查询") private String name; @ApiModelProperty(value = "头衔 1高级讲师 2首席讲师") private Integer level; @ApiModelProperty(value = "查询开始时间", example = "2019-01-01 10:10:10") private String begin; @ApiModelProperty(value = "查询结束时间", example = "2019-12-01 10:10:10") private String end; }
2、编写controller
//4.根据条件查询讲师 @ApiOperation("根据条件查询讲师") @PostMapping("pageQuery/{current}/{limit}") //@RequestBody: 通过json传递数据,把数据封装到对象中. json数据只能封装到请求体中,所以就需要用到POST请求 public R pageQuery(@ApiParam(name = "current", value = "当前页码", required = true) @PathVariable("current") Integer current, @ApiParam(name = "limit", value = "每页记录数", required = true) @PathVariable("limit") Integer limit, @ApiParam(name = "teacherQuery",value = "查询条件",required = false) @RequestBody(required = false) TeacherQuery teacherQuery){//required = false,表示条件可有可无 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(); //mybatis我们学过动态sql,这里我们可以使用MP简化操作 if(!StringUtils.isEmpty(name)){ wrapper.like("name", name); } if(!StringUtils.isEmpty(level)){ wrapper.eq("level", level); } if(!StringUtils.isEmpty(begin)){ wrapper.ge("gmt_create", begin); } if(!StringUtils.isEmpty(end)){ wrapper.le("gmt_modified", end); } eduTeacherService.page(page, wrapper);//分页查询 return R.ok().data("total", page.getTotal()).data("rows", page.getRecords()); }
七、自动填充封装
1、在service-base中创建自动填充类
@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { //这里设置的是属性名称,而非字段名称 this.setFieldValByName("gmtCreate", new Date(), metaObject); this.setFieldValByName("gmtModified", new Date(), metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("gmtModified", new Date(), metaObject); } }
2、在实体类添加自动填充注解
八、讲师添加功能
1、在实体类添加自动填充注解
2.EduTeacherController中新增方法
//5.添加讲师 @ApiOperation("添加讲师") @PostMapping("addTeacher") public R addTeacher(@ApiParam(value = "eduTeacher",name = "讲师信息") @RequestBody EduTeacher eduTeacher){ boolean flag = eduTeacherService.save(eduTeacher); if (flag){ return R.ok(); }else{ return R.error(); } }
3.Swagger中测试