【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现
项目搭建
-
创建项目
# 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js}
- 使用
npx create-react-app
创建项目,进入项目目录后通过npm start
启动。 - 调整项目目录结构,包括
apis
、assets
、components
、pages
等多个文件夹。
- 使用
-
使用技术
- 接入
scss
预处理器,安装sass
工具,创建全局样式文件index.scss
。# 安装sass工具 npm i sass -D
// 在src/index.scss中设置全局样式 body {font-family: Arial, sans-serif;background-color: #f4f4f4; }
- 引入组件库
antd
,安装后在Login
页面测试Button
组件。# 安装antd组件库 npm i antd
// 在src/pages/Login/index.jsx中使用Button组件 import React from 'react'; import { Button } from 'antd';const Login = () => {return (<div><Button type='primary'>登录</Button></div>); };export default Login;
- 使用
react-router-dom
配置基础路由,创建Layout
和Login
组件并配置路由规则。# 安装react-router-dom npm i react-router-dom
// 在src/router/index.js中配置路由 import { createBrowserRouter } from 'react-router-dom'; import Login from '../pages/Login'; import Layout from '../pages/Layout';const router = createBrowserRouter([{path: '/',element: <Layout />,},{path: '/login',element: <Login />,}, ]);export default router;
- 通过
craco
工具包配置别名路径,在craco.config.js
中设置webpack
别名,并在jsconfig.json
中配置VsCode
提示。# 安装craco工具包 npm i @craco/craco -D
// 在craco.config.js中配置别名 const path = require('path'); module.exports = {webpack: {alias: {'@': path.resolve(__dirname,'src')}} };
// 在package.json中修改scripts命令 "scripts": {"start": "craco start","build": "craco build","test": "craco test","eject": "react-scripts eject" }
// 在src/router/index.js中使用别名 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout';const router = createBrowserRouter([{path: '/',element: <Layout />,},{path: '/login',element: <Login />,}, ]);export default router;
// 在jsconfig.json中配置VsCode提示 {"compilerOptions": {"baseUrl": "./","paths": {"@/*": ["src/*"]}} }
- 接入
-
功能模块实现
-
登录模块
-
基本结构搭建
-
-
- 在
Login/index.js
创建登录页面结构,引入antd
组件,使用@/assets
路径引入图片,在Login/index.scss
中设置样式。 -
import React from 'react'; import { Card, Form, Input, Button } from 'antd'; import logo from '@/assets/logo.png'; import './index.scss';const Login = () => {return (<div className="login"><Card className="login-container"><img className="login-logo" src={logo} alt="" /><Form><Form.Item><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Item><Input size="large" placeholder="请输入验证码" /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form></Card></div>); };export default Login;
-
表单校验实现
- 为
Form
组件设置validateTrigger
,为Form.Item
组件设置name
和rules
属性进行表单校验。import React from 'react'; import { Form, Input, Button } from 'antd';const Login = () => {return (<Form validateTrigger={['onBlur']}><Form.Itemname="mobile"rules={[{ required: true, message: '请输入手机号' },{pattern: /^1[3-9]\d{9}$/,message: '手机号码格式不对'}]}><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Itemname="code"rules={[{ required: true, message: '请输入验证码' },]}><Input size="large" placeholder="请输入验证码" maxLength={6} /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form>); };export default Login;
- 为
-
获取登录表单数据
- 为
Form
组件设置onFinish
属性,在点击登录按钮时触发获取表单数据的函数。import React from 'react'; import { Form, Input, Button } from 'antd';const Login = () => {const onFinish = formValue => {console.log(formValue);};return (<Form onFinish={onFinish}><Form.Item><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Item><Input size="large" placeholder="请输入验证码" /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form>); };export default Login;
- 为
-
封装 request 工具模块
- 安装
axios
,在utils/request.js
中创建axios
实例,配置baseURL
、请求拦截器和响应拦截器。# 安装axios npm i axios
import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });// 请求拦截器 http.interceptors.request.use(config => {return config; }, error => {return Promise.reject(error); });// 响应拦截器 http.interceptors.response.use(response => {return response.data; }, error => {return Promise.reject(error); });export { http };
- 安装
-
使用 Redux 管理 token
- 安装
react-redux
和@reduxjs/toolkit
,在store
中创建userStore
切片,设置token
初始状态和setUserInfo
等reducers
,封装fetchLogin
异步方法。# 安装react-redux和@reduxjs/toolkit npm i react-redux @reduxjs/toolkit
import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils';const userStore = createSlice({name: 'user',initialState: {token: ''},reducers: {setUserInfo(state, action) {state.token = action.payload;}} });const { setUserInfo } = userStore.actions; const userReducer = userStore.reducer;const fetchLogin = loginForm => {return async dispatch => {const res = await http.post('/authorizations', loginForm);dispatch(setUserInfo(res.data.token));}; };export { fetchLogin }; export default userReducer;
- 安装
-
实现登录逻辑
- 在
Login
组件中调用fetchLogin
方法,登录成功后跳转到首页并提示。import React from 'react'; import { message } from 'antd'; import { useDispatch } from 'react-redux'; import { fetchLogin } from '@/store/modules/user';const Login = () => {const dispatch = useDispatch();const onFinish = async formValue => {await dispatch(fetchLogin(formValue));message.success('登录成功');};return (<div><form onSubmit={onFinish}>{/* 登录表单字段 */}</form></div>); };export default Login;
- 在
-
token 持久化
- 封装
setToken
、getToken
和clearToken
方法,在userStore
中setUserInfo
时将token
存入本地。// 在@/utils/token.js中封装存取方法 const TOKENKEY = 'token_key';function setToken(token) {return localStorage.setItem(TOKENKEY, token); }function getToken() {return localStorage.getItem(TOKENKEY); }function clearToken() {return localStorage.removeItem(TOKENKEY); }export {setToken,getToken,clearToken };
// 在userStore中使用token持久化方法 import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils'; import { getToken, setToken } from '@/utils/token';const userStore = createSlice({name: 'user',initialState: {token: getToken() || ''},reducers: {setUserInfo(state, action) {state.token = action.payload;setToken(state.token);}} });export default userStore;
- 封装
-
请求拦截器注入 token
- 在
request.js
的请求拦截器中,判断是否有token
,有则添加到请求头Authorization
中。// 在utils/request.js中注入token import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });http.interceptors.request.use(config => {const token = getToken();if (token) {config.headers.Authorization = `Bearer ${token}`;}return config; }, error => {return Promise.reject(error); });http.interceptors.response.use(response => {return response.data; }, error => {return Promise.reject(error); });export { http };
- 在
-
路由鉴权实现
- 在
components/AuthRoute/index.jsx
中创建路由鉴权高阶组件,判断本地是否有token
,决定是否重定向到登录页面。import React from 'react'; import { Navigate } from 'react-router-dom'; import { getToken } from '@/utils';const AuthRoute = ({ children }) => {const isToken = getToken();if (isToken) {return <>{children}</>;} else {return <Navigate to="/login" replace />;} };export default AuthRoute;
// 在src/router/index.js中使用AuthRoute组件 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout'; import AuthRoute from '@/components/AuthRoute';const router = createBrowserRouter([{path: '/',element: <AuthRoute><Layout /></AuthRoute>,},{path: '/login',element: <Login />,}, ]);export default router;
- 在
-
Layout 模块
-
基本结构和样式 reset
- 在
pages/Layout/index.js
中使用antd/Layout
组件创建页面结构,引入antd
的Menu
和Popconfirm
等组件,设置样式并安装normalize.css
进行样式 reset。import React from 'react'; import { Layout, Menu, Popconfirm } from 'antd'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons'; import './index.scss'; import 'normalize.css';const { Header, Sider } = Layout;const items = [{label: '首页',key: '1',icon: <HomeOutlined />,},{label: '文章管理',key: '2',icon: <DiffOutlined />,},{label: '创建文章',key: '3',icon: <EditOutlined />,}, ];const GeekLayout = () => {return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">用户名</span><span className="user-logout"><Popconfirm title="是否确认退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"defaultSelectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}>内容</Layout></Layout></Layout>); };export default GeekLayout;
- 在
-
二级路由配置
- 在
pages
目录创建Home
、Article
、Publish
页面文件夹,在router/index.js
中配置嵌套子路由,在Layout
中配置二级路由出口,使用Link
修改左侧菜单内容实现路由切换。// 在pages目录创建Home.jsx import React from 'react';const Home = () => {return <div>首页内容</div>; };export default Home;
// 在pages目录创建Article.jsx import React from 'react';const Article = () => {return <div>文章管理内容</div>; };export default Article;
// 在pages目录创建Publish.jsx import React from 'react';const Publish = () => {return <div>发布文章内容</div>; };export default Publish;
// 在src/router/index.js中配置二级路由 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout'; import Publish from '@/pages/Publish'; import Article from '@/pages/Article'; import Home from '@/pages/Home'; import { AuthRoute } from '@/components/AuthRoute';const router = createBrowserRouter([{path: '/',element: (<AuthRoute><Layout /></AuthRoute>),children: [{index: true,element: <Home />,},{path: 'article',element: <Article />,},{path: 'publish',element: <Publish />,},],},{path: '/login',element: <Login />,}, ]);export default router;
// 在Layout组件中配置二级路由出口 import React from 'react'; import { Outlet } from 'react-router-dom';const GeekLayout = () => {return (<Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout>); };export default GeekLayout;
- 在
-
路由菜单点击交互实现
- 为
Menu
组件设置onClick
属性实现点击菜单跳转路由,通过useLocation
获取当前路由路径实现菜单反向高亮。import React from 'react'; import { Outlet, useNavigate } from 'react-router-dom'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons';const items = [{label: '首页',key: '/',icon: <HomeOutlined />,},{label: '文章管理',key: '/article',icon: <DiffOutlined />,},{label: '创建文章',key: '/publish',icon: <EditOutlined />,}, ];const GeekLayout = () => {const navigate = useNavigate();const menuClick = route => {navigate(route.key);};return (<Layout><Header className="main-header"><div className="logo" /><div className="user-info"><span className="user-name">用户名</span><span className="user-logout"><Popconfirm title="是否确认退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"selectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}onClick={menuClick}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout></Layout>); };export default GeekLayout;
// 菜单反向高亮实现 import React from 'react'; import { Outlet, useLocation } from 'react-router-dom'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons';const items = [{label: '首页',key: '/',icon: <HomeOutlined />,},{label: '文章管理',key: '/article',icon: <DiffOutlined />,},{label: '创建文章',key: '/publish',icon: <EditOutlined />,}, ];const GeekLayout = () => {const location = useLocation();const selectedKey = location.pathname;return (<Layout><Header className="main-header"><div className
- 为
-
展示个人信息
- 在
store/userStore.js
中编写获取用户信息的逻辑,在Layout
组件中触发fetchUserInfo
方法获取信息并渲染用户名。// store/userStore.js import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils'; import { getToken, setToken } from '@/utils';const userStore = createSlice({name: 'user',initialState: {token: getToken() || '',userInfo: {}},reducers: {setUserToken(state, action) {state.token = action.payload;setToken(state.token);},setUserInfo(state, action) {state.userInfo = action.payload;},clearUserInfo(state) {state.token = '';state.userInfo = {};clearToken();}} });// 解构出actionCreater const { setUserToken, setUserInfo, clearUserInfo } = userStore.actions; // 获取reducer函数 const userReducer = userStore.reducer;const fetchLogin = (loginForm) => {return async (dispatch) => {const res = await http.post('/authorizations', loginForm);dispatch(setUserToken(res.data.token));}; };const fetchUserInfo = () => {return async (dispatch) => {const res = await http.get('/user/profile');dispatch(setUserInfo(res.data));}; };export { fetchLogin, fetchUserInfo, clearUserInfo }; export default userReducer;
- 在
-
退出登录实现
- 为
Popconfirm
添加确认回调事件,在store/userStore.js
中新增clearUserInfo
方法删除token
和用户信息,在回调事件中调用该方法并返回登录页面。// pages/Layout/index.js import React, { useEffect } from 'react'; import { Layout, Menu, Popconfirm } from 'antd'; import {HomeOutlined,DiffOutlined,EditOutlined,LogoutOutlined, } from '@ant-design/icons'; import { useDispatch, useSelector } from 'react-redux'; import { fetchUserInfo } from '@/store/modules/user';const { Header, Sider } = Layout;const items = [// 菜单配置项 ];const GeekLayout = () => {const dispatch = useDispatch();const name = useSelector(state => state.user.userInfo.name);useEffect(() => {dispatch(fetchUserInfo());}, [dispatch]);const loginOut = () => {dispatch(clearUserInfo());// 假设这里有合适的导航函数,替换为实际的导航逻辑// navigate('/login'); };return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">{name}</span><span className="user-logout"><Popconfirmtitle="是否确认退出?"okText="退出"cancelText="取消"onConfirm={loginOut}><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"defaultSelectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}>{/* 页面内容 */}</Layout></Layout></Layout>); };export default GeekLayout;
- 为
-
处理 Token 失效
- 在
http.interceptors.response
中判断响应状态码为401
时,清除token
,跳转到登录页面并刷新页面。// 在http.js(假设是配置axios请求相关的文件)中处理Token失效 import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });http.interceptors.response.use((response) => {return response.data; }, (error) => {if (error.response && error.response.status === 401) {// 假设这里有合适的获取和清除token的函数,替换为实际的逻辑const token = getToken();if (token) {clearToken();}// 假设这里有合适的导航函数,替换为实际的导航逻辑// navigate('/login'); window.location.reload();}return Promise.reject(error); });export { http };
- 在
-
相关文章:
【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现
项目搭建 创建项目 # 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js} 使用npx create-react-app创建项目࿰…...

