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

Jest单元测试

由于格式和图片解析问题,可前往 阅读原文

前端自动化测试在提高代码质量、减少错误、提高团队协作和加速交付流程方面发挥着重要作用。它是现代软件开发中不可或缺的一部分,可以帮助开发团队构建可靠、高质量的应用程序

单元测试(Unit Testing)和端到端测试(End-to-End Testing)是两种常见的测试方法,它们在测试的范围、目的和执行方式上有所不同。单元测试和端到端测试不是相互排斥的,而是互补的。它们在不同的层面和阶段提供了不同的价值,共同构成了一个全面的测试策略

单测和端测区别

单元测试(Unit)

  • 单元测试关注于最小的可测试单元,如函数、方法或模块
  • 目的是验证代码中的每个独立单元(如函数)是否按照预期工作
  • 通常是自动化的、快速执行的,且不依赖于外部资源或其他模块
  • 验证单个代码单元的行为,提供快速反馈,并帮助捕获和修复问题

端到端测试(End-to-End)

  • 从用户角度出发,测试整个应用程序的功能和流程
  • 模拟真实的用户交互和场景,从应用程序的外部进行测试。跨多个模块、组件和服务进行,以确保整个应用程序的各个部分正常协同工作
  • 涉及用户界面(UI)交互、网络请求、数据库操作等,以验证整个应用程序的功能和可用性

总之,单元测试主要关注代码内部的正确性,而端到端测试关注整体功能和用户体验。结合使用这两种测试方法可以提高软件的质量和可靠性。在项目中尤其是公共依赖如组件库至少都需要单测,端测相对来说比较繁琐点,但是也是程序稳定的重要验证渠道

单元测试 - Jest

这里使用Jest作为单元测试工具,Jest 是一个用于 JavaScript 应用程序的开源测试框架。它是由 Facebook 开发和维护的,通常用于单元测试。Jest 具有简单易用的 API、丰富的功能和强大的断言库,广泛应用于前端开发和 Node.js 环境中

安装

npm install jest -D

初始化

使用npx进行交互式生成默认的配置文件,它会提示你每步的选择:

➜ npx jest --init
The following questions will help Jest to create a suitable configuration for your project✔ Would you like to use Jest when running "test" script in "package.json"? … yes
✔ Would you like to use Typescript for the configuration file? … no
✔ Choose the test environment that will be used for testing › jsdom (browser-like)
✔ Do you want Jest to add coverage reports? … yes
✔ Which provider should be used to instrument code for coverage? › v8
✔ Automatically clear mock calls, instances, contexts and results before every test? … yes✏️  Modified test/package.json📝  Configuration file created at test/jest.config.js

默认配置文件大概是下面的内容:配置中有很多注释提供我们参考,对于默认的配置就不用删除多语的注释了,方便参考。通常都是对需要的配置项做修改即可

const config = {// All imported modules in your tests should be mocked automatically// automock: false,// Automatically clear mock calls, instances, contexts and results before every testclearMocks: true,// Indicates whether the coverage information should be collected while executing the testcollectCoverage: true,// An array of glob patterns indicating a set of files for which coverage information should be collected// collectCoverageFrom: undefined,// The directory where Jest should output its coverage filescoverageDirectory: "coverage",// An array of regexp pattern strings used to skip coverage collection// coveragePathIgnorePatterns: [//   "/node_modules/"// ],// Indicates which provider should be used to instrument code for coveragecoverageProvider: "v8",// Make calling deprecated APIs throw helpful error messages// errorOnDeprecated: false,// A list of paths to directories that Jest should use to search for files in// roots: [//   "<rootDir>"// ],// The test environment that will be used for testingtestEnvironment: "jsdom",// 省略其他...
};module.exports = config;

