1、创建后端项目
pom文件所需要的依赖
<dependencies><!-- SpringBoot-Web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MySQL依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- MybatisPlus和SpringBoot整合--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><!-- 适用版本:mybatis-plus-generator代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version></dependency><!-- Freemarker模板引擎依赖--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version></dependency><!-- Swagger相关依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- 加入log4j2的日志框架 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 测试依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
2、上传项目到码云

项目地址:https://gitee.com/yangcunle/YangCunle-Blog
3、整合MyBatisPlus
3.1配置乐观锁和分页插件
@Configurationpublic class MyBatisPlusConfig {/*** 注册乐观锁插件和分页插件* 不同版本的配置插件不一样(本次是用的是最新的版本3.5.1)* 详情见MyBatisPlus官方文档:https://baomidou.com* @return*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//添加乐观锁mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//添加分页mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}}
3.2插入修改的填充策略
@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {/*** 插入时的填充策略* @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {//setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}/*** 修改时的填充策略* @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updateTime", new Date(), metaObject);}}
3.3MyBatisPlus代码生成器
public class MyBatisPlusGenerator {public static void main(String[] args) {//数据库相关配置String url = "jdbc:mysql://119.23.106.219:3306/ycl_blog?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC";String username = "root";String password = "ycl1207";String projectPath = System.getProperty("user.dir");//表名集合List<String> tables = new ArrayList<>();tables.add("t_user");FastAutoGenerator.create(url, username, password)//全局配置.globalConfig(builder -> {builder.author("YangCunle") // 设置作者.enableSwagger() // 开启 swagger 模式.fileOverride() // 覆盖已生成文件.dateType(DateType.ONLY_DATE).outputDir(projectPath + "/src/main/java"); // 指定输出目录})//包配置.packageConfig(builder -> {builder.parent("com.yangcunle.blog") // 设置父包名//设置包的命名.entity("entity").service("service").serviceImpl("service.impl").controller("controller").mapper("mapper").xml("mapper").pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mapper/")); // 设置mapperXml生成路径})//策略配置.strategyConfig(builder -> {builder.addInclude(tables) // 设置需要生成的表名.addTablePrefix("t_")// 设置过滤表前缀// 控制器配置:controllerBuilder.controllerBuilder().enableHyphenStyle()//开启驼峰命名转字符.enableRestStyle()//设置@RestController注解// 逻辑层配置:serviceBuilder.serviceBuilder().formatServiceFileName("%sService")//格式化 service 接口文件名称.formatServiceImplFileName("%sServiceImpl")//格式化 serviceImpl 接口文件名称// 实体类配置:entityBuilder.entityBuilder().enableLombok()//设置Lombok.enableTableFieldAnnotation()//开启生成实体时生成字段注解.idType(IdType.AUTO)//设置主键类型:自增.versionColumnName("version")//乐观锁.logicDeleteColumnName("deleted")//逻辑删除.addTableFills(new Column("create_time", FieldFill.INSERT), new Column("update_time", FieldFill.INSERT_UPDATE))//添加、修改时间自动填充// Mapper配置:mapperBuilder.mapperBuilder().enableBaseResultMap()//mapper自动生成通用查询映射结果.enableBaseColumnList();//mapper自动生成通用列}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}}
3.4一键生成代码

4、统一异常处理
统一异常处理包括:全局异常处理、特殊异常处理、自定义异常处理
4.1全局异常处理
@RestControllerAdvicepublic class GlobalExceptionHandler {//获取日志记录器对象private final Logger logger = Logger.getLogger(GlobalExceptionHandler.class);/*** 处理运行时异常* @param e* @return*/@ResponseBody@ExceptionHandler(value = RuntimeException.class)public CommonResult handler(RuntimeException e) {logger.error("运行时异常:{}" + e.getMessage());return CommonResult.failed("博客系统貌似出现了问题o(╥﹏╥)o,请联系管理员处理。微信:YCL357486967");}}
4.2特殊异常处理
我们知道的一些异常可以列举出来,进行捕获,这里以除数不能为0举例
如果不处理,就会报以下错误:
/*** 特殊异常处理 :ArithmeticException* @param e* @return*/@ResponseBody@ExceptionHandler(value = ArithmeticException.class)public CommonResult handler(ArithmeticException e) {logger.error("除数不能为0异常:{}" + e.getMessage());return CommonResult.failed(e.getMessage());}
成功捕获:
4.3自定义异常处理
自己创建一个自定义异常类:BlogException 继承运行时异常 RuntimeException
@Datapublic class BlogException extends RuntimeException {private Integer code;private String message;public BlogException(Integer code, String message) {super(message);this.code = code;this.message = message;}public BlogException(ResultCode ResultCode) {super(ResultCode.getMessage());this.code = ResultCode.getCode();this.message = ResultCode.getMessage();}}
在全局异常处理中加入捕获自定义异常
/*** 自定义异常处理* @param e* @return*/@ResponseBody@ExceptionHandler(value = BlogException.class)public CommonResult handler(BlogException e) {logger.error("自定义异常:{}" + e.getMessage());return CommonResult.failed(e.getMessage());}
5、封装统一返回结果工具类
public class ResultUtil<T> {// 状态码private Integer code;// 消息private String msg;// 数据private T data;public ResultUtil(T data) {this.data = data;}/*** 成功(无返回数据)* @return*/public static ResultUtil success() {ResultUtil result = new ResultUtil<>();result.setCode(ResponseCode.SUCCEED);result.setMsg(ResponseMsg.SUCCEED);return result;}/*** 成功(有返回数据)* @param data* @param <T>* @return*/public static <T> ResultUtil<T> success(T data) {ResultUtil<T> result = new ResultUtil<>(data);result.setCode(ResponseCode.SUCCEED);result.setMsg(ResponseMsg.SUCCEED);return result;}/*** 错误* @param code* @param msg* @return*/public static ResultUtil error(Integer code, String msg) {ResultUtil result = new ResultUtil();result.setCode(code);result.setMsg(msg);return result;}}
6、用户模块的接口开发
public class UserController {//获取日志记录器对象private final Logger logger = Logger.getLogger(UserController.class);@Autowiredprivate UserService userService;/*** 分页查询用户列表* @param username* @param pageNum* @param pageSize* @return*/@GetMapping("/list")public ResultUtil<Page<User>> list(String username,@RequestParam(required = false, defaultValue = "1") Integer pageNum,@RequestParam(required = false, defaultValue = "10") Integer pageSize) {logger.info("查询用户列表开始:入参{username}:" + username);LambdaQueryWrapper<User> query = Wrappers.<User>lambdaQuery().orderByDesc(User::getId);if (!StringUtils.isEmpty(username)) {query.like(User::getUsername, username);}Page<User> userPage = userService.page(new Page<>(pageNum, pageSize), query);return ResultUtil.success(userPage);}/*** 保存用户* @param user* @return*/@PostMapping("/save")public ResultUtil<Boolean> save(@RequestBody User user) {logger.info("添加用户:入参{user}:" + user.toString());boolean result = userService.save(user);return ResultUtil.success(result);}/*** 修改用户信息* @param user* @return*/@PostMapping("/update")public ResultUtil<Boolean> update(@RequestBody User user) {logger.info("修改用户:入参{user}:" + user.toString());boolean result = userService.updateById(user);return ResultUtil.success(result);}/*** 查看用户信息* @param id* @return*/@GetMapping("/read")public ResultUtil<User> read(Integer id) {logger.info("查看用户信息:入参{id}:" + id);User user = userService.getById(id);return ResultUtil.success(user);}/*** 删除用户* @param id* @return*/@GetMapping("/delete")public ResultUtil<Boolean> delete(Integer id) {logger.info("删除用户信息:入参{id}:" + id);boolean result = userService.removeById(id);return ResultUtil.success(result);}}
7、ApiPost测试接口

https://console-docs.apipost.cn/preview/e66f1e46125af959/222ee42959f879ef
文档支持在线查看
用户列表支持分页查询
http://localhost:8081/user/list
返回结果
{"code": 0,"msg": "成功","data": {"records": [{"id": 3,"username": "ycl","password": "123","role": 2,"email": "123@qq.com","phone": "123","age": null,"headImg": null,"createTime": "2021-08-02T08:11:47.000+00:00","updateTime": "2021-08-02T08:11:47.000+00:00","deleted": 0},{"id": 2,"username": "乐多多","password": "123456","role": 2,"email": "123456@qq.com","phone": "123456","age": null,"headImg": null,"createTime": "2021-08-02T08:06:14.000+00:00","updateTime": "2021-08-02T08:06:14.000+00:00","deleted": 0},{"id": 1,"username": "admin","password": "admin","role": 1,"email": "357487967@qq.com","phone": "15971397103","age": 25,"headImg": null,"createTime": "2021-08-02T10:33:11.000+00:00","updateTime": "2021-08-02T10:33:15.000+00:00","deleted": 0}],"total": 3,"size": 10,"current": 1,"orders": [],"optimizeCountSql": true,"searchCount": true,"countId": null,"maxLimit": null,"pages": 1}}


