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

使用SSM框架实现个人博客管理平台以及实现Web自动化测试

文章目录

  • 前言
    • 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中;

  1. common包:设置统一数据格式返回代码(AjaxResult)、全局变量用于session存储(AppVariable)、密码加盐已经密码验证(PasswordUtils)、获取当前用户(UserSessionUtils)。
  2. config包:系统配置文件(Appconfig)用于设置登录拦截器规则、登录拦截器的实现(LoginIntercept)、数据返回增强,校验是否是统一格式返回不是则封装为统一格式(ResponseAdvice)
  3. controller包:控制层;连接页面请求和服务层,获取页面请求的参数,通过自动装配,映射不同的URL到相应的处理函数,并获取参数,对参数进行处理,之后传给服务层。关于博客文章的控制器(ArticleController),实现博客以及草稿的增删改查以及列表分页点击量统计等功能、关于用户的控制器(UserController)实现增删改查功能。
  4. entity包:实体类,定义文章以及用户属性,同时定义视图UserVo的属性。
  5. service包:服务层;为控制层提供服务,接受控制层的参数,完成相应的功能,并返回给控制层;
  6. mapper包:持久层;根据service相关功能定义与数据库相关的增删改查方法。

在这里插入图片描述

在resources包中保存着系统资源,其中:

  1. mapper:根据 com.example.blog_system.mapper中的方法实现sql语句的增删改查。
  2. static:存储系统的前端页面HTML,CSS样式,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((salt+password).getBytes());//3。生成最终密码,32位盐值+"$"+加盐密码String finalpassword = salt+"$"+saltpassword;retur

在进行用户登录密码校验中,密码解密过程,从数据库取出密码,得到盐值,根据盐值以及用户输入密码进行加密,校验与数据库存储密码是否相同。

具体实现如下:

//2.生成最终密码(数据库中的,便于密码验证)public static String encrypt(String password,String salt){//2.通过盐值和原始密码生成加盐之后的密码String saltpassword = DigestUtils.md5DigestAsHex((salt+password).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!=null&&session.getAttribute(AppVariable.USER_SESSION_KEY)!=null){//用户已登录return true;}//跳转到登录页面response.sendRedirect("/login.html");return false;}
}

6. 项目展示

主页:
在这里插入图片描述

我的博客列表页:
在这里插入图片描述

博客编辑页:
在这里插入图片描述

草稿列表页:
在这里插入图片描述

草稿编辑页:
在这里插入图片描述

个人中心:
在这里插入图片描述

修改个人信息:
在这里插入图片描述

登录页面:
在这里插入图片描述
注册页面:
在这里插入图片描述

7. 项目测试

接下来将对个人博客管理平台功能以及界面进行测试,编写Web自动化测试用例。

7.1 测试用例

编写的测试用例如下:

在这里插入图片描述

7.2 执行部分自动化测试用例

登录功能:执行登录测试用例检验结果是否符合预期、界面是否符合预期;

检测页面是否正确加载:

  /*** 打开网页*/@Test@Order(1)public  void openWeb() throws InterruptedException {driver.get("http://124.221.76.124:59090/login.html");sleep(3000);}//检测页面是否正常打开,元素是否存在@Test@Order(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"));}

测试结果如下:符合预期

在这里插入图片描述
在这里插入图片描述

