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

【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.xdnf.cn/news/2897.html

相关文章:

  • 常见的硬盘分类
  • SpringBoot、微服务与AI场景题深度解析
  • neo4j基础操作:命令行增删改查
  • java web 过滤器
  • 华为云IAM用户权限设置主要有哪些问题需要注意?
  • 医疗生态全域智能化:从技术革新到价值重塑的深度探析
  • 激光驱鸟:以科技重构生态防护边界
  • JavaAPI — 包装类与正则表达式
  • 从厨房到云端:从预制菜到云原生
  • kotlin flatMap 变换函数的特点和使用场景
  • SpringBoot Actuator未授权访问漏洞的全面解析与解决方案
  • 【uom】 0 配置文件(Cargo.toml)
  • vscode chrome调试怎么在所有浏览器都好使
  • jmeter-Beashell获取请求body data
  • 音视频之H.265/HEVC网络适配层
  • 打造惊艳的渐变色下划线动画:CSS实现详解
  • [C++]C++20协程的原理
  • 【MySQL】聚合查询 和 分组查询
  • 大脑、机器人与贝叶斯信念及AI推理
  • Spring MVC 进阶 - 拦截器、异常处理、数据校验
  • 【网络编程】UDP协议 和 Socket编程
  • Nginx核心功能
  • 数据一致性巡检总结:基于分桶采样的设计与实现
  • 青少年编程与数学 02-018 C++数据结构与算法 16课题、贪心算法
  • HCIA-Datacom 高阶:VLAN、VLANIF 与静态路由综合实验
  • 清华与智谱联合发布TTS模型GLM-4-Voice,支持情绪、语气控制,多语言,实时效果很不错~
  • nginx 核心功能
  • Python异常抛出指南
  • vue3使用<el-date-picker分别设置开始时间和结束时间时,设置开始时间晚于当前时间,开始时间早于结束时间,结束时间晚于开始时间
  • 完整的 SSL 证书生成与 Spring Boot 配置流程