CMake 属性之目录属性
【写在前面】 CMake 的目录属性是指在特定目录(及其子目录)范围内有效的设置。 这些属性不同于全局变量或目标(Target)属性,它们提供了一种机制,允许开发者为项目中的不同部分定义不同的构建行为。 通过目录…...

ChatGPT:引领人工智能新潮流!
一、ChatGPT 是什么? 1. ChatGPT 的强大功能和广泛应用。 ChatGPT 作为一款先进的 AI 语言模型,拥有众多强大功能。它可以进行文本生成、文本分类、情感分析、机器翻译等多种自然语言处理任务。同时,ChatGPT 还能进行对话式交互,…...

【银河麒麟高级服务器操作系统】安全配置基线相关分析全过程及解决方案
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 服务器环境以及配置 【机型】物理机或虚机 【…...
用Python实现图片转ASCII艺术:图像处理与字符艺术的完美结合
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 ASCII艺术是一种通过字符来表现图像的艺术形式,最早用于早期计算机显示器,它仅支持字符显示。如今,尽管图像分辨率和显示技术得到了极大的提升,ASCII艺术作为一种复古而别具一格的图像表现形式,仍然受到许多…...

大数据-162 Apache Kylin 全量增量Cube的构建 Segment 超详细记录 多图
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