检测用户名密码错误是否登录失败:

  @ParameterizedTest@CsvSource({"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);}

测试结果如下:符合预期

在这里插入图片描述
在这里插入图片描述

检测用户名已经密码正确是否登录成功并且跳转到正确的用户下

/***登录正常测试*/@ParameterizedTest@CsvSource({"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);}

测试结果如下:符合预期
在这里插入图片描述

在这里插入图片描述

分页查询功能:执行分页查询功能的测试用例查看主页响应是否符合预期

检查首页的博客内容是否正确显示:

//检查首页的博客标题,内容是否正确显示@Test@Order(1)public void checkElements(){String actual = driver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("保姆级自动化测试教程(Selenium+java)",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

总结:根据测试用例结果基本符合预期可以确定个人博客管理平台的基本功能能够正确执行。

相关文章:

使用SSM框架实现个人博客管理平台以及实现Web自动化测试

文章目录 前言1. 项目概述2. 项目需求2.1功能需求2.2 其他需求2.3 系统功能模块图 3. 开发环境4. 项目结构5. 部分功能介绍5.1 数据库密码密文存储5.2 统一数据格式返回5.3 登录拦截器 6. 项目展示7. 项目测试7.1 测试用例7.2 执行部分自动化测试用例 前言 在几个月前实现了一…...

【深度学习】MAT: Mask-Aware Transformer for Large Hole Image Inpainting

论文:https://arxiv.org/abs/2203.15270 代码:https://github.com/fenglinglwb/MAT 文章目录 AbstractIntroductionRelated WorkMethod总体架构卷积头Transformer主体Adjusted Transformer Block Multi-Head Contextual Attention Style Manipulation Mo…...

PyTorch BatchNorm2d详解

通常和卷积层,激活函数一起使用...

慕课网Go-4.package、单元测试、并发编程

package 1_1_User.go package usertype User struct {Name string }1_1_UserGet.go package userfunc GetCourse(c User) string {return c.Name }1_1_UserMain.go package mainimport ("fmt"Userch03 "goproj/IMOOC/ch03/user"//别名,防止同名…...

[JavaWeb]SQL介绍-DDL-DML

SQL介绍-DDL-DML 一.SQL简介1.简介2.SQL通用语法3.SQL语言的分类 二.DDL-操作数据库与表1.DDL操作数据库2.DDL操作表①.查询表(Retrieve)②.创建表(Create)③.修改表(Update)④.删除表(Delete) 三.Navicat的安装与使用四.DML-操作表数据1.添加(Insert)2.修改(Update)3.删除(Del…...

git源码安装(无sudo权限)

git源码安装(无sudo权限) 下载源码解压安装添加到环境变量 下载源码 去https://mirrors.edge.kernel.org/pub/software/scm/git/下载需要的版本。我下载的是2.41.0版本 wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.41.0.tar.gz解…...

Web3 叙述交易所授权置换概念 编写transferFrom与approve函数

前文 Web3带着大家根据ERC-20文档编写自己的第一个代币solidity智能合约 中 我们通过ERC-20一种开发者设计的不成文规定 也将我们的代币开发的很像个样子了 我们打开 ERC-20文档 我们transfer后面的函数就是transferFrom 这个也是 一个账号 from 发送给另一个账号 to 数量 val…...

Redis系列二:Clion+MAC+Redis环境搭建

1. ClionMACRedis-3.0-annotated环境搭建 参考: https://github.com/huangz1990/redis-3.0-annotated https://gitee.com/dumpcao/redis-3.0-annotated-cmake-in-clion https://tool.4xseo.com/a/12910.html 1.1 下载并导入Clion git clone https://gitee.com/dum…...

Linux下 Docker容器引擎基础(2)

目录 创建私有仓库 将修改过的nginx镜像做标记封装,准备上传到私有仓库 将镜像上传到私有仓库 从私有仓库中下载镜像到本地 CPU使用率 CPU共享比例 CPU周期限制 CPU 配额控制参数的混合案例 内存限制 Block IO 的限制 限制bps 和iops 创建私有仓库 仓库&a…...

现场服务管理系统有哪些?5个现场服务管理软件对比

现场售后服务管理软件的使用者通常是机械设备、家电、仪表仪器、医疗器械等厂商的工程师和客服调度人员。现场售后服务管理软件可将服务过程标准化,包括工单派发、服务过程步骤、配件订购出货和付款、客户评价都有系统支持,有的现场售后服务软件还支持数…...

leetcode 912.排序数组

⭐️ 题目描述 🌟 leetcode链接:排序数组 思路: 此题如果使用冒泡插入选择这些时间复杂度 O ( N 2 ) O(N^2) O(N2) 的算法会超时,使用快排 优化也过不去,因为里面有一个测试用例全是 2 即使加了三数取中也会是 O (…...

利用MMPreTrain微调图像分类模型

前言 MMPreTrain是一款基于PyTorch的开源深度学习预工具箱,是OpenMMLab项目的成员之一MMPreTrain的主要特性有: 支持多元化的主干网络与预训练模型支持多种训练策略(有监督学习,无监督学习,多模态学习等)提…...

express学习笔记3 - 三大件

便于统一管理router,创建 router 文件夹,创建 router/index.js: const express require(express)// 注册路由 const router express.Router() router.get(/,function(req,res){res.send(让我们开始express之旅) }) /*** 集中处理404请求的…...

Java课题笔记~Maven基础

2、Maven 基础 2.1 Maven安装与配置 下载安装 配置:修改安装目录/conf/settings.xml 本地仓库:存放的是下载的jar包 中央仓库:要从哪个网站去下载jar包 - 阿里云的仓库 2.2 创建Maven项目...

三步问题(力扣)n种解法 JAVA

目录 题目:1、dfs:2、dfs 备忘录(剪枝):(1)神器 HashMap 备忘录:(2)数组 memo 备忘录: 3、动态规划:4、利用 static 的储存功能:&…...

flask---》登录认证装饰器/配置文件/路由系统

登录认证装饰器 # 0 装饰器的本质原理-# 类装饰器:1 装饰类的装饰器 2 类作为装饰器 # 1 装饰器使用位置,顺序 # 3 flask路由下加装饰器,一定要加endpoint-如果不指定endpoint,反向解析的名字都是函数名,不加装饰器…...

Jvm实际运行情况-JVM(十七)

上篇文章说jmap和jstat的命令,如何查看youngGc和FullGc耗时和次数。 Jmap-JVM(十六) Jvm实际运行情况 背景: 机器配置:2核4G JVM内存大小:2G 系统运行天数:7天 期间发生FULL GC次数和耗时…...

【BASH】回顾与知识点梳理(二)

【BASH】回顾与知识点梳理 二 二. Shell 的变量功能2.1 什么是变量?2.2 变量的取用与设定: echo, 变量设定规则: set/unset2.3 环境变量的功能用 set 观察所有变量 (含环境变量与自定义变量)export: 自定义变量转成环境变量那如何将环境变量转成自定义变…...

【分布式训练】Accelerate 多卡训练,单卡评测,进程卡住的解决办法

最近想把之前的一个模型的改成多卡训练的。我并不懂DDP,DP。一开始打算使用Transformers的Trainer,但是配置的过程踩了很多坑也没有弄成功。【我是自己写的评测方法,但是我找不到能让触发Trainer去用我的方法评测的路劲】,后来偶然…...

时间复杂度为O(nlogn)的两种排序算法

1.归并排序 归并排序的核心思想:如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。 归并排序使用的就是分治思想。分治&#x…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...

CTF show 数学不及格

拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 ​ 用IDA Pro 64 打开这个文件 ​ 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 ​ 根据题目…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...

stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)

这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...