当前位置: 首页 > news >正文

【博客系统】博客系统第一弹:博客系统项目配置、MyBatis-Plus 实现 Mapper 接口、处理项目公共模块:统一返回结果、统一异常处理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


案例综合练习 - 博客系统


本节目标

  1. 从 0 到 1 完成博客系统后端项目的开发。

前言

通过前面课程的学习,我们掌握了 Spring 框架和 MyBatis 的基本使用,并完成了图书管理系统的常规功能开发。接下来我们系统地从 0 到 1 完成一个项目的开发。


项目介绍


使用 SSM 框架实现一个简单的博客系统,共 5 个页面:

  1. 用户登录
  2. 博客发表页
  3. 博客编辑页
  4. 博客列表页
  5. 博客详情页

功能描述:用户登录成功后,可以查看所有人的博客。点击“查看全文”可以查看该博客的正文内容。如果该博客作者为当前登录用户,可以完成博客的修改和删除操作,以及发表新博客。(前端页面随课堂资料一起提供)


页面预览


  • 用户登录

image-20250422194547841

  • 博客列表页

image-20250422194600375

  • 博客详情页

image-20250422194611378

  • 博客发表/修改页

image-20250422194622260


数据准备


建表 SQL:

-- 建表 SQL
create database if not exists java_blog_spring charset utf8mb4;use java_blog_spring;-- 用户表
DROP TABLE IF EXISTS java_blog_spring.user_info;
CREATE TABLE java_blog_spring.user_info(
`id` INT NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR (128) NOT NULL,
`password` VARCHAR (128) NOT NULL,
`github_url` VARCHAR (128) NULL,
`delete_flag` TINYINT (4) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY (id),
UNIQUE INDEX user_name_UNIQUE (user_name ASC)) ENGINE = INNODB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '用户表';-- 博客表
drop table if exists java_blog_spring.blog_info;
CREATE TABLE java_blog_spring.blog_info (
`id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NULL,
`content` TEXT NULL,
`user_id` INT(11) NULL,
`delete_flag` TINYINT(4) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY (id))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';-- 新增用户信息
insert into java_blog_spring.user_info (user_name, password, github_url) values("zhangsan", "123456", "https://gitee.com/bubblefish666/class-java45");
insert into java_blog_spring.user_info (user_name, password, github_url) values("lisi", "123456", "https://gitee.com/bubblefish666/class-java45");insert into java_blog_spring.blog_info (title, content, user_id) values("第一篇博客", "111我是博客正文我是博客正文我是博客正文", 1);
insert into java_blog_spring.blog_info (title, content, user_id) values("第二篇博客", "222我是博客正文我是博客正文我是博客正文", 2);

创建项目


创建 SpringBoot 项目,添加 Spring MVC 和 MyBatis 对应依赖。

image-20250426193259883


添加MyBatis-Plus 依赖


<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version>
</dependency>

删除引入 lombok 依赖添加的多余插件:

image-20250426194025041


创建对应目录


image-20250422194655535


准备前端页面


把课程中提供的博客系统静态页面拷贝到 static 目录下。

image-20250422194707200


配置配置文件


spring:datasource:url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpllogging:file:name: spring-blog.log

测试


访问前端页面:http://127.0.0.1:8080/blog_login.html。前端页面可以正确显示,说明项目初始化成功。

image-20250422194725101


项目公共模块


项目分为控制层(Controller)、服务层(Service)、持久层(Mapper)。各层之间的调用关系如下:

我们先根据需求完成公共层代码的编写。

image-20250422194737930


统一返回结果实体类


  • code:业务状态码
    • 200:业务处理成功
    • -1:业务处理失败
    • 后续有其他异常信息,可以再补充。
  • errMsg:业务处理失败时,返回的错误信息。
  • data:业务返回数据。

定义业务状态枚举:

image-20250426221200882

基于会话管理 Session 、统一响应封装、枚举状态码、工厂方法模式实现状态码方法:全栈开发获取图书列表接口的强制登录功能(含会话管理、统一响应封装思维导图、核心部分代码)

后面需要把 Object data 修改为泛型:

@Data
public class Result<T> {private int code;private String errMsg;private T data;public static <T> Result success(T data) {Result result = new Result();result.setCode(ResultCodeEnum.SUCCESS.getCode());result.setData(data);return result;}public static <T> Result fail(String errMsg) {Result result = new Result();result.setCode(ResultCodeEnum.FAIL.getCode());result.setErrMsg(errMsg);return result;}
}

统一返回结果


统一返回结果封装:封装 String 类型造成参数类型不匹配异常、通过 Debug 锁定调用链出现异常的具体位置、解决异常的方法_springboot 报错返回类封装

image-20250426222020300


定义项目异常


image-20250426222759177

import com.bite.blog.common.pojo.response.Result;public class BlogException extends RuntimeException {private Result errorResult = new Result<>();public BlogException(String message) {this.errorResult.setCode(-1);this.errorResult.setErrMsg(message);}
}

统一异常处理


@ControllerAdvice(含底层源码分析) 、@ExceptionHandler、@ResponseBody 配合实现统一异常处理功能

image-20250426224614197

@RestController 变成 @Controller ,方法的返回值会被当成 URL,使用 @ResponseBody 会告诉 Spring 返回结果是数据而非页面


import com.bite.blog.common.pojo.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {@ExceptionHandlerpublic Result handler(Exception e) {log.error("发生异常, e: {}", e);return Result.fail(e.getMessage());}
}

业务代码


实体类


image-20250426201722384

在数据库中,我们创建了两张表,接下来需要创建两个类,来与之对应;

对应机制:yml 驼峰自动转换/MP 依赖 ???

image-20250426201906327


UserInfo


image-20250426200538880

@Data
public class UserInfo {@TableId(type = IdType.AUTO)private Integer id;private String userName;private String password;private String githubUrl;private Integer deleteFlag;private LocalDate createTime;private LocalDate updateTime;
}

因为数据库的表名,列名都能和 MyBatis-Plus 中设置的实体类,属性对上,就不需要使用 @TableName@TableField 来指定表和类、字段和属性;

但是需要使用 @TableId(type = IdType.AUTO) 设置主键,并且设置该主键类型为自增主键;

@TableName、@TableField、@TableId 的使用方法在这篇博客中有提及


BlogInfo


image-20250426201648875

@Data
public class BlogInfo {@TableId(value = "id", type = IdType.AUTO)private Integer id;private String title;private String content;private Integer userId;private Integer deleteFlag;private LocalDateTime createTime;private LocalDateTime updateTime;
}

持久层


使用 MyBatisPlus 来完成持久层代码的开发,创建 mapper 实现 BaseMapper 即可。


Mapper


MP:依赖引入、继承 BaseMapper 接口实现单表增删改查、MP日志配置、表设计中设置主键自增值、MP 相关的 @Table系列常见注解说明_

image-20250427103322923


image-20250427111839344

@Mapper 用于标识该接口是 MyBatis 中的 Mapper接口


在这里插入图片描述

在这里插入图片描述

http://www.xdnf.cn/news/184915.html

相关文章:

  • 关于华为高斯数据库出现Invalid or unsupported by client SCRAM mechanisms定位解决的过程
  • -信息革命-
  • OpenManus云端部署及经典案例应用
  • 心磁图技术突破传统局限!心血管疾病早筛迈入“三零“新时代
  • TV launcher官方下载-tv launcher汉化版-tv桌面启动器极简下载
  • c++17 对于临时对象作为右值的优化
  • MRI学习笔记-conjunction analysis
  • Linux——线程(2)线程互斥(锁)
  • 机器学习 | 基于回归模型的交通需求预测案例分析及代码示例
  • 日本IT|UIUX主要的工作都是哪些?及职业前景
  • 【每日随笔】文化属性 ② ( 高维度信息处理 | 强者思维形成 | 认知重构 | 资源捕获 | 进化路径 )
  • LangChain构建大模型应用之RAG
  • 使用ROS实现多机通讯
  • 线上查询车辆出险记录:快速掌握事故情况!
  • 大模型API密钥的环境变量配置(大模型API KEY管理)(将密钥存储在环境变量)(python-dotenv)(密钥管理)
  • 数据结构(七)---链式栈
  • AI看论文自动生成代码库:Paper2Code如何革新科研复现?
  • 函数式链表:Python编程的非常规 “链” 接
  • QT6 源(53)篇三:存储 c 语言字符串的类 QByteArray 的使用举例,
  • 移除生产环境所有console.log
  • 给视频自动打字幕:从Humanoid-X、UH-1到首个人形VLA Humanoid-VLA:迈向整合第一人称视角的通用人形控制
  • 基于STM32、HAL库的AD7616BSTZ模数转换器ADC驱动程序设计
  • Linux操作系统学习---进程地址空间
  • 【LaTex】8.1 文档类与层级
  • 前端权限管理
  • 小刚说C语言刷题——1320时钟旋转
  • 生成式人工智能认证(GAI认证)要学哪些知识?
  • google chrome 中 fcitx5 候选框不跟随光标
  • 【SpringCloudAlibaba】Dubbo 和 Spring Cloud OpenFeign 在服务治理能力上的差异
  • 生成式人工智能认证(GAI认证)考试难吗?