Redis-缓存过期淘汰策略
缓存淘汰策略 生产上redis内存设置为多少 设置为最大内存的 3/4 redis 会占用物理机多少内存 默认大小是 0,64 位系统下表示不限制内存大小,32位系统表示 3G 如何设置修改redis内存大小 config get maxmemory 查看修改方式 配置文件 单位是字节 2.…...

如何设置LED电子显示屏的屏幕参数?
LED电子显示屏因其高亮度、低能耗和长寿命等优点,在广告、信息显示等领域得到了广泛应用。正确设置屏幕参数对于确保显示屏的最佳性能至关重要。以下是LED电子显示屏设置屏幕参数的步骤: 1. 确定屏幕参数 在开始设置之前,需要了解显示屏的基本…...

Spring Boot Starter Parent介绍
引言 spring-boot-starter-parent 是一个特殊的项目,为基于 Spring Boot 的应用程序提供默认配置和默认依赖。 在本 Spring Boot 教程中,我们将深入了解所有 Spring Boot 项目内部使用的 spring-boot-starter-parent 依赖项。我们将探讨此依赖项所提供…...

【含开题报告+文档+PPT+源码】基于SpringBoot乡村助农益农平台的设计与实现
开题报告 近年来,随着社会经济的快速发展和人民生活水平的提高,人们对优质农产品的需求越来越高。然而,传统的农产品销售管理模式存在一些问题。首先,农产品供应链信息不透明,导致生产者难以了解市场需求和价格变动趋…...

