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

news2025/7/19 7:42:26

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


案例综合练习 - 博客系统


本节目标

  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=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  mybatis-plus:
    configuration:
      map-underscore-to-camel-case: true
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  logging:
    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 {
    @ExceptionHandler
    public 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.coloradmin.cn/o/2345453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于OpenMV+STM32+OLED与YOLOv11+PaddleOCR的嵌入式车牌识别系统开发笔记

基于OpenMV、STM32与OLED的嵌入式车牌识别系统开发笔记 基于OpenMV、STM32与OLED的嵌入式车牌识别系统开发笔记系统架构全景 一、实物演示二、OpenMV端设计要点1. 硬件配置优化2. 智能帧率控制算法3. 数据传输协议设计 三、PyTorch后端核心实现&#xff1a;YOLOv11与PaddleOCR的…

w~嵌入式C语言~合集4

我自己的原文哦~ https://blog.51cto.com/whaosoft/13870376 一、STM32怎么选型 什么是 STM32 STM32&#xff0c;从字面上来理解&#xff0c;ST是意法半导体&#xff0c;M是Microelectronics的缩写&#xff0c;32表示32位&#xff0c;合起来理解&#xff0c;STM32就是指S…

K8S安全认证

一。用户认证的基本框架 在K8S集群中&#xff0c;客户端通常有两类&#xff1a; 1.User Account&#xff1a;一般独立于K8S之外的其他服务管理的用过户账号 2.Service Account&#xff1a;K8S管理的账号&#xff0c;用于为Pod中的服务进程在访问K8S提供身份标识 ApiServer是…

mybatis-plus里的com.baomidou.mybatisplus.core.override.MybatisMapperProxy 类的详细解析

以下是 com.baomidou.mybatisplus.core.override.MybatisMapperProxy 类的详细解析&#xff1a; 1. 类的作用 MybatisMapperProxy 是 MyBatis-Plus 框架中用于实现 Mapper 接口动态代理的核心类。它继承自 MyBatis 的 MapperProxy&#xff0c;并扩展了以下功能&#xff1a; …

在java程序中,类,进程,线程他们之间的关系以及main方法与他们之间的关系

在 Java 程序里&#xff0c;类、进程、线程各自有着不同的概念&#xff0c;同时也存在着紧密的联系&#xff0c;下面来详细分析它们之间的关系以及 main 方法和它们的关系。 类 类是 Java 中最基础的编程单元&#xff0c;是一种自定义的数据类型&#xff0c;它定义了对象的属…

[ACTF2020 新生赛]BackupFile题解

启动环境 进入后只有一段话&#xff0c;没有其他的说法。 解题方法 但是题目命名为backup file&#xff0c;应该是备份文件的意思&#xff0c;那么就用dirsearch工具来扫一下看看。 查看扫描结果 index.php.bak 下载下这个文件&#xff0c;查看文件内容。 进行php代码审计…

如何修改npm的全局安装路径?

修改 npm 的全局安装路径可以通过以下步骤完成&#xff0c;确保全局包&#xff08;使用 -g 安装的模块&#xff09;和缓存文件存储到自定义路径。以下是详细步骤&#xff1a; 1. 创建自定义路径的目录 在目标路径下创建两个文件夹&#xff0c;分别用于存储全局模块和缓存文件…

巧用 Element - UI 实现图片上传按钮的智能隐藏

引言 在前端开发中&#xff0c;使用 Element - UI 组件库来构建用户界面是非常常见的操作。其中图片上传功能更是在许多项目中频繁出现&#xff0c;比如用户头像上传、商品图片上传等场景。有时候&#xff0c;我们会有这样的需求&#xff1a;当上传图片达到一定数量后&#xf…

从“拼凑”到“构建”:大语言模型系统设计指南!

你有没有试过在没有说明书的情况下组装宜家家具?那种手忙脚乱却又充满期待的感觉,和设计大语言模型(LLM)系统时如出一辙。如果没有一个清晰的计划,很容易陷入混乱。我曾经也一头扎进去,满心期待却又手足无措,被网上那些复杂的架构图搞得晕头转向。于是,我坐下来,把它们…

【数据结构与算法】从完全二叉树到堆再到优先队列

完全二叉树 CBT 设二叉树的深度为 h , 若非最底层的其他各层的节点数都达到最大个数 , 最底层 h 的所有节点都连续集中在左侧的二叉树叫做 完全二叉树 . 特点 对任意节点 , 其右分支下的叶子节点的最底层为 L , 则其左分支下的叶子节点的最低层一定是 L 或 L 1 .完全二叉树…

【Linux网络】构建类似XShell功能的TCP服务器

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

Spring Boot 配置源详解(完整版)

Spring Boot 配置源详解&#xff08;完整版&#xff09; 一、配置源加载顺序与优先级 配置源类型优先级顺序&#xff08;从高到低&#xff09;对应配置类/接口是否可覆盖典型文件/来源命令行参数&#xff08;--keyvalue&#xff09;1&#xff08;最高&#xff09;SimpleComman…

puppeteer注入浏览器指纹过CDP

一、背景 通过puppeteer爬取目标网站时&#xff0c;经常会被对方网站检测到&#xff0c;比如原生puppeteerCDP特征非常明显&#xff0c;另外指纹如果一直不变&#xff0c;也会引发风控 二、实现 通过以下几行代码即可轻松过大部分检测点&#xff0c;并且能够切换指纹&#x…

软件项目实施全流程及交付物清单

需求分析 -> 概要设计 -> 详细设计 -> 开发实现 -> 测试 -> 部署 -> 运维 一、确认项目目标、范围和团队成员 二、收集和分析客户需求&#xff0c;确定需求规格 三、制定详细的项目计划&#xff0c;包括时间表、资源计划、预算 四、系统架构设计&#xf…

【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的

HTTP与HTTPS全面对比及HTTPS加密流程详解 一、HTTP与HTTPS核心区别 特性HTTPHTTPS协议基础明文传输HTTP SSL/TLS加密层默认端口80443加密方式无加密混合加密&#xff08;非对称对称&#xff09;证书要求不需要需要CA颁发的数字证书安全性易被窃听、篡改、冒充防窃听、防篡改…

从梯度消失到百层网络:ResNet 是如何改变深度学习成为经典的?

自AlexNet赢得2012年ImageNet竞赛以来&#xff0c;每个新的获胜架构通常都会增加更多层数以降低错误率。一段时间内&#xff0c;增加层数确实有效&#xff0c;但随着网络深度的增加&#xff0c;深度学习中一个常见的问题——梯度消失或梯度爆炸开始出现。 梯度消失问题会导致梯…

Uni-App 多端电子合同开源项目介绍

项目概述 本项目是一款基于 uni-app框架开发的多端电子合同管理平台&#xff0c;旨在为企业及个人用户提供高效、安全、便捷的电子合同签署与管理服务。项目创新性地引入了 “证据链”与“非证据链”两种签署模式&#xff0c;满足不同场景下的签署需求&#xff0c;支持多种签署…

多语言笔记系列:共享数据

在笔记中共享数据(变量) 使用 .NET 交互式内核&#xff0c;可以在单个笔记本中以多种语言编写代码。为了利用每种语言的不同优势&#xff0c;您会发现在它们之间共享数据很有用。即一种语言的变量&#xff0c;可以在其它语言中使用。 默认情况下&#xff0c;.NET Interactive …

如何使用SeedProd创建无缝的WordPress维护页面

不管您刚接触 WordPress &#xff0c;还是经验丰富的站长&#xff0c;SeedProd 都是创建网站维护页面的得力助手。通过SeedProd&#xff0c;您可以轻松创建一个与网站风格一致、功能齐全的维护页面&#xff0c;让您的用户在网站维护期间也能感受到您的专业与关怀。本文将为您提…