service-oa模块
SysRoleControllerpackage com.atguigu.auth.controller;import com.atguigu.auth.service.SysRoleService;import com.atguigu.model.system.SysRole;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;///角色管理 控制层 10@RestController ///交给spring管理和返回json数据@RequestMapping("/admin/system/sysRole")public class SysRoleController { //注入 @Autowired private SysRoleService sysRoleService; }
2.查询所有角色100service-oa模块SysRoleController
//1 查询所有角色 和 当前用户所属的角色 10 ////如果测试,访问此路径 http://localhost:8800/admin/system/sysRole/findAll @GetMapping("findAll") public List<SysRole> findAll(){ ////调用serivice方法 List<SysRole> list = sysRoleService.list(); return list; }
测试,成功启动启动类
浏览器输入http://localhost:8800/admin/system/sysRole/findAll
当然也可以使用postman测试
3.定义统一返回结果对象11在项目中,我们将将响应包装成json返回。一般来说,我们将统一所有接口的数据格式,使前端(iOSAndroid,Web)对数据的操作更一致、更容易。
一般来说,只要您能清楚地描述返回的数据状态和要返回的具体数据,统一的返回数据格式就没有固定的格式。但它通常包括状态码、返回信息和数据
例如,我们系统要求返回的基本数据格式如下:
列表:{ "code": 200, "message": "成功", "data": [ { "id": 2, "roleName": “系统管理员” } ], "ok": true}
分页:{ "code": 200, "message": "成功", "data": { "records": [ { "id": 2, "roleName": “系统管理员” }, { "id": 3, "name": “普通管理员” } ], "total": 10, "size": 3, "current": 1, "orders": [], "hitCount": false, "searchCount": true, "pages": 2 }, "ok": true}
没有返回数据:{ "code": 200, "message": "成功", "data": null, "ok": true}
失败:{ "code": 201, "message": "失败", "data": null, "ok": false}
3.1定义统一返回结果对象11操作模块:common-util
后续也会使用其他模块,所以提取到common-util模块
Resultcodenumpackage com.atguigu.common.result;import lombok.Getter;///这是一个统一返回结果对象的枚举配置定义 11@Getterpublic enum ResultCodeEnum { SUCCESS(200,“成功”), FAIL(201, “失败”, ; private Integer code; private String message; private ResultCodeEnum(Integer code, String message) { this.code = code; this.message = message; }}
统一结果返回类Resultttpackage com.atguigu.common.result;import lombok.Data;///定义统一结果返回类 11@Datapublic class Result<T> { private Integer code;//状态码 private String message;//返回信息 private T data;//数据 //私有化 ,私有化结构意味着这一类不能new。如果其他人想操作这一类,他们只能使用这种static方法 private Result() {} //包装返回是数据 11 public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) { Result<T> result = new Result<>(); //包装数据 if(body != null) { result.setData(body); } //状态码 result.setCode(resultCodeEnum.getCode()); //返回信息 result.setMessage(resultCodeEnum.getMessage()); return result; } //成功 无数据的 11 public static<T> Result<T> ok() { return build(null,ResultCodeEnum.SUCCESS); } //成功 有数据的 11 public static<T> Result<T> ok(T data) { return build(data,ResultCodeEnum.SUCCESS); } //失败 无数据的 11 public static<T> Result<T> fail() { return build(null,ResultCodeEnum.FAIL); } //失败 有数据的 11 public static<T> Result<T> fail(T data) { return build(data,ResultCodeEnum.FAIL); } public Result<T> message(String msg){ this.setMessage(msg); return this; } public Result<T> code(Integer code){ this.setCode(code); return this; }}
3.2转换查询所有角色11service-oa模块//改造 查询所有角色 和 当前用户所属的角色 11 ////如果测试,访问此路径 http://localhost:8800/admin/system/sysRole/findAll @GetMapping("findAll") public Result findAll(){ ////调用serivice方法 List<SysRole> list = sysRoleService.list(); return Result.ok(list); }
浏览器测试
postman测试
4.knife4j12文档地址:https://doc.xiaominfo.com/
knife4j是JavaMVC框架集成Swager生成Api文档的增强解决方案。
4.1Swagger介绍介绍api文档是前后分离开发模式中最好的沟通方式。
用于生成、描述、调用和可视化RESTful风格的Web服务,Swagger是一个标准化、完整的框架。
1、及时性(接口变更后,相关前后端开发人员可及时准确通知)
2、标准化(并保证接口的标准化,如接口地址、请求方式、参数、响应格式和错误信息)
3、一致性(接口信息一致,不会因为开发人员获得的文档版本不一致而产生分歧)
4、可测性(直接测试接口文档,方便理解业务)
4.2集成knife4j集成knife4j属于service模块的公共资源,因此我们集成到service-uitl模块
4.2.1添加依赖操作模块:service-uitl
pom.xml
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId></dependency>
说明:guigu-auth-parent已经加入版本管理
4.2.22添加knife4j配置类12操作模块:service-uitl
Knife4jConfigpackage com.atguigu.common.config.knife4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.ParameterBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.schema.ModelRef;import springfox.documentation.service.ApiInfo;import springfox.documentation.service.Contact;import springfox.documentation.service.Parameter;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableswagerWebMvc;import java.util.ArrayList;import java.util.List;//Knife4j配置类,Knife4j是Java MVC框架集成Swager生成Api文档的增强解决方案。//方便我们测试,前后端统一接口等功能 12public class Knife4jConfig { @Bean public Docket adminApiConfig(){ List<Parameter> pars = new ArrayList<>(); ParameterBuilder tokenPar = new ParameterBuilder(); tokenPar.name("token") .description(用户token) .defaultValue("") .modelRef(new ModelRef("string")) .parameterType("header") .required(false) .build(); pars.add(tokenPar.build()); ///添加head参数endd Docket adminApi = new Docket(DocumentationType.SWAGGER_2) .groupName("adminApi") .apiInfo(adminApiInfo()) .select() ////只显示admin路径下的页面 .apis(RequestHandlerSelectors.basePackage("com.atguigu")) .paths(PathSelectors.regex("/admin/.*")) .build() .globalOperationParameters(pars); return adminApi; } private ApiInfo adminApiInfo(){ return new ApiInfoBuilder() .title(“后台管理系统-API文档” .description(本文描述了后台管理系统微服务接口的定义) .version("1.0") .contact(new Contact("atguigu", "http://atguigu.com", "atguigu@qq.com")) .build(); }}
4.2.在3controler层添加注释12service-oa模块
SysRoleController测试启动服务
输入http的浏览器://localhost:8800/doc.html成功
5.条件分页查询角色13第一步是配置分页插件
第二步是编写controller的分页方法
(1)需要参数:分页相关参数(当前页面和每页显示记录数)
(2)所需参数:条件参数
第三步是使用service的方法来实现条件分页查询
5.1启动类修改13service-oa模块启动类ServiceAuthaplicationionpackage com.atguigu.auth;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.ComponentScan;//启动类 6@SpringBootApplication@ComponentScan("com.atguigu") //设置扫描规则,这里扫描那些包,扫描com.publiccatguigu包及其子包 class ServiceAuthApplication { public static void main(String[] args) { SpringApplication.run(ServiceAuthApplication.class, args); }}
5.1配置分页插件133操作模块:service-uitl,service公共资源描述:我们将@MapperScan("com.atguigu.auth.mapper()提取到配置类上,统一管理,无需启动。
MybatisPlusConfigpackage com.atguigu.common.config.mp;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;///这是一个分页插件 13@Configuration@MapperScan("com.atguigu.auth.mapper"//表示可以找到mapper动态创建的对象public class MybatisPlusConfig { /** * 新的分页插件,遵循mybatis的规则,一缓和二缓, 13 * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false * 避免缓存问题(旧插件移除后会一起移除此属性) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); }}
5.2条件分页查询实现133service-oa模块
SysRoleController//条件分页查询 13 //page 当前页 limit 每页显示记录数 //SysRoleQueryVo 条件对象 @ApiOperation(“条件分页查询”) @GetMapping("{page}/{limit}") public Result pageQueryRole(@PathVariable Long page, @PathVariable Long limit, SysRoleQueryVo sysRoleQueryVo) { ////调用service实现 //1 创建Page对象,分页相关参数的传输 //page 当前页 limit 每页显示记录数 Page<SysRole> pageParam = new Page<>(page,limit); //2 判断封装条件是否为空,封装不为空 LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>(); String roleName = sysRoleQueryVo.getRoleName(); if(!StringUtils.isEmpty(roleName)) { //封装 like模糊查询 wrapper.like(SysRole::getRoleName,roleName); } //3 实现调用方法 IPage<SysRole> pageModel = sysRoleService.page(pageParam, wrapper); return Result.ok(pageModel); }
测试http://localhost:8800/doc.html
添加条件
6.添加角色14service-oa模块
SysRoleController///添加角色 14 @ApiOperation(“添加角色”) @PostMapping("save") public Result save(@RequestBody SysRole role) {/@Requestbody通过json格式传输到对象中 ////调用service方法 boolean is_success = sysRoleService.save(role); if(is_success) { return Result.ok(); } else { return Result.fail(); } }
7.修改角色14service-oa模块
SysRoleController//修改角色-根据ID查询- 14 //说白了,这种方法就是基于ID查询。 @ApiOperation(“按id查询”) @GetMapping("get/{id}"//使用restful风格 public Result get(@PathVariable Long id) {/@PathVariable从restful获得的值 SysRole sysRole = sysRoleService.getById(id); return Result.ok(sysRole); }
///修改角色-最终修改 14 @ApiOperation(“修改角色”) @PutMapping ("update") public Result update(@RequestBody SysRole role) { ////调用service方法 boolean is_success = sysRoleService.updateById(role); if(is_success) { return Result.ok(); } else { return Result.fail(); } }
8.删除角色(id删除和批量删除)14service-oa模块
SysRoleController//按id删除 14 @ApiOperation(根据id删除) @DeleteMapping("remove/{id}") public Result remove(@PathVariable Long id) { boolean is_success = sysRoleService.removeById(id); if(is_success) { return Result.ok(); } else { return Result.fail(); } }
9.配置日期格式15.
service-oa模块
application-dev.ymljackson: # 配置时间 15 date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
再次正确查询时间格式
10.统一异常处理1510.1制造异常service-oa模块
我们给findalll查询所有模拟异常
SysRoleController//改造 查询所有角色 和 当前用户所属的角色 11 ////如果测试,访问此路径 http://localhost:8800/admin/system/sysRole/findAll @ApiOperation(“查询所有角色”) ///knife4j生成接口文档的中文说明 12 @GetMapping("findAll") public Result findAll(){ ////调用serivice方法 List<SysRole> list = sysRoleService.list(); //模拟异常 15 int i = 10/0; return Result.ok(list); }
测试
10.2统一异常15如果我们希望将异常结果显示为统一的返回结果对象,并对系统的异常信息进行统一处理,则需要对异常进行统一处理。
15.全局异常处理service-util模块
GlobalExceptionHandlerpackage com.atguigu.common.config.exception;import com.atguigu.common.result.Result;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;//统一全局异常类 15@ControllerAdvice ////通过AOP将这个功能添加到当前的类中去public class GlobalExceptionHandler { //全局异常处理,执行的方法 @ExceptionHandler(Exception.class)///指定哪种异常发生时会执行此方法 @ResponseBody///返回json数据 15 public Result error(Exception e) { e.printStackTrace(); return Result.fail().message(”执行全局异常处理..."); }}
16.特定异常处理service-util模块
GlobalExceptionHandler//特定异常处理 16 @ExceptionHandler(ArithmeticException.class) @ResponseBody public Result error(ArithmeticException e) { e.printStackTrace(); return Result.fail().message(”执行特定异常处理..."); }
自定义异常处理16第一步是创建异常类,继承RuntimeException
第二步是在异常类别中添加属性、状态码和描述信息
第三步是在出现异常的地方,手动抛出异常
第四步是在之前创建类别并添加执行方法
service-util模块
GuiguExceptionpackage com.atguigu.common.config.exception;import com.atguigu.common.result.ResultCodeEnum;import lombok.Data;//自定义异常类 16@Datapublic class GuiguException extends RuntimeException { private Integer code;//状态码 private String msg;//描述信息 public GuiguException(Integer code,String msg) { super(msg); this.code = code; this.msg = msg; } /** * 接收枚举类型的对象 * @param resultCodeEnum */ public GuiguException(ResultCodeEnum resultCodeEnum) { super(resultCodeEnum.getMessage()); this.code = resultCodeEnum.getCode(); this.msg = resultCodeEnum.getMessage(); } @Override public String toString() { return "GuliException{" + "code=" + code + ", message=" + this.getMessage() + '}'; }}
手动抛出异常(我们在查询所有模拟)
service-oa模块
SysRoleController
//改造 查询所有角色 和 当前用户所属的角色 11 ////如果测试,访问此路径 http://localhost:8800/admin/system/sysRole/findAll @ApiOperation(“查询所有角色”) ///knife4j生成接口文档的中文说明 12 @GetMapping("findAll") public Result findAll(){ ////调用serivice方法 List<SysRole> list = sysRoleService.list(); //模拟异常 15 //int i = 10/0; //模拟异常 手动抛出异常 验证我们的自定义异常 16 try { int i = 10/0; }catch (Exception e){ ///抛出自定义异常 throw new GuiguException(20001)执行自定义异常处理.."); } return Result.ok(list); }
service-util模块
全局异常添加方法
GlobalExceptionHandler
//自定义异常处理 16 @ExceptionHandler(GuiguException.class) @ResponseBody public Result error(GuiguException e) { e.printStackTrace(); return Result.fail().code(e.getCode()).message(e.getMsg()); }
自定义异常测试成功