Java个人博客系统--基于Springboot的设计与实现
目录
一、项目概述
应用技术
接口实现:
数据库定义:
数据库建表:
博客表数据库相关操作:
添加项⽬公共模块
加密MD5
页面展示:http://121.41.168.121:8080/blog_login.html
项目源码:https://gitee.com/li-dot/blogs
二、对博客系统进行自动化测试
测试用例图Docs
使用Selenium进行测试
一、项目概述
应用技术
接口实现:

数据库定义:

数据库建表:
--建表SQL
create database if not exists `java_blog_spring` charset utf8mb4;
--⽤户表
drop table if exists `java_blog_spring`.`user`;
CREATE TABLE `java_blog_spring`.`user` (`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` TIMESTAMP NULL DEFAULT current_timestamp(),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`;
CREATE TABLE `java_blog_spring`.`blog` (`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` TIMESTAMP NULL DEFAULT current_timestamp(),PRIMARY KEY (`id`))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';
--新增⽤户信息
insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("zhangsan","123456","https://gitee.com");
insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("lisi","123456","https://gitee.com");
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼀篇博客","111我是博客正⽂我是博客正⽂我是博客正⽂",1);
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼆篇博客","222我是博客正⽂我是博客正⽂我是博客正⽂",2);
博客表数据库相关操作:
......
添加项⽬公共模块
加密MD5
页面展示:http://121.41.168.121:8080/blog_login.html
用户名:zhangsan/lisi
密码:123456
博客登录界面:

博客列表页:

博客详情页:
写博客页:
项目源码:https://gitee.com/li-dot/blogs
二、对博客系统进行自动化测试
测试用例图Docs

使用Selenium进行测试
package BlogTest;import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriverBuilder;import java.util.concurrent.TimeUnit;import static java.lang.Thread.sleep;/*** @author Dian* Description* Date:2023/8/5:23:47*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogCases extends InitAndEnd{/*** 登录*/@Order(1)@ParameterizedTest //参数化@CsvSource("zhangsan,123456")void Login(String userName,String password) throws InterruptedException {System.out.println(userName);System.out.println(password);//打开登陆页面webDriver.get("http://121.41.168.121:8080/blog_login.html");//输入用户名webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("#userName")).sendKeys(userName);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);sleep(2000);//校验当前登录的用户是不是zhangsan,如果是则测试通过,否则测试不通过String user_name = webDriver.findElement(By.cssSelector("h3")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(userName,user_name);}/***博客列表*/@Order(2)
@Testvoid BlogList(){webDriver.get("http://121.41.168.121:8080/blog_list.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int blog_num = webDriver.findElements(By.cssSelector(".title")).size();Assertions.assertNotEquals(0,blog_num);String page_title = webDriver.getTitle();Assertions.assertEquals(page_title,"博客列表页");}
/*** 博客详情页校验*/
@Order(3)
@Test
void BlogDetail(){//打开列表页webDriver.get("http://121.41.168.121:8080/blog_list.html");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//找到查看全文按钮webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//获取博客标题String blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > div.title")).getText();//如果博客正文不为空,测试通过//否则测试不通过
Assertions.assertNotNull(blog_title);
}/*** 写博客*/
@Order(4)
@Testvoid EditBlog() throws InterruptedException {// 找到写博客按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 执行js(选中标题输入框,输入字符串)((JavascriptExecutor)webDriver).executeScript("document.querySelector(\"#title\").value =\"自动化测试\"");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 校验页面跳转到列表页sleep(3000);String cur_url = webDriver.getCurrentUrl();// 校验第一条博客标题是不是刚刚发布的博客标题String first_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(6) > div.title")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals("自动化测试",first_blog_title);
}/*** 删除博客*/@Order(5)@Testvoid DeleteBlog(){// 找到查看全文按钮并且点击webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 找到删除按钮,点击webDriver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)")).click();// 校验当前页面是否跳转到博客列表页面webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://121.41.168.121:8080/blog_list.html",cur_url);// 获取博客发布是时间String blog_release_time = webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[2]")).getText();// 如果博客发布时间 包括2023-06-02测试 不通过if(blog_release_time.contains("2023-08-04 15:49:49")){System.out.println("博客发布时间:" + blog_release_time);System.out.println("测试不通过");}else{System.out.println("测试通过");}}/*** 退出博客*/@Order(6)@Testvoid LogOut() throws InterruptedException {webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 找到退出按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 校验页面是否有登录文案String login_text= webDriver.findElement(By.cssSelector("body > div.container-login > div > h3")).getText();// 如果有登录文案,退出成功(测试用例通过)// 否则,退出失败(测试不通过)sleep(3000);if(login_text.equals("登录")){System.out.println("测试通过");}else{System.out.println("测试不通过");}}
}
相关文章:
Java个人博客系统--基于Springboot的设计与实现
目录 一、项目概述 应用技术 接口实现: 数据库定义: 数据库建表: 博客表数据库相关操作: 添加项⽬公共模块 加密MD5 页面展示:http://121.41.168.121:8080/blog_login.html 项目源码:https://gitee…...
在jupyter中下载数据集失败及解决方法(以IMDB为例)
在IMDB数据集下载时,由于网络原因下载失败,报错如下: Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz ConnectionResetError Traceback (most recent call last) … Exception: URL fetch f…...
【设计模式】-工厂方法模式
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,但是将具体对象的创建推迟到子类中。这样,子类可以决定要实例化的对象类型。工厂方法模式提供了一种方式,通…...
H7-TOOL的高速DAPLINK用于新版STM32CubeIDE V1.13及其以上版本的超简单实现方法(2023-08-08)
之前分享了一个方法,太繁琐了,H7-TOOL群的群友提供了一个方法,实现非常简单。1、使用STM32CubeMX或者自己创建一个STM32CubeIDE工程后,设置这两个地方即可: 配置调试器,设置完毕记得点击右下角的Apply 2、然…...
成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】
成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】 问题描述解决方案 问题描述 在下载安装包的时候一直卡在0% [Waiting for headers],报错信息如下: Get:1 file:/var/cudnn-local-repo-ubuntu1804-8.5.0.96 InRelease […...
openLayers实战(一):vue项目中的离线地图引入
最近的项目涉及到离线地图的操作,查阅社区文章,决定使用openLayersvue离线地图的方式进行开发,前期基础引入操作完全参考掘金文章,非常优秀全面的文章。 openlayers 实战离线地图 - 掘金 此外,开发过程的地图操作可参考…...
如何构造一个安全的单例?
为什么要问这个问题? 我们知道,单例是一种很常用的设计模式,主要作用就是节省系统资源,让对象在服务器中只有一份。但是实际开发中可能有很多人压根没有写过单例这种模式,只是看过或者为了面试去写写demo熟悉一下。那…...
单片机开发 esp8266
一、固件界面 二、项目介绍 固件名称:esp8266-universalboard v1.0 提供商: 半条虫(466814195) 下载:esp8266-universalboard.bin 源码地址:Gitlab...
Linux 查看版本和用户权限提升实践心得
文章目录 linux (Ubuntu内核)查看版本版本信息解释内置yum工具?用户权限提升操作步骤 查看deepin系统的版本和其debian的版本遇到的问题:deepin-release文件不存在 linux (Ubuntu内核)查看版本 使用lsb_release命令: lsb_release -a该命令将…...
多线程编程5:线程同步和进程通信(C++11和linux)
常见的线程同步 linux: 互斥锁:实现共享资源的串行访问,有三个版本普通锁(默认属性),检错锁(可以防止相同线程重复加锁)和递归锁(相同线程可以重复加锁)条件变量:配合互斥锁使用,实现线程之间的通信&#…...
tensorrt官方int8量化方法汇总
原理及操作 量化的基本原理及流程可参看懂你的神经网络量化教程:第一讲、量化番外篇、TensorRT中的INT8、tensorRT int8量化示例代码 Tensorrt 方式1:trtexec(PTQ的一种) int8量化 trtexec --onnxXX.onnx --saveEnginemodel.…...
21、p6spy输出执行SQL日志
文章目录 1、背景2、简介3、接入3.1、 引入依赖3.2、修改database参数:3.3、 创建P6SpyLogger类,自定义日志格式3.4、添加spy.properties3.5、 输出样例 4、补充4.1、参数说明 1、背景 在开发的过程中,总希望方法执行完了可以看到完整是sql语…...
实力认证!TDengine 入选 Gartner 中国数据分析与人工智能技术成熟度曲线
近日,国际权威研究机构 Gartner 发布了《2023 年中国数据分析及人工智能技术成熟度曲线》(即《Hype Cycle for Data, Analytics and AI in China, 2023》)报告,TDengine 成功入选实时数据管理领域代表产品。 作为评估全球新技术成…...
如何将jar包部署到宝塔
尝试多种方式上传,但启动一直失败,这种方式亲测是好使的 项目内修改位置 在pom.xml文件中将mysql的scope改成provided,如果是固定的版本号会出现问题 之后就可以打包啦,直接点击maven中的package 找到打包文件的位置ÿ…...
el-tree-select那些事
下拉菜单树形选择器 用于记录工作及日常学习涉及到的一些需求和问题 vue3 el-tree-select那些事 1、获取el-tree-select选中的任意层级的节点对象 1、获取el-tree-select选中的任意层级的节点对象 1-1数据集 1-2画面 1-3代码 1-3-1画面代码 <el-tree-selectv-model"s…...
分布式任务调度框架之开山鼻祖:Quartz
1.简介 最近我司上线使用了分布式任务调度框架:XXL-JOB,方便对任务的管理控制。本来一开始就想讲述一下该框架,但是在学习了解过程中发现该框架式基于Quartz思想开发实现的,Quartz 是一个很火的开源任务调度框架,完全…...
Django实现音乐网站 ⑺
使用Python Django框架制作一个音乐网站, 本篇主要是后台对歌手原有实现功能的基础上进行优化处理。 目录 新增编辑 表字段名称修改 隐藏单曲、专辑数 姓名首字母 安装xpinyin 获取姓名首字母 重写保存方法 列表显示 图片显示处理 引入函数 路径改为显示…...
PO、DTO和VO的区别
PO:Persistence Object,是持久化对象,也叫实体对象(Entity),是对象到关系表的映射。在关系型数据库中,每张表对应着一个PO,PO 中的属性值与表中数据一一对应,通过数据访问…...
ReadableStream流的js处理
需求 今天接了一个gpt的项目。需要对接接口。后端返回的数据是ReadableStream类型的。记录下如何处理ReadableStream类型的数据 代码 const response ... // response 是服务端返回的数据// 创建了一个数据读取器 const reader response.getReader(); // 创建了一个文本解…...
图扑软件入选 2023 中国信通院“铸基计划”全景图
7 月 27 日,由中国信通院主办的“2023 数字生态发展大会”暨中国信通院“铸基计划”年中会议在北京召开。本次大会重磅发布了《高质量数字化转型产品及服务全景图(2023 上半年度)》。图扑软件凭借自研 HT for Web 数字孪生可视化产品成功入选…...
VisualCppRedist AIO:一站式解决Windows系统依赖问题的开源神器
VisualCppRedist AIO:一站式解决Windows系统依赖问题的开源神器 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 在Windows生态中,超过80%…...
系统安装:安装Ubuntu 26.04 LTS
1. EFI以及UEFI,什么用途? https://baike.baidu.com/item/EFI/2025809 EFI(Extensible Firmware Interface,可扩展固件接口)是由英特尔公司开发的固件接口标准,用于替代传统BIOS以实现更高效的硬件初始化和…...
AI编程助手Composer插件:无缝管理PHP依赖,提升结对编程效率
1. 项目概述:一个为AI编程助手量身定制的Composer工具如果你和我一样,日常重度依赖像Aider这样的AI编程助手来提升开发效率,那你一定遇到过这样的场景:你正和AI助手热火朝天地讨论一个功能实现,它为你生成了一段完美的…...
八千多条提示词,装成你的「随身工具箱」
做图、想创意的时候,最烦的不是「不会写」,而是找不到、和不好管,写过的好句子不知道丢哪了。群里转发的、自己试出来的、收藏夹里吃灰的链接——真要用时,往往只记得个大概,翻半天也找不回来。 BoltPrompt 提示词库想…...
Cortex-M0非对齐访问陷阱:从硬件错误中断到__attribute__((aligned))的实战避坑指南
1. Cortex-M0非对齐访问的硬件陷阱 第一次在Cortex-M0上遇到HardFault中断时,我盯着调试器看了整整半小时。那是个简单的Flash读取函数,代码在STM32F0上运行得好好的,移植到M0内核的芯片就突然崩溃。后来发现这其实是很多嵌入式新手都会踩的…...
3步完成Python界面设计:可视化拖拽工具完全指南
3步完成Python界面设计:可视化拖拽工具完全指南 【免费下载链接】tkinter-helper 为tkinter打造的可视化拖拽布局界面设计小工具 项目地址: https://gitcode.com/gh_mirrors/tk/tkinter-helper 还在为Python界面开发而烦恼吗?手动编写Tkinter代码…...
GitHub代码仓库导航:开发者如何高效构建与使用技术资源地图
1. 项目概述:一个面向开发者的代码仓库导航 最近在GitHub上闲逛,发现了一个挺有意思的仓库,叫 yeabnoah/vx_code 。乍一看这个标题,可能会有点摸不着头脑, vx_code 是什么?是某种新的编程语言…...
RISC-V开发踩坑实录:从编译错误‘csrr a5,mhartid’到GDB报错‘E14’的完整排错指南
RISC-V开发实战:从编译到调试的完整排错手册 在嵌入式开发领域,RISC-V架构正以惊人的速度改变着行业格局。作为一名长期从事ARM架构开发的工程师,当我第一次接触RISC-V时,本以为凭借多年的嵌入式经验可以轻松上手,却没…...
别再只做静态分析了!用DPABI探索小鼠大脑rs-fMRI的动态功能连接(含Matlab代码片段)
动态功能连接分析:解锁小鼠大脑rs-fMRI的时变奥秘 在神经影像研究领域,静息态功能磁共振成像(rs-fMRI)已成为探索大脑功能组织的强大工具。传统静态分析方法虽然提供了宝贵的基础认知,但大脑本质上是一个动态系统,其功能连接会随时…...
告别混乱!用EPLAN高效管理端子连接图的5个实战技巧与常见坑点复盘
告别混乱!用EPLAN高效管理端子连接图的5个实战技巧与常见坑点复盘 在电气工程设计领域,端子连接图的质量直接影响着生产效率和调试准确性。许多工程师在项目后期常常陷入反复修改端子图表的泥潭,不仅耗费宝贵时间,还可能因疏忽导致…...
