新野微网站建设,网站开发技术语言的选择,网站seo方法,带地板翻转的网站怎么做文章目录 前言1. 项目概述2. 项目需求2.1功能需求2.2 其他需求2.3 系统功能模块图 3. 开发环境4. 项目结构5. 部分功能介绍5.1 数据库密码密文存储5.2 统一数据格式返回5.3 登录拦截器 6. 项目展示7. 项目测试7.1 测试用例7.2 执行部分自动化测试用例 前言
在几个月前实现了一… 文章目录 前言1. 项目概述2. 项目需求2.1功能需求2.2 其他需求2.3 系统功能模块图 3. 开发环境4. 项目结构5. 部分功能介绍5.1 数据库密码密文存储5.2 统一数据格式返回5.3 登录拦截器 6. 项目展示7. 项目测试7.1 测试用例7.2 执行部分自动化测试用例 前言
在几个月前实现了一个servlet版本的博客系统本项目则是在原有基础上进行升级。使用SSM框架、数据库密码使用加盐算法加密、使用Redis对session进行持久化存储从而支持分部式部署、通过拦截器实现用户登录校验、对于数据格式返回以及异常处理进行统一功能处理、增加分页以及点击量统计等功能。
1. 项目概述
用户进入主页可以看到他人发布的博客同时也可以注册账号通过本平台编写发布博客平台支持markdown编辑用户也可以在个人中心修改个人信息同时对博客可以随写随存以草稿形式之后也可以发布修改草稿。用户可以通过博客的点击量判断博客质量等等。
2. 项目需求
2.1功能需求
登录与注册功能个人中心查看、修改个人信息查看博客详情编写个人博客修改个人博客删除个人博客草稿箱保存博客为草稿修改博客为草稿发布草稿为博客草稿增删改查博客列表分页查询功能博客阅读量统计注销功能
2.2 其他需求
系统界面有良好的视觉体验营造美观舒适的界面操作简单流畅无可视卡顿有良好的引导提示增强用户体验
2.3 系统功能模块图 3. 开发环境 1.前端开发 技术HTML、CSS、JavaScript 工具IntelliJ IDEA 2021.3.1 2.后端开发 服务器tomcat-8.5.50 数据库MySQL5.7 开发语言Java 技术框架SpringBoot、SpringMVC、Mybatis、Redis 管理工具Maven 开发工具Intellij IDEA 2020.1.4 操作系统Windows10 4. 项目结构
Java源代码位于com.example.blog_system中
common包设置统一数据格式返回代码AjaxResult、全局变量用于session存储AppVariable、密码加盐已经密码验证PasswordUtils、获取当前用户UserSessionUtils。config包系统配置文件Appconfig用于设置登录拦截器规则、登录拦截器的实现LoginIntercept、数据返回增强校验是否是统一格式返回不是则封装为统一格式ResponseAdvicecontroller包控制层连接页面请求和服务层获取页面请求的参数通过自动装配映射不同的URL到相应的处理函数并获取参数对参数进行处理之后传给服务层。关于博客文章的控制器ArticleController实现博客以及草稿的增删改查以及列表分页点击量统计等功能、关于用户的控制器UserController实现增删改查功能。entity包实体类定义文章以及用户属性同时定义视图UserVo的属性。service包服务层为控制层提供服务接受控制层的参数完成相应的功能并返回给控制层mapper包持久层根据service相关功能定义与数据库相关的增删改查方法。 在resources包中保存着系统资源其中
mapper根据 com.example.blog_system.mapper中的方法实现sql语句的增删改查。static存储系统的前端页面HTMLCSS样式markdown编辑器jquery等相关资源。
5. 部分功能介绍
5.1 数据库密码密文存储
基于spring框架提供的md5加密的基础上通过UUID生成随机盐值对用户密码进行加密
加密过程如下
//1.加盐并生成密码public static String encrypt(String password){//1.生成盐值String salt UUID.randomUUID().toString().replace(-,);//2.生成加盐之后的密码String saltpassword DigestUtils.md5DigestAsHex((saltpassword).getBytes());//3。生成最终密码32位盐值$加盐密码String finalpassword salt$saltpassword;retur在进行用户登录密码校验中密码解密过程从数据库取出密码得到盐值根据盐值以及用户输入密码进行加密校验与数据库存储密码是否相同。
具体实现如下
//2.生成最终密码数据库中的便于密码验证public static String encrypt(String password,String salt){//2.通过盐值和原始密码生成加盐之后的密码String saltpassword DigestUtils.md5DigestAsHex((saltpassword).getBytes());
// 最终密码String finalPassword salt$saltpassword;return finalPassword;}//3.验证密码/**** param inputPassword 用户输入密码* param finalPassword 数据库存储密码* return*/public static boolean check(String inputPassword,String finalPassword){//先进性非空校验和长度校验if (StringUtils.hasLength(inputPassword)StringUtils.hasLength(finalPassword)finalPassword.length()65){//1.得到盐值从finalPassword,对$加上\\进行转义它是关键字String salt finalPassword.split(\\$)[0];//2.使用之前加密步骤将明文加密并生成最终密码String confinmrPassword PasswordUtils.encrypt(inputPassword,salt);//3,进行比较return confinmrPassword.equals(finalPassword);}return false;}5.2 统一数据格式返回
定义数据格式为状态码状态码描述信息返回数据实现成功以及失败的返回。
具体实现如下
package com.example.blog_system.common;import lombok.Data;import java.io.Serializable;/*** 统一数据格式返回*/
Data
public class AjaxResult implements Serializable {// 状态码private Integer code;// 状态码描述信息private String msg;// 返回的数据private Object data;/*** 操作成功返回的结果*/public static AjaxResult succecc(Object data) {AjaxResult result new AjaxResult();result.setCode(200);result.setMsg();result.setData(data);return result;}public static AjaxResult succecc(int code, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg();result.setData(data);return result;}public static AjaxResult succecc(int code, String msg, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}/*** 返回失败结果*/public static AjaxResult fail(int code, String msg) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(null);return result;}public static AjaxResult fail(int code, String msg, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}}
5.3 登录拦截器
继承HandlerInterceptor实现一个登录拦截器判断在用户进入主页、登录页、注册页、以外的页面进行相关操作时判断是否登录未登录则自动跳转到登录页面。
具体实现如下
/**登录拦截器* author zq* date 2023-07-22 22:33*/public class LoginIntercept implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session request.getSession(false);if(session!nullsession.getAttribute(AppVariable.USER_SESSION_KEY)!null){//用户已登录return true;}//跳转到登录页面response.sendRedirect(/login.html);return false;}
}6. 项目展示
主页
我的博客列表页
博客编辑页
草稿列表页
草稿编辑页
个人中心
修改个人信息
登录页面 注册页面
7. 项目测试
接下来将对个人博客管理平台功能以及界面进行测试编写Web自动化测试用例。
7.1 测试用例 编写的测试用例如下 7.2 执行部分自动化测试用例 登录功能执行登录测试用例检验结果是否符合预期、界面是否符合预期 检测页面是否正确加载 /*** 打开网页*/TestOrder(1)public void openWeb() throws InterruptedException {driver.get(http://124.221.76.124:59090/login.html);sleep(3000);}//检测页面是否正常打开元素是否存在TestOrder(2)public void elementAppear(){driver.findElement(By.cssSelector(body div.login-container div h3));driver.findElement(By.cssSelector(#username));driver.findElement(By.cssSelector(#password));driver.findElement(By.cssSelector(#submit));}测试结果如下符合预期 检测用户名密码错误是否登录失败 ParameterizedTestCsvSource({admin,12345})Order(2)//登录异常检测public void loginAbnormalTest(String username, String password) throws IOException, InterruptedException {//先清除用户名和密码框driver.findElement(By.cssSelector(#username)).clear();driver.findElement(By.cssSelector(#password)).clear();//输入账号和密码driver.findElement(By.cssSelector(#username)).sendKeys(username);driver.findElement(By.cssSelector(#password)).sendKeys(password);driver.findElement(By.cssSelector(#submit)).click();//期望结果和实际结果String expect 登录失败用户名或密码错误请重试;String actual driver.findElement(By.cssSelector(body)).getText();Assertions.assertEquals(expect, actual);sleep(5000);}
测试结果如下符合预期 检测用户名已经密码正确是否登录成功并且跳转到正确的用户下
/***登录正常测试*/ParameterizedTestCsvSource({admin,123456})Order(3)public void loginNormalTest(String username, String password) throws IOException, InterruptedException {//先清除用户名和密码框driver.findElement(By.cssSelector(#username)).clear();driver.findElement(By.cssSelector(#password)).clear();//输入用户名和密码并点击登录driver.findElement(By.cssSelector(#username)).sendKeys(username);driver.findElement(By.cssSelector(#password)).sendKeys(password);driver.findElement(By.cssSelector(#submit)).click();//查看跳转页面是否是博客列表页sleep(3000);String url http://124.221.76.124:59090/myblog_list.html;Assertions.assertEquals(url,driver.getCurrentUrl());// 校验当前登录的用户是不是admin如果是测试通过否则测试不通过String user_name driver.findElement(By.cssSelector(#username)).getText();driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(username, user_name);sleep(5000);}测试结果如下符合预期 分页查询功能执行分页查询功能的测试用例查看主页响应是否符合预期 检查首页的博客内容是否正确显示
//检查首页的博客标题内容是否正确显示TestOrder(1)public void checkElements(){String actual driver.findElement(By.cssSelector(#artListDiv div:nth-child(1) div.title)).getText();Assertions.assertEquals(保姆级自动化测试教程(Seleniumjava,actual);String actual1 driver.findElement(By.cssSelector(#artListDiv div:nth-child(1) div.date)).getText();Assertions.assertEquals(2023-07-31,actual1);String actual2 driver.findElement(By.cssSelector(#artListDiv div:nth-child(1) div.desc)).getText();Assertions.assertEquals(自动化测试指软件测试的自动化在预设状态下运行应用程序或者系统预设条件包括正常和异常最后评估运行结果。将人为驱动的测试行为转化为机器,actual2);}测试结果如下符合预期
检查分页查询首页、上一页、下一页、末页功能是否正常
//检查分页查询功能Testpublic void checkCha() throws InterruptedException {//首页driver.findElement(By.cssSelector(body div.container div div.blog-pagnation-wrapper button:nth-child(1))).click();sleep(3000);Alert alert driver.switchTo().alert();String atext alert.getText();Assertions.assertEquals(已经是第一页,atext);//点击确定关闭弹窗alert.accept();//上一页driver.findElement(By.cssSelector(body div.container div div.blog-pagnation-wrapper button:nth-child(2))).click();sleep(3000);Alert alert2 driver.switchTo().alert();String atext2 alert.getText();Assertions.assertEquals(已经是第一页,atext2);alert2.accept();//下一页driver.findElement(By.cssSelector(body div.container div div.blog-pagnation-wrapper button:nth-child(3))).click();sleep(3000);Alert alert3 driver.switchTo().alert();String atext3 alert.getText();Assertions.assertEquals(已经是最后一页,atext3);alert3.accept();//尾页driver.findElement(By.cssSelector(body div.container div div.blog-pagnation-wrapper button:nth-child(4))).click();sleep(3000);Alert alert4 driver.switchTo().alert();String atext4 alert.getText();Assertions.assertEquals(已经是最后一页,atext4);alert4.accept();}测试结果如下符合预期 博客编辑功能查看编辑发布博客、保存为草稿以及博客编辑页面是否正常显示 检查不输入标题时提示信息是否正确检查输入标题发布文章时是否跳转到我的博客列表页 Test//Order(2)//检查发布文章功能是否正常分为输入为空、非空public void checkAdd() throws InterruptedException {sleep(3000);driver.findElement(By.cssSelector(body div.nav a:nth-child(5))).click();sleep(3000);//1.输入为空driver.findElement(By.xpath(/html/body/div[2]/div[1]/button[1])).click();sleep(3000);Alert alert1 driver.switchTo().alert();String atext1 alert1.getText();Assertions.assertEquals(确认提交,atext1);alert1.accept();sleep(3000);Alert alert driver.switchTo().alert();String atext alert.getText();Assertions.assertEquals(请先输入标题,atext);alert.accept();sleep(3000);//2输入不为空时是否正常发布跳转到博客列表页driver.findElement(By.cssSelector(#title)).sendKeys(发布文章测试);sleep(3000);driver.findElement(By.xpath(/html/body/div[2]/div[1]/button[1])).click();sleep(3000);Alert alert2 driver.switchTo().alert();String atext2 alert1.getText();Assertions.assertEquals(确认提交,atext1);alert1.accept();sleep(3000);//不再继续提交Alert alert3 driver.switchTo().alert();alert3.dismiss();sleep(3000);//验证当前页面是否是博客列表页面String url driver.getCurrentUrl();Assertions.assertEquals(http://124.221.76.124:59090/myblog_list.html,url);}测试结果如下符合预期
同上述检查保存为草稿时是否符合预期 测试结果如下符合预期 博客相关功能删除、查看全文、修改 草稿相关功能删除、查看全文、修改 测试代码与结果如下符合预期 篇幅有限关于其他功能的测试在此省略测试完整代码可以查看我的码云https://gitee.com/zxxqqa/automated-testing
总结根据测试用例结果基本符合预期可以确定个人博客管理平台的基本功能能够正确执行。