常用的配置:

  • collectCoverage:boolean值,用来生成覆盖率报告,通常也可以使用命令行--coverage参数生成

  • moduleFileExtensions:对于引入文件可以省去文件后缀,jest会根据规则一一匹配

  • moduleNameMapper:模块匹配规则,告诉jest改模块的匹配路径

    {moduleNameMapper: {// 当匹配到 .css 等结尾的文件时对应 /__mocks__/style-mock.ts 文件"\\.(css|less|scss|sass)$": "<rootDir>/__mocks__/style-mock.ts",// 当匹配 @ui 开头的的对应到 src 文件夹"@ui/(.*)": "<rootDir>/src/$1",},
    }
    
  • setupFiles:在测试环境准备后和安装jest框架前做一些配置,常用来添加一些全局环境模拟数据

  • setupFilesAfterEnv:在安装jest框架后对jest做一些扩展,相比setupFiles更加通用

  • testEnvironment:jest模拟的环境,可以选择node、jsdom来模拟node和浏览器环境

  • testMatch:指定要测试哪些文件

  • transform:使用一些插件对代码进行转义以便jest可以理解,如设置tsx转义

以上是最基本的配置,jest的配置还是很多的,还要官方有列举了一个表可以随时翻阅不用死记

转译器

Jest中有转义器的概念来帮助它理解编写的代码,可以比做babel对代码做一些转换来兼容浏览器,差不多一样的道理

  1. 模块引用转换

    在单个测试文件中都会引入我们编写的代码,然后对此代码的功能进行测试,而前端通常都是以esmodule的形式进行函数的导出,jest默认使用的是commonjs,对于module语法jest不认识就会报错

    import { sum } from "../core"; // 报错describe("第一个测试", () => {// ...
    })
    

    那么可以对jest添加转义器将esmodule模块的代码转换成commonjs就可以了。打开配置文件:

    // jest.config.js
    {transform: {"^.+\\.(ts|tsx|js|jsx)$": ["babel-jest",{presets: [["@babel/preset-env", { targets: { node: "current" } }]]},],},
    }
    

    上面使用了 babel-jest@babel/preset-env的依赖包需要安装下:

    npm i babel-jest @babel/preset-env -D
    

    这样就可以解决esmodule语法不识别的问题

  2. 转换typescript:目前项目中的文件都是以ts编写的,而默认情况下jest只识别js文件的,那么就需要对ts进行转译让jest识别

    // jest.config.js
    {transform: {"^.+\\.(ts|tsx|js|jsx)$": ["babel-jest",{presets: [/* 其它... */["@babel/preset-typescript"]]},],},
    }
    

    需要安装对应的@babel/preset-typescript;除了使用ts转义器也可以使用ts-jest直接运行ts代码

    得益于ts的转译插件可以让jest的测试文件(或配置文件)都写成ts类型的,而在ts文件中对于不识别的jest工具会报错或者没有提示,安装jest的类型文件包@types/jest来告诉ts对应的jest类型,然后进行配置:

    // tsconfig.json
    {"types": ["jest"]
    }
    
  3. 转换jsx:假如项目中使用了jsx那么也要对jsx进行转义,这里以vue jsx为例

    // jest.config.ts
    {transform: {"^.+\\.(ts|tsx|js|jsx)$": ["babel-jest",{// 省略其他plugins: ["@vue/babel-plugin-jsx"],},],},
    }
    

基本断言

基本环境配置好后,就到了测试的时间了,我们先来最简单的配置用起

// __tests__/demo.spec.ts
import { sum } from "src/utils";describe("第一个测试", () => {it("分组1", () => {expect(sum(1, 2)).toBe(3);});
});// 或者不用分组
test("第一个测试", () => {expect(sum(1, 2)).toBe(3);
});

这里介绍下几个关键字基本概念:

  • describe:用来描述当前测试的整体内容
  • it:用来分组测试
  • test:用来描述当前测试,无分组
  • expect:判断参数的值,其的返回值有多个断言方法,上面使用了toBe也就是等于的意思。除了次此断言有很多断言的条件,你可以点击这里阅读官方文档
执行测试
# 现在package中配置 jest 脚本,然后执行测试npm run test # npx jestPASS  __tests__/demo.spec.ts第一个测试✓ 分组1 (2 ms)----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   utils.ts |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.519 s
Ran all test suites.
✨  Done in 1.02s.

可以看到对应的测试文件、分组以及测试覆盖率

路径映射

上面在测试代码时会先引入对应的工具代码,如果都使用相对路径引入会显得很麻烦。在项目中通常都喜欢使用@这种方式引入文件,在测试环境依然可以使用,这样也可以和项目中的文件路径保持一致

配置路径映射需要满足两个条件:

  1. jest识别路径映射
  2. ts识别路径映射(如果项目中用了ts)
配置jest路径映射
// jest.config.ts
{moduleNameMapper: {"@/(.*)": "<rootDir>/src/$1",},
}
配置tsconfig
// tsconfig.json
{"paths": {"@/*": ["src/*"]}
}

这样在测试文件中就可以使用路径映射降低心智负担

// __tests__/demo.spec.ts
import { sum } from "@/utils";

除了手动设置外还可以将tsconfig中的path直接作为路径映射,这样就减少了多处的修改。实现这一功能需要借助ts-jest工具包,不同这个自己也可以写个逻辑实现

// jest.config.ts
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')export default {moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {prefix: "<rootDir>/",}),
}

dom测试

jest支持浏览器环境,使用浏览器环境时需要安装对应的包,请根据版本可以选择jsdomjest-environment-jsdom包进行安装,这里jest版本为28+使用后者。测试文件修改如下:

// __tests__/demo.spec.ts
describe("第一个测试", () => {it("分组1", () => {// 使用 localStorage APIlocalStorage.setItem('a', '1');expect(localStorage.getItem(('a'))).toBe('1')});
});

运行测试用例:

npm run test
PASS  __tests__/demo.spec.ts第一个测试✓ 分组1 (2 ms)----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.701 s, estimated 1 s
Ran all test suites.
✨  Done in 1.13s.

异步测试

jest可以使用多种方式进行异步代码测试,通常使用promise、async就可以了

  1. 使用promise
  2. async/await
  3. 回调

这里模拟一个异步方法,通过上面的三种方式进行测试

// src/utils
export function getUser(name: string) {return new Promise((resolve) => {setTimeout(() => resolve(name), 1000);});
}
使用Promise
// __tests__/demo.spec.ts
import { getUser } from "@/utils";describe("测试异步代码", () => {it("promise调用方式测试", () => {const user = "小明";// 使用thengetUser(user).then((res) => {expect(res).toBe(user);});});it("使用resolves测试promise", () => {const user = "小李";// 使用 .resolves 方式,注意这里要 returnreturn expect(getUser(user)).resolves.toBe(user);})
});
使用async测试
// __tests__/demo.spec.ts
import { getUser } from "@/utils";describe("测试异步代码", () => {it("使用async测试", async () => {const user = "小明";const res = await getUser(user)expect(res).toBe(user);})
});
使用回调函数

回调函数默认通常是以前那种回调写法,这里需要对以上的异步函数进行调整,让其换成回调函数模式

// 接受一个cb,这里固定返回的值为true,没有错误
export function getUser(cb: (error: any, data: any) => void) {setTimeout(() => {cb(null, true);}, 500);
}// 定义测试
describe("测试异步代码", () => {it("使用回调函数", (done) => {function cb(error: any, data: any) {if (error) {done(error);return;}try {expect(data).toBe(true);done();} catch (err) {done(err); // 这里一定要使用try catch,防止出错时没有执行done}}getUser(cb);});
});

回调模式一定要执行done函数,如果没有执行则会被认为超时错误

模拟函数

假设要模拟一个工具函数的内部实现,可以使用mock函数来判断函数内部的值是否达到预期

定义个待测试的函数forEach

export function forEach(items: number[], callback: (num: number) => void) {for (let index = 0; index < items.length; index++) {callback(items[index]);}
}

添加测试用例:

// __tests__/demo.spec.ts
import { forEach } from "@/utils";// 模拟函数
const mockFn = jest.fn((x: number) => x + 1);test("模拟函数", () => {forEach([0, 1], mockFn);expect(mockFn.mock.calls).toHaveLength(2);expect(mockFn.mock.calls[0][0]).toBe(0);expect(mockFn.mock.calls[1][0]).toBe(1);expect(mockFn.mock.results[0].value).toBe(1);
});

更多关于模拟函数的例子请查看文档 和 API

定时器

Jest可以通过一个函数转换计时器以便允许你控制时间流量

假设测试如下定时器代码:

export function useTimer(cb?: Function) {setTimeout(() => cb && cb(), 1000);
}

编写测试用例:

import { useTimer } from "@/utils";jest.useFakeTimers();
jest.spyOn(global, "setTimeout");test("test timer", () => {const cb = jest.fn();useTimer(cb);expect(cb).not.toBeCalled();// 执行所有的定时器jest.runAllTimers();expect(cb).toBeCalled();
});

更多见官方文档

setup配置

写测试的时候你经常需要在运行测试前做一些准备工作,和在运行测试后进行一些收尾工作。 Jest 提供辅助函数来处理这个问题

这其中包括beforeEach、afterEach、beforeAll、afterAll,其中前两者在每个测试前都会执行一次,后者在文件中只会执行一次

覆盖率

除了对程序进行断言外,jest还收集代码的测试覆盖率并生成对应的报告,包括:某个函数内部的测试覆盖率、整个文件的覆盖率,要想达到覆盖率100%,就要测试到每个文件的所有代码、每个函数内部的所有分支条件

开启覆盖率

可以通过配置文件

// jest.config.ts
// 主要涉及到这两个配置
export default {collectCoverage: true, // 启用coverageDirectory: "coverage", // 报告生成位置
}

通过cli,执行脚本时带上参数

➜ npx jest --coverage
测试覆盖率

假设我们有这么一个函数

export function whatType(arg: any) {const type = Object.prototype.toString.call(arg)if (type === '[object String]') {return 'string';} else if (type === '[object Boolean]') {return 'boolean';}
}

添加测试用例

import { whatType } from "@/utils";describe("测试覆盖率", () => {it("函数条件覆盖率", () => {expect(whatType(true)).toBe("boolean");});
});

执行测试用例

npm run testPASS  __tests__/demo.spec.ts测试覆盖率✓ 函数条件覆盖率 (1 ms)----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   96.77 |       50 |     100 |   96.77 |                   index.ts |   96.77 |       50 |     100 |   96.77 | 4                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.486 s, estimated 1 s
  • File:测试的文件
  • Stmts:测试中被执行的代码语句的比例
  • Branch:测试代码条件分支比例
  • Funcs:测试中被执行函数比例
  • Lines:测试中被执行代码行数比例
  • Uncovered Line:没有测试到的行数

除了查看终端的表格外,还可以使用更直观的报告,文件报告的结构大概如下:

coverage
├── clover.xml # xml格式
├── coverage-final.json # json格式
├── lcov-report # html格式
│   ├── base.css
│   ├── block-navigation.js
│   ├── favicon.png
│   ├── index.html # 主页面入口
│   ├── index.ts.html
│   ├── other.ts.html
│   ├── prettify.css
│   ├── prettify.js
│   ├── sort-arrow-sprite.png
│   └── sorter.js
└── lcov.info

一般都来查看HTML报告,打开报告页面

可以点击对应的文件查看更详细的报告

Vue组件测试

jest也可以对vue组件进行测试,vue官方提供了 vue2版本工具包(vue-test) 和 vue3版本工具包(@vue/test-utils),这里基于vue3组件进行测试

安装对应的依赖:

npm install @vue/test-utils -D

对于Jestv28+以上版本还需要添加以下配置:

// jest.config.ts
export default {testEnvironmentOptions: {customExportConditions: ["node", "node-addons"],},
}

创建一个简单的Button组件:

import { defineComponent } from "vue";export default defineComponent({render(){return <button>按钮</button>}
})

添加测试用例:

import { mount } from "@vue/test-utils";
import Button from "@/components/Button";test("测试vue组件", () => {const wrapper = mount({setup() {return () => {return <Button />;};},});expect(wrapper.text()).toBe('按钮')
})

运行测试

npm run testPASS  __tests__/demo.spec.tsx✓ 测试vue组件 (9 ms)------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |     100 |      100 |     100 |     100 |                   Button.tsx |     100 |      100 |     100 |     100 |                   
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.633 s

添加全局组件,当单测某个组件时,组件内部引用的其它组件会因为没有引用而报错,定义全局组件可以解决这个问题

// jest.setup.ts
import { config } from "@vue/test-utils";
import Button from "@/button/src/button";
import Icon from "@/button/src/icon";config.global.components = {Button,Icon,
};

配置jest

// jest.config.ts
export default {setupFiles: ["<rootDir>/jest.setup.ts"],
}

这里不对vue工具包API过多的解释,更多的API使用可以查看官方文档,vue2版本的可以查看这里

由于格式和图片解析问题,可前往 阅读原文

相关文章:

Jest单元测试

由于格式和图片解析问题&#xff0c;可前往 阅读原文 前端自动化测试在提高代码质量、减少错误、提高团队协作和加速交付流程方面发挥着重要作用。它是现代软件开发中不可或缺的一部分&#xff0c;可以帮助开发团队构建可靠、高质量的应用程序 单元测试&#xff08;Unit Testi…...

C++字符串处理指南:从基础操作到性能优化——基于std::string的全面解析

博主将从C标准库中的 std::string 出发&#xff0c;详细探讨字符串的处理方法&#xff0c;涵盖常见操作、性能优化和实际应用场景。以下内容将围绕std::string 的使用展开&#xff0c;结合代码示例进行说明。 一、std::string 的基本操作 1.1 创建与初始化 std::string 提供了…...

JVM类加载过程详解:从字节码到内存的蜕变之旅

一、类加载的意义与整体流程 在Java中&#xff0c;每一个.java文件经过编译都会生成.class字节码文件。但字节码本身并不能直接运行&#xff0c;必须通过 类加载&#xff08;Class Loading&#xff09;将其转化为JVM内存中的数据结构&#xff0c;才能被程序调用。 类加载过程就…...

【力扣Hot100详解】解锁“字母异位词分组”:用排序魔法一键通关力扣!

字母异位词分组&#xff0c;力扣第49题&#xff0c;看似是“找不同”的排列游戏&#xff0c;实则是哈希表与字符串处理的经典结合。这道题就像是一把钥匙&#xff0c;能帮你打开“如何高效归类数据”的算法大门。今天&#xff0c;我们就用 Java 带你用“排序魔法”轻松破解它&a…...

vite配置scss全局变量

vite配置scss全局变量 创建单独文件variable.scss在其中定义变量 vite.config.ts中配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import path from path// https://vite.dev/config/ export default defineConfig({plugins: [vue()],resolve:…...

Spring Boot01(注解、)---java八股

Spring Boot中常用注解及其底层实现 1、SpringBootApplication注解&#xff1a; SpringBootApplication注解&#xff1a;这个注解标识了一个SpringBoot工程&#xff0c;它实际上是另外三个注解的组合&#xff0c;这三个注解是&#xff1a; aSpringBootConfiguration&#xff1a…...

2.19学习记录

Web easyupload3.0 这是一道构造.htaccess文件的传马 如下&#xff1a; <FilesMatch "jpg">SetHandler application/x-httpd-php </FilesMatch>.htaccess文件可以作为一个解释器&#xff0c;可以将传进去的图片马改为php马上传之后再传个图片马&#…...

汽车免拆诊断案例 | 2013 款奔驰 S300L 车起步时车身明显抖动

故障现象  一辆2013款奔驰S300L车&#xff0c;搭载272 946发动机&#xff0c;累计行驶里程约为15万km。车主反映&#xff0c;将挡位置于D挡&#xff0c;稍微释放一点制动踏板&#xff0c;车辆蠕动时车身明显抖动&#xff0c;类似气缸失火时的抖动&#xff0c;又类似手动变速器…...

【HeadFirst系列之HeadFirst设计模式】第5天之工厂模式:比萨店的秘密武器,轻松搞定对象创建!

工厂模式&#xff1a;比萨店的秘密武器&#xff0c;轻松搞定对象创建&#xff01; 大家好&#xff0c;今天我们来聊聊设计模式中的工厂模式。如果你曾经为对象的创建感到头疼&#xff0c;或者觉得代码中到处都是 new 关键字&#xff0c;那么工厂模式就是你的救星&#xff01;本…...

Redis如何解决热Key问题

目录 **如何解决 Redis 的热 Key&#xff08;Hot Key&#xff09;问题&#xff1f;****解决方案** **1. 使用多级缓存****方案** **2. 进行 Key 预分片&#xff08;Key Sharding&#xff09;****方案** **3. 使用 Redis 复制机制&#xff08;主从复制或集群&#xff09;****方案…...

从开发到部署:EasyRTC嵌入式视频通话SDK如何简化实时音视频通信的集成与应用

嵌入式设备和视频综合管理平台均支持B/S架构。在B/S架构下&#xff0c;传统的视频观看方式依赖于微软的OCX控件&#xff0c;然而OCX控件的使用正面临越来越多的挑战&#xff1a; 首先&#xff0c;用户需要安装浏览器插件、调整浏览器安全级别&#xff0c;并允许ActiveX控件弹出…...

Zookeeper(58)如何在Zookeeper中实现分布式锁?

在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务&#xff0c;使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例&#xff0c;展示如何在 Zookeeper 中实现分布式锁。 1. Zookeeper 分布式锁的基本原理 Zookeep…...

Mac端homebrew安装配置

拷打了一下午o3-mini-high&#xff0c;不如这位博主的超强帖子&#xff0c;10分钟结束战斗 跟随该文章即可&#xff0c;2025/2/19亲测可行 mac 安装HomeBrew(100%成功)_mac安装homebrew-CSDN博客文章浏览阅读10w次&#xff0c;点赞258次&#xff0c;收藏837次。一直觉得自己写…...

Spring 接入 DeepSeek

引入依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>2.yml配置 spring:ai:openai:api-key: sk-xxxxx // 填写自己申请的keybase-url: http…...

vscode将文件中行尾默认CRLF改为LF

安装prettier npm install --save-dev --save-exact prettier执行命令 npx prettier --write --end-of-line lf .即可将项目中的所有文件行尾序列格式改为lf *在你使用git拉取代码的时候&#xff0c;git会自动将代码当中与你当前系统不同的换行方式转化成你当前系统的换行方…...

python-leetcode 33.排序链表

题目&#xff1a; 给定链表的头结点head,请将其按升序排列&#xff0c;并返回排序后的链表 方法一&#xff1a;自顶向下归并排序 链表自顶向下归并排序的过程&#xff1a; 1.找到链表的中点&#xff0c;以中点为分界&#xff0c;将链表拆分成两个子链表。寻找链表的中点可以…...

【数据结构初阶第十二节】设计循环队列

云边有个稻草人-CSDN博客 必须有为成功付出代价的决心&#xff0c;然后想办法付出这个代价。 还有最后一道关于队列的习题&#xff0c;这题有点难&#xff0c;准备好迎接挑战吧&#xff01; 目录 1.【题目】 2.实现循环队列推荐用数组&#xff0c;Why? 3.Q1&#xff1a;如…...

基于微信小程序的民宿短租系统设计与实现(ssm论文源码调试讲解)

第4章 系统设计 4.1系统设计的目标 系统设计的目标是满足用户的需求和满足系统实现所需要的所有要求。本系统收集了信息浏览、信息删除、信息添加、信息修改、信息查询为一体[17]。改变了用户民宿短租的方式&#xff0c;提高管理员管理效率以及用户预订的效率。为用户、房主提…...

使用 Jetty 构建 HTTPS 服务入门指南

在互联网安全越来越重要的今天,使用 HTTPS 为 Web 服务提供安全传输成为标准配置。Jetty 是一个高性能、易用且功能丰富的开源 Java HTTP 服务器和 Servlet 容器,能够轻松实现 HTTPS 支持。本文将结合代码实例,引导您快速搭建一个基于 Jetty 的 HTTPS 服务。 一、Jetty 简介…...

数据结构《图》

数据结构《图论》 图的性质 一、无向图&#xff08;Undirected Graph&#xff09; 定义 由一组顶点&#xff08;Vertex&#xff09;和一组无向边&#xff08;Edge&#xff09;构成。 每条无向边用一条无方向的线段连接两个顶点&#xff0c;记为 ( (u, v) )&#xff0c;其中…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...