【SpringBoot】基于MybatisPlus的博客管理系统(1)

1.准备工作

1.1数据库

-- 建表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/bubble-fish666/class-java45");
insert into java_blog_spring.user_info (user_name, password,github_url)values("lisi","123456","https://gitee.com/bubble-fish666/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);

1.2pom文件配置(MybatisPlus依赖)

MybatisPlus依赖:

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

1.3yml文件配置(数据库配置)

记得更改password

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

1.4项目架构初始化

前期的架构:

 

开发中, 以下命名统称为实体类:

POJO
Model
Entity


在实际开发中, 实体类的划分要细的多:

VO(value object):   表现层对象
DO(Data Object)/PO(Persistant Object): 持久层/数据层对象
DTO(Data Transfer Object): 数据传输对象
BO(Business Object): 业务对象
细分实体类, 可以实现业务代码的解耦.

详情见:实体类

2.业务实现

2.1获取博客列表

1.第一步:实现实体类  对接数据库数据

//do层数据库资源对象
@Data
@AllArgsConstructor
public class BlogInfo {@TableId(type = IdType.AUTO)private Integer id;private String title;private String content;private Integer userId;private Integer deleteFlag;private LocalDateTime createTime;private LocalDateTime updateTime;
}
@Data
public class UserInfo {@TableId(type = IdType.AUTO)private Integer id;private String userName;private String password;private String githubUrl;private Integer deleteFlag;private LocalDateTime createTime;private LocalDateTime updateTime;
}

2.实现返回对象类  对接前端

@Data
public class BlogInfoResponse {@TableId(type = IdType.AUTO)private Integer id;private String title;private String content;//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//重写构造方法public String getCreateTime() {return DateUtils.format(createTime);}//通过重写0content构造方法完成业务想要的返回结果  如:对字符串进行拼接等等}

BlogInfoResponse 是返回前端展示博客列表所需的数据

注意:

我们需要掌握更改日期格式的方法:

常见的日期类型有:Date  LocalDateTime

在这里我们用的是LocalDateTime

那我们就先讲它的转化方法

		LocalDateTime localDateTime = LocalDateTime.now();DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");String format1 = dateTimeFormatter.format(localDateTime);System.out.println(format1);

使用 DateTimeFormatter 类进行格式定义

类型格式的定义是什么呢?

查询java.text.SimpleDateFormat 官⽅⽂档可知

  • LetterDate or Time ComponentPresentationExamples
    GEra designatorTextAD
    yYearYear1996; 96
    YWeek yearYear2009; 09
    MMonth in year (context sensitive)MonthJuly; Jul; 07
    LMonth in year (standalone form)MonthJuly; Jul; 07
    wWeek in yearNumber27
    WWeek in monthNumber2
    DDay in yearNumber189
    dDay in monthNumber10
    FDay of week in monthNumber2
    EDay name in weekTextTuesday; Tue
    uDay number of week (1 = Monday, ..., 7 = Sunday)Number1
    aAm/pm markerTextPM
    HHour in day (0-23)Number0
    kHour in day (1-24)Number24
    KHour in am/pm (0-11)Number0
    hHour in am/pm (1-12)Number12
    mMinute in hourNumber30
    sSecond in minuteNumber55
    SMillisecondNumber978
    zTime zoneGeneral time zonePacific Standard Time; PST; GMT-08:00
    ZTime zoneRFC 822 time zone-0800
    XTime zoneISO 8601 time zone-08; -0800; -08:00

Date的转化方法:

		Date date = new Date();//SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");String format = simpleDateFormat.format(date);System.out.println(format);

 所以我们通过重写构造方法完成日期格式修改

最后我们通过AOP思想完成日期统一修改:

public class DateUtils {public static String format(LocalDateTime localDateTime) {DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(Constant.PATTERN);return dateTimeFormatter.format(localDateTime);}public static String format(LocalDateTime localDateTime, String pattern) {DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);return dateTimeFormatter.format(localDateTime);}
}
/*** 统一返回结果* @param <T>*/
@Data
public class Result<T> {private int code;private String errMsg;private T data;public static <T> Result success(T data) {Result<T> re = new Result<>();re.setCode(ResultCodeEnum.SUCCESS.getCode());re.setData(data);return re;}public static <T> Result fail(String errMsg) {Result<T> re = new Result<>();re.setCode(ResultCodeEnum.FAIL.getCode());re.setErrMsg(errMsg);return re;}public static <T> Result fail(String errMsg, T data) {Result<T> re = new Result<>();re.setCode(ResultCodeEnum.FAIL.getCode());re.setErrMsg(errMsg);re.setData(data);return re;}
}

Result:统一返回结果 

注意:在静态方法中使用T泛型时要在static后加<T>

在这一步我们在使用code时可以选择:

1.在Constant中定义静态常亮

2.定义枚举

我选择使用枚举:

@AllArgsConstructor
public enum ResultCodeEnum {SUCCESS(200),FAIL(-1);@Getterprivate int code;}

 3.Controller  Service  Mapper  三件套

Controller:在注入BlogService 时推荐使用@Resource  因为可能使用实现了多个对象的接口

同时注入的类型为接口类型,方便修改注入(只用修改@Resource name属性)

@Slf4j
@RestController
@RequestMapping("/blog")
public class BlogInfoController {@Resource(name = "blogService")private BlogService blogService;@RequestMapping("/getList")public List<BlogInfoResponse> getList() {log.info("获取博客列表...");return blogService.getList();}
}

 

Service :先定义接口,然后在impl包中实现具体类并处理逻辑

 

@Service
public interface BlogService {List<BlogInfoResponse> getList();
}
@Service("blogService")
public class BlogServiceImpl implements BlogService {@Resourceprivate BlogInfoMapper blogInfoMapper;@Overridepublic List<BlogInfoResponse> getList() {//1.SQL拼接QueryWrapper<BlogInfo> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(BlogInfo::getDeleteFlag, Constant.IS_DELETE);List<BlogInfo> blogInfos = blogInfoMapper.selectList(queryWrapper);//2.将获取的数据转化为BlogInfoResponse用于返回List<BlogInfoResponse> list = blogInfos.stream().map(blogInfo -> {BlogInfoResponse blogInfoResponse = new BlogInfoResponse();//根据属性名称进行复制  原数据  转化数据BeanUtils.copyProperties(blogInfo, blogInfoResponse);return blogInfoResponse;}).collect(Collectors.toList());//转化listreturn list;}}

注意点:

1.在 @Service中进行名称绑定

2.参数转换:

使用blogInfos.stream().map()与lambda表达式实现遍历  (或者使用for循环)

代码中的链式调用解释如下:

blogInfos.stream(): 将 List 转换为一个 stream

blogInfos.stream().map(x -> {转换规则, return y}): 对 List 中的每一个元素根据指定规则进行转换(x: 原来的元素; y: 转换后的元素)

.collect(Collectors.toList()): 将转换后的 Stream 转换为一个新的 List

3.根据属性名称进行复制    原数据      转化数据

BeanUtils.copyProperties(blogInfo, blogInfoResponse);

Mapper:因为使用了MybatisPlus,不用写SQL语句(舒服)

只用实现BaseMapper<T>接口  T为对接数据库的类,会根据该类生成SQL语句

@Mapper
public interface BlogInfoMapper extends BaseMapper<BlogInfo> {
}

使用postman校验一下:

2.2获取博客详情 

前置工作已经做完了,直接写Controller  Service代码就行

Controller :

    @RequestMapping("/getBlogDetail")public BlogDetailResponse getBlogDetail(@NotNull(message = "blogId 不能为空") Integer blogId) {
//        if(blogId == null) {
//            throw new BlogException("用户id不能为空");
//        }log.info("获取博客详情,id:{}",blogId);return blogService.getBlogDetail(blogId);}

@NotNull(message = "blogId 不能为空"):

jakarta.validation完成的参数校验(javax.validation 是Java Bean Validation API的包名)

 如果参数为空了还要爆出异常,这时候启用我们定义的异常与统一异常处理

@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {@ExceptionHandlerpublic Result exceptionAdvice(Exception e) {log.error("出现异常e:", e);return Result.fail(e.getMessage());}@ExceptionHandlerpublic Result exceptionAdvice(BlogException e) {log.error("出现异常e:", e);return Result.fail(e.getErrMsg());}@ExceptionHandlerpublic Result exceptionAdvice(HandlerMethodValidationException e) {log.error("出现异常e:", e);//获取异常信息
//        List<String> errors = new ArrayList<>();
//        e.getAllErrors().forEach(error -> errors.add(e.getMessage()));return Result.fail("参数校验失败");}
}

在统一异常处理(@ResponseBody@ControllerAdvice@ExceptionHandler)中可以处理自定义异常与常规异常  同时打印日志 

Service:

    @Overridepublic BlogDetailResponse getBlogDetail(Integer blogId) {QueryWrapper<BlogInfo> queryWrapper = new QueryWrapper<>();//根据id与DeleteFlag查询queryWrapper.lambda().eq(BlogInfo::getId, blogId).eq(BlogInfo::getDeleteFlag, Constant.IS_DELETE);BlogInfo blogInfo = blogInfoMapper.selectOne(queryWrapper);BlogDetailResponse blogDetailResponse = new BlogDetailResponse();BeanUtils.copyProperties(blogInfo, blogDetailResponse);return blogDetailResponse;}

老套路查询后转化类型

postman检验一下:

没传参,返回我们定义的返回信息

正常传参:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77700.shtml

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

相关文章

贵族运动项目有哪些·棒球1号位

10个具有代表性的贵族运动&#xff1a; 高尔夫 马术 网球 帆船 击剑 斯诺克 冰球 私人飞机驾驶 深海潜水 马球 贵族运动通常指具有较高参与成本、历史底蕴或社交属性的运动&#xff0c;而棒球作为一项大众化团队运动&#xff0c;与典型贵族运动的结合较为罕见。从以下几个角度探…

【Tauri2】035——sql和sqlx

前言 这篇就来看看插件sql SQL | Taurihttps://tauri.app/plugin/sql/ 正文 准备 添加依赖 tauri-plugin-sql {version "2.2.0",features ["sqlite"]} features可以是mysql、sqlite、postsql 进去features看看 sqlite ["sqlx/sqlite&quo…

全链路自动化AIGC内容工厂:构建企业级智能内容生产系统

一、工业化AIGC系统架构 1.1 生产流程设计 [需求输入] → [创意生成] → [多模态生产] → [质量审核] → [多平台分发] ↑ ↓ ↑ [用户反馈] ← [效果分析] ← [数据埋点] ← [内容投放] 1.2 技术指标要求 指标 标准值 实现方案 单日产能 1,000,000 分布式推理集群 内容合规率…

是否想要一个桌面哆啦A梦的宠物

是否想拥有一个在指定时间喊你的桌面宠物呢&#xff08;手动狗头&#xff09; 如果你有更好的想法&#xff0c;欢迎提出你的想法。 是否考虑过跟开发者一对一&#xff0c;提出你的建议&#xff08;狗头&#xff09;。 https://wwxc.lanzouo.com/idKnJ2uvq11c 密码:bbkm

Unity AI-使用Ollama本地大语言模型运行框架运行本地Deepseek等模型实现聊天对话(二)

一、使用介绍 官方网页&#xff1a;Ollama官方网址 中文文档参考&#xff1a;Ollama中文文档 相关教程&#xff1a;Ollama教程 使用版本&#xff1a;Unity 2022.3.53f1c1、Ollama 0.6.2 示例模型&#xff1a;llama3.2 二、运行示例 三、使用步骤 1、创建Canvas面板 具体…

从 BERT 到 GPT:Encoder 的 “全局视野” 如何喂饱 Decoder 的 “逐词纠结”

当 Encoder 学会 “左顾右盼”&#xff1a;Decoder 如何凭 “单向记忆” 生成丝滑文本&#xff1f; 目录 当 Encoder 学会 “左顾右盼”&#xff1a;Decoder 如何凭 “单向记忆” 生成丝滑文本&#xff1f;引言一、Encoder vs Decoder&#xff1a;核心功能与基础架构对比1.1 本…

数据结构入门:详解顺序表的实现与操作

目录 1.线性表 2.顺序表 2.1概念与结构 2.2分类 2.2.1静态顺序表 2.2.2动态顺序表 3.动态顺序表的实现 3.1.SeqList.h 3.2.SeqList.c 3.2.1初始化 3.2.2销毁 3.2.3打印 3.2.4顺序表扩容 3.2.5尾部插入及尾部删除 3.2.6头部插入及头部删除 3.2.7特定位置插入…

LeetCode热题100--53.最大子数组和--中等

1. 题目 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&…

python:练习:2

1.题目&#xff1a;统计一篇英文文章中每个单词出现的次数&#xff0c;并按照出现次数排序输出。 示例输入&#xff1a; text "Python is an interpreted, high-level, general-purpose programming language. Created by Guido van Rossum and first released in 1991…

AI Agent 孵化器?开源框架CAMEL

简介 CAMEL&#xff08;Communicative Agents for Mind Exploration of Large Scale Language Model Society&#xff09;是一个开源框架&#xff0c;大语言模型多智能体框架的先驱者。旨在通过角色扮演和自主协作&#xff0c;探索大语言模型&#xff08;LLM&#xff09;在多智…

关于插值和拟合(数学建模实验课)

文章目录 1.总体评价2.具体的课堂题目 1.总体评价 学校可以开设这个数学建模实验课程&#xff0c;我本来是非常的激动地&#xff0c;但是这个最后的上课方式却让我高兴不起哦来&#xff0c;因为老师讲的这个内容非常的简单&#xff0c;而且一个上午的数学实验&#xff0c;基本…

LayerSkip: Enabling Early Exit Inference and Self-Speculative Decoding

TL;DR 2024 年 Meta FAIR 提出了 LayerSkip&#xff0c;这是一种端到端的解决方案&#xff0c;用于加速大语言模型&#xff08;LLMs&#xff09;的推理过程 Paper name LayerSkip: Enabling Early Exit Inference and Self-Speculative Decoding Paper Reading Note Paper…

解决ktransformers v0.3 docker镜像中 operator torchvision::nms does not exist 问题

问题背景 更新ktransformers docker镜像到v0.3版本后&#xff08;之前为v0.2.4post1&#xff09;&#xff0c;使用更新前启动命令无法正确启动服务&#xff0c;提示以下错误&#xff1a; Traceback (most recent call last):File "/workspace/ktransformers/ktransforme…

如何系统学习音视频

学习音视频技术涉及多个领域&#xff0c;包括音频处理、视频处理、编码解码、流媒体传输等。 第一阶段&#xff1a;基础知识准备 目标&#xff1a;掌握音视频学习所需的计算机科学和数学基础。 计算机基础 学习计算机网络基础&#xff08;TCP/IP、UDP、HTTP、RTSP等协议&#…

TiDB 可观测性最佳实践

TiDB 介绍 TiDB&#xff0c;由 PingCAP 公司自主研发的开源分布式关系型数据库&#xff0c;是一款创新的 HTAP 数据库产品&#xff0c;它融合了在线事务处理&#xff08;OLTP&#xff09;和在线分析处理&#xff08;OLAP&#xff09;的能力&#xff0c;支持水平扩容和缩容&…

使用FreeRTOS解决单片机串口异步打印

单片机串口异步打印 文章目录 单片机串口异步打印前言设计思路准备队列创建完整代码 总结 前言 &#x1f30a;在单片机开发中串口的异步打印异步打印允许单片机在执行其他任务的同时进行打印操作&#xff0c;无需等待打印完成后再继续执行后续代码&#xff0c;避免了在多处调用…

代码颜色模式python

1. CMYK&#xff08;印刷场景&#xff09; 例子&#xff1a;某出版社设计书籍封面时&#xff0c;使用 Adobe Illustrator 绘制图案。 红色封面的 CMYK 值可能为&#xff1a;C0, M100, Y100, K0&#xff08;通过洋红和黄色油墨混合呈现红色&#xff09;。印刷前需将设计文件转…

HarmonyOS NEXT 诗词元服务项目开发上架全流程实战(二、元服务与应用APP签名打包步骤详解)

在HarmonyOS应用开发过程中&#xff0c;发布应用到应用市场是一个重要的环节。没经历过的童鞋&#xff0c;首次对HarmonyOS的应用签名打包上架可能感觉繁琐。需要各种秘钥证书生成和申请&#xff0c;混在一起分不清。其实搞清楚后也就那会事&#xff0c;各个文件都有它存在的作…

【BotSharp框架示例 ——实现聊天机器人,并通过 DeepSeek V3实现 function calling】

BotSharp框架示例 ——实现聊天机器人&#xff0c;并通过 DeepSeek V3实现 function calling 一、一点点感悟二、创建项目1、创建项目2、添加引用3、MyWeatherPlugin项目代码编写4、WeatherApiDefaultService项目代码编写5、WebAPI MyWeatherAPI 的项目代码编写6、data文件夹中…

百度CarLife实现手机车机无缝互联

百度CarLife是百度推出的智能车联网解决方案&#xff0c;通过手机与车机互联技术&#xff0c;为用户提供安全便捷的车载互联网服务体验。 CarLife 实现手机与车机屏幕的无缝互联&#xff0c;让应用内容同步至车载系统&#xff0c;减少驾驶过程中操作手机的频率&#xff0c;提升…