数据中心运维挑战:性能监控的困境与智能化解决方案的探寻
随着数字化进程的加速,数据中心已成为企业信息架构的核心支撑,其运维管理的复杂度和重要性也随之提升。运维团队需应对设备老化、资源分配失衡、性能波动等多重难题,以确保数据中心持续高效运行。 其中,性能监控作为运维管理的关键…...

基于SSM的民宿管理系统【附源码】
基于SSM的民宿管理系统(源码L文说明文档) 目录 4 系统设计 4.1 系统概要设计 4.2 系统功能结构设计 4.3 数据库设计 4.3.1 数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1用户信息管理 5.2 房东信息管理…...

显卡 3090 vs v100
1.3090 Date: 2020 AmperePielines/ Cuda cores: 10496 2.V100 Date: 2018 VoltaPielines/ Cuda cores: 5129 3.结构 & Core比较: v100优点: v100功耗小v100较快的双精度(fp64)和混合精度(fp16fp32)pcie版的NVLink与2080ti完全一致 v100缺点: 不支持整数格式计算&…...

怎么在单片机裸机程序中移植EasyLogger?
1、介绍 EasyLogger 是一款超轻量级、高性能的C日志库,非常适合对资源敏感的软件项目。例如:IoT产品、可穿戴设备、智能家居等等。相比log4c、zlog这些知名的C日志库,EasyLogger的功能更加简单,提供给用户的接口更少,但…...
C/C++解析文件名和目录路径
文章目录 主要函数使用注意事项示例程序总结 #include <libgen.h> 是一个 C/C 语言的头文件,主要用于字符串处理,特别是在处理文件路径时。它提供了一些函数来帮助你解析文件名和目录路径。 主要函数 以下是 libgen.h 中一些常见的函数ÿ…...
Git 基本命令行操作
Git是一个开源的分布式版本控制系统,用于管理源代码和文档的版本。以下是Git的基本命令行操作: 一、配置 安装完成后,需要配置Git的用户名和邮箱,以便在提交记录时记录操作者的信息。 配置全局用户名:git config --g…...
【Rust练习】17.泛型
练习题来自:https://practice-zh.course.rs/generics-traits/generics.html 函数 1 // 填空 struct A; // 具体的类型 A. struct S(A); // 具体的类型 S. struct SGen<T>(T); // 泛型 SGen.fn reg_fn(_s: S) {}fn gen_spec_t(_s: SGen<A&…...

java脚手架系列4--测试用例、拦截器
异常处理、拦截器、数据库连接 1 测试用例 单元测试是一个老生常谈的问题,无论是后端对自己的代码质量把的第一道关也好,也是对测试减缓压力。这里就不过多讲述测试用例的重要性,但是有2个框架我们必须了解一下。 1.1 JUnit和mockito 我们…...
论文推荐 |【Agent】自动化Agent设计系统
论文标题: Automated Design of Agentic Systems 论文地址: https://arxiv.org/abs/2408.08435 GitHub地址: https://github.com/ShengranHu/ADAS 自动化代理设计在性能和通用性方面显著超越了手动方法。 • 引入了自动化代理系统设计&am…...
Linux操作系统提供了五种主要的IO(输入/输出)模型
Linux操作系统提供了五种主要的IO(输入/输出)模型,这些模型旨在优化应用程序对输入输出操作的管理和处理。以下是关于这五种IO模型的详细介绍。 一、阻塞IO(Blocking IO) 阻塞IO是最常见、最传统的IO模型。在这种模型…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...