用React给XXL-JOB开发一个新皮肤(四):实现用户管理模块

目录

  • 一. 简述
  • 二. 模块规划
    • 2.1. 页面规划
    • 2.2. 模型实体定义
  • 三. 模块实现
    • 3.1. 用户分页搜索
    • 3.2. Modal 配置
    • 3.3. 创建用户表单
    • 3.4. 修改用户表单
    • 3.5. 删除
  • 四. 结束语

一. 简述

上一篇文章我们实现登录页面和管理页面的 Layout 骨架,并对接登录和登出接口。这篇文章我们将实现用户管理的模块和相应的接口。最后效果如下:
在这里插入图片描述

二. 模块规划

在开发之前我们需要对 xxl-job管理系统的用户模块进行规划。

2.1. 页面规划

一般我们都是从前端页面需要使用什么组件;后端接口需要哪些?
在这里插入图片描述
前端使用的组件:表格、分页、下拉框、输入框和按钮,就是一个很普通的 CRUD 管理页面,比较简单;接口也是围绕这些功能的:分页查询接口、创建用户接口、编辑用户接口和删除接口。

2.2. 模型实体定义

接着我们需要定义下前后端交互会使用的到的请求和响应实体的定义。

首先是用户分页查询接口的请求和响应:

// UserPageQueryProp 用户分页查询请求参数定义
export interface UserPageQueryProp {page: number;      // 页码size: number;      // 页大小role: number;      // 角色 IDusername?: string;  // 用户名称
}// UserTableProp 用户分页查询返回参数定义
export interface UserTableProp {id: number;         // 用户IDusername: string;   // 用户名称role: number;       // 角色permission: string; // 权限
}

这里需要注意的是虽然我们表格中只有用户名和角色名两个显示属性,但是考虑到在编辑的时候需要根据角色显示权限信息,这里在分页查询中返回用户的权限数据。但是如果在一些复杂的分页表格中,不建议这样操作!

接着是用户创建和编辑的请求的定义:

// UserTableProp 用户创建表单属性
export interface UserCreateFormProp {username: string;     // 用户名称password: string;     // 密码role: number;         // 角色permission: string[]; // 权限
}// UserUpdateFormProp 用户创建表单属性
export interface UserUpdateFormProp extends UserCreateFormProp{id: number;           // 用户ID
}

三. 模块实现

从这个模块我们可以分为两个大部分和三个小组件组成。
在这里插入图片描述
其中功能部分我们可以使用 antdSpace 中嵌套表单组件实现;表格可以使用 Table 组件(这个组件自带分页功能)实现;最后创建和编辑按钮我们使用 Modal 组件中嵌套 Form 表单组件实现就可以了。下面我们按功能一个个实现这个用户模块。

这里我们在使用 TS 这个 Buff 的使用,大部分使用需要申明类型,尤其在使用不熟悉的 UI 组件库的时候,大家需要多读文章,多看组件定义文件或者源码。

3.1. 用户分页搜索

上面我们分析我们要使用组件,这里就不赘述了,直接上代码:

import {Button, Divider, Input, Select, Space, Table, Tag} from "antd";
import React, {useEffect, useState} from "react";
import {User} from "@/types";
import {ColumnsType} from "antd/es/table";
import {useRequest} from "ahooks";
import UserApi from "@/api/user.ts";
import {ClearOutlined, PlusOutlined, SearchOutlined} from "@ant-design/icons";const UserPage = () => {// 定义列信息const columns: ColumnsType<User.UserTableProp> = [{title: '账号',key: 'username',dataIndex: 'username',align: 'center'},{title: '角色',key: 'role',dataIndex: 'role',align: 'center',render: (_, record) => record.role == 1 ? <Tag color="#f50">管理员</Tag> : <Tag color="#2db7f5">普通用户</Tag>},{title: '操作',key: 'active',align: 'center',width: 200,render: (_, record) => <Space><Button type="primary" onClick={() => openEdit(record.id)}>编辑</Button><Button type="primary" danger onClick={() => deleteUser(record.id)}>删除</Button></Space>,},]// 总条数const [total, setTotal] = useState<number>(0);const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);// 用户数据const [datasource, setDatasource] = useState<User.UserTableProp[]>([]);// 分页查询属性const [pageQuery, setPageQuery] = useState<User.UserPageQueryProp>(defaultUserPageQuery());return <div><Space><Button type="primary" icon={<PlusOutlined />}>增加用户</Button><Divider type="vertical"/><div>角色:</div><SelectonChange={e => setPageQuery({...pageQuery, role: e})}placeholder="选择状态"defaultValue={-1}style={{width: 100}}options={[{value: -1, label: '全部'},{value: 1, label: '管理员'},{value: 0, label: '普通用户'}]}/><div style={{marginLeft: 20}}>用户名称:</div><InputallowClearplaceholder="请输入搜索的用户名称"value={pageQuery.username}onChange={e => setPageQuery({...pageQuery, username: e.target.value})} /><Button danger type='primary' icon={<ClearOutlined />} onClick={clearSearch}>清空</Button><Button type='primary' icon={<SearchOutlined />} onClick={() => loadUser.run(pageQuery)}>搜索</Button></Space><Tableborderedsize={'small'}columns={columns}loading={loadUser.loading}dataSource={datasource}style={{ marginTop: 10 }}rowKey={(record) => record.id}pagination={{onShowSizeChange: (current, size) => loadUser.run({...pageQuery, page: current, size: size}),onChange: (page, pageSize) => loadUser.run({...pageQuery, page: page, size: pageSize}),showTotal: () => `${total}`,showQuickJumper: true,showSizeChanger: true,pageSize: pageQuery.size,current: pageQuery.page,size: 'default',total: total,}}rowSelection={{type: 'checkbox',selectedRowKeys: selectedRowKeys,onChange: (selectedRowKeys: React.Key[]) => {setSelectedRowKeys([...selectedRowKeys.map(item => item as number)])}}}/></div>
}export default UserPage;

这里我们需要注意一下几点:

  • 表格每一个行都需要一个 Key,默认是 React.Key,但是如果我们需要自定义的时候,可以使用rowKey={(record) => record.id}定义自己的 rowKey,这里的 record 就是定义表格属性模型:User.UserTableProp
  • 关于分页属性我们可以通过pagination属性进行设置,可以设置属性和方法可以在分页组件文章中看到
  • 最后一点就是关于表格行选中可以通过rowSelection属性设置;

接下来我们就需要对接分页查询的接口了,首先我们在 api/user.ts 中添加用户分页接口 api 定义:

/*** 用户分页* @param param* @constructor*/
export const UserPage = (param: User.UserPageQueryProp): Promise<PageData<User.UserTableProp>> => {return https.request({url: '/user/pageList',method: 'post',data: param})
}

接着我们看一下如何使用这个api,并且了解下ahooks 中的useRequest中非常好用的地方。

// 加载用户列表
const loadUser = useRequest(UserApi.UserPage, {manual: true, // 手动调用onSuccess: ({records, total}) => { // 成功之后执行的操作setTotal(total);setDatasource(records);}
});

最后我们配合 useEffect使用,加载用户列表的接口会在加载用户管理页面的时候调用这个接口。

useEffect(() => {loadUser.run(pageQuery)
}, [])

这里我们介绍 ahooks 中的 useRequest这个工具 hooks

在这里插入图片描述
支持的功能很多,这里我们现使用这里的 loading 返回值。在我们请求接口的时候如果遇到网络抖动之类的加载缓慢的情况,让表格出现一个加载状态的图标是非常友好了,不然用户也很懵逼。在上面antd 提供了加载属性loading={loadUser.loading}我们只需要将这个值的变化交给 useRequest 就可以,完全不需要我们手动控制。

接下来我们实现上面搜索的功能。
在这里插入图片描述
这里一个是下拉框一个是输入框,我们直接使用的是 antd 的组件,我们仅需要实现清空输入和搜索两个按钮事件就可以了。对于清空搜索的点击事件,我们只需要将下拉选项设置为默认值,输入框清空就可以了,代码如下 :

// 清空搜索
const clearSearch = () => {setPageQuery({...pageQuery, role: -1, username: ""})
}

对于搜索我们仅需要手动调用分页接口就可以了,代码如下:

<Button type='primary' icon={<SearchOutlined />} onClick={() => loadUser.run(pageQuery)}
>搜索</Button>

3.2. Modal 配置

这个用户管理的部分需要用到创建用户和编辑用户两个功能,在xxl-job中都是都通过打开弹窗进行操的,我们这里也是使用相同的逻辑。这里我们使用 antdModal 组件。在使用这个组件的时候我们需要对 Modal 组件的打开和关闭进行一个统一的控制。

// UserCreateModelProp 创建用户弹窗属性
export interface UserCreateModalProp {visible: boolean;close: (isLoad: boolean) => void; // 关闭模态框
}// UserUpdateFormProp 用户更新表单属性
export interface UserUpdateFormProp {id: number;           // 用户IDpassword: string;     // 密码role: number;         // 角色permission: string[]; // 权限
}// 定义模态框的类型
export type ModalType = "create" | "update";// UserModelProp 用户模态框汇总属性
export interface UserModalProp {createVisible: boolean;    // 创建用户模态框打开标识updateVisible: boolean;    // 编辑用户模态框打开标识userData?: UserTableProp;  // 编辑是存放被编辑用户信息
}

接着我们分别定义打开和关闭模态框的事件:

// 关闭模态框
const closeModal = (isLoad: boolean) => {// 在全局只能有一个弹窗打开,所以在关闭的时候把标识变量都设为 false 就可以了setUserModelProp({createVisible: false, updateVisible: false, userData: undefined})if(isLoad) {// 如果创建和编辑成功,我们需要重新加载表格数据显示最新的数据loadUser.run(pageQuery)}
}// 打开模态框
const openModal = (types: User.ModalType, data?: User.UserTableProp) => {switch (types) {case "create":setUserModalProp({createVisible: true, updateVisible: false});break;case "update":setUserModalProp({updateVisible: true, createVisible: false, userData: data});break;default:break}
}

最后我们在创建和编辑按钮上使用这些事件就可以了:

<Button type="primary" icon={<PlusOutlined />} onClick={() => openModal('create')}>增加用户</Button><Button type="primary" onClick={() => openModal('update', record)}>编辑</Button>

接着我们定一个模态框组件,在当前目录下创建 create.tsxupdate.tsx 文件,这两个文件分别是创建用户和编辑用户模态框组件(子组件)。

import {Modal} from "antd";
import React from "react";
import {User} from "@/types";const CreateUserModal: React.FC<User.UserCreateModalProp> = ({visible, close}) => {const submitForm = () => {close(true)}return <Modaltitle="创建用户"open={visible}onOk={submitForm}onCancel={() => close(false)}><h1>创建用户</h1></Modal>
}export default CreateUserModal;

编辑类似不做展示了

这两个子组件设置组件之间的传值问题,我们在User.UserCreateModalProp定义了创建用户模态框组件需要的参数:visible变量和 close函数。最后我们在 index.tsx 中使用这个子组件就可以了。

// 存放模态框状态值
const [userModalProp, setUserModalProp] = useState<User.UserModalProp>({createVisible: false, updateVisible: false});<CreateUserModalkey="create"close={closeModal}  // 模态框关闭事件visible={userModalProp.createVisible} // 创建用户模态框打开状态标识变量
/>

效果如下:
在这里插入图片描述

3.3. 创建用户表单

这里我们接着实现创建用户表单和表单提交的相关部分,直接上代码:

推荐先看看 antdForm 组件的文章。

import {Checkbox, Divider, Empty, Form, Input, message, Modal, Radio, Row, Spin, Tag} from "antd";
import React, {useEffect, useState} from "react";
import {Group, User} from "@/types";
import {useRequest} from "ahooks";
import {GroupApi, UserApi} from "@/api/index.ts";
import styled from "@emotion/styled";const CreateUserModal: React.FC<User.UserCreateModalProp> = ({visible, close}) => {// 表单const [form] = Form.useForm<User.UserCreateFormProp>();// 监听表单 role 的 valueconst roleValue = Form.useWatch('role', form);// 执行器列表const [groups, setGroups] = useState<Group.JobGroupListProp[]>([]);// 执行器请求const groupLoader = useRequest(GroupApi.GroupLists, {manual: true, onSuccess: (data) => {setGroups(data);}})// 创建用户请求const createLoader = useRequest(UserApi.CreateUser, {manual: true, onSuccess: () => {message.success('创建用户成功')close(true)}});const submitForm = () => {form.validateFields().then(value => {// console.log("submit => ", value)if (value.role == 1) {value.permission = []}createLoader.run(value);})}// 监听 visible 打开关闭标识useEffect(() => {if (visible) { // 当创建用户模态框打开,请求执行器列表接口并设置角色默认值为普通用户groupLoader.run();form.setFieldValue('role', 0)} else {// 关闭模态框的时候,将表单置为空并将执行器列表设置为空数组form.resetFields();setGroups([]);}}, [visible])return <Controllertitle="创建用户"maskClosablewidth={500}open={visible}onOk={submitForm}onCancel={() => close(false)}><Spin tip="加载中......" spinning={createLoader.loading}><Form form={form} layout="vertical" name="form_create_modal"><Form.Item name="username" label="账号" rules={[{ required: true, message: '请输入账号' }]}><Input placeholder="请输入账号" /></Form.Item><Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item><Form.Item name="role" label="角色"><Radio.Group><Radio value={0}>普通用户</Radio><Radio value={1}>管理员</Radio></Radio.Group></Form.Item>{roleValue === 0 && <Form.Item name="permission" label="权限">{groups.length > 0 ? <Checkbox.Group className="xxl-job-list">{groups.map(item =><Row key={item.id}><Checkbox value={item.appName}>{item.title}<Divider type="vertical" /><Tag color="lime">{item.appName}</Tag></Checkbox></Row>)}</Checkbox.Group> : <Empty />}</Form.Item>}</Form></Spin></Controller>
}const Controller = styled(Modal)`.ant-modal-body {padding-top: 24px;.xxl-job-list {flex-direction: column;}}
`export default CreateUserModal;

这里我们通过 Modal 包裹表单组件,使用 useEffect监听 visible属性,当前模态框打开的时候,需要请求执行器列表,并设置角色默认值。

还需要注意的一个点是,当角色是管理员的时候,是不需要选择执行器的,所有在切换角色为管理员的时候,需要将之前选中的执行器清空;所以在最后提交用户数据的时候,设置下执行器就可以了。

const submitForm = () => {form.validateFields().then(value => {if (value.role == 1) { // 当角色是管理员的时候,将执行器权限设置为空数据value.permission = []}createLoader.run(value);})
}

此外我们还通过 styled 修改了 Modal 组件的样式,主要是为了将多选框flex 布局从 row 改为 column

// 使用 styled 包裹 Modal 组件
const Controller = styled(Modal)`.ant-modal-body {padding-top: 24px;.xxl-job-list {flex-direction: column;}}
`

3.4. 修改用户表单

有了上面创建用户表单部分,我们在修改用户信息的时候,仅需要了解表单初始化的问题了;这里我们也是用使用Form.setFieldsValue方法进行初始化表单,代码代码:

useEffect(() => {if (visible && data) {groupLoader.run();form.setFieldsValue({id: data.id, username: data.username, role: data.role, permission: data.permission})} else {form.resetFields();setGroups([]);}
}, [visible])

这里还有一个不一样的地方是我们会设置一个隐藏的用户主键,方便我们后面执行更新的时候确定要被更新用户信息:

<Controllertitle="更新用户"maskClosablewidth={500}open={visible}onOk={submitForm}onCancel={() => close(false)}><Spin tip="加载中......" spinning={updateLoader.loading}><Form form={form} layout="vertical" name="form_update_modal">// 不显示主键,在我们提交数据的时候会反给form.validateFields().then(value => {})中<Form.Item name="id" label="主键" style={{display: 'none'}}><Input /></Form.Item><Form.Item name="username" label="账号"><Input placeholder="请输入账号" readOnly /></Form.Item><Form.Item name="password" label="密码"><Input.Password placeholder="请输入新密码,为空则不更新密码" /></Form.Item><Form.Item name="role" label="角色"><Radio.Group><Radio value={0}>普通用户</Radio><Radio value={1}>管理员</Radio></Radio.Group></Form.Item>{roleValue === 0 && <Form.Item name="permission" label="权限">{groups.length > 0 ? <Checkbox.Group className="xxl-job-list">{groups.map(item =><Row key={item.id}><Checkbox value={item.appName}>{item.title}<Divider type="vertical" /><Tag color="lime">{item.appName}</Tag></Checkbox></Row>)}</Checkbox.Group> : <Empty />}</Form.Item>}</Form></Spin></Controller>

3.5. 删除

终于快要搞完了,现在我们就剩删除用户这个功能了。针对我们删除来说,一般我都需要弹出一个提示,询问用户是否确定删除这条数据。这里我们可以使用 antd 中的 删除Modal或者气泡提示就可以了。

在这里插入图片描述
这里功能简单,只需要调用组件,在其回调方法中调用删除接口就可以了。代码如下:

// 移除用户
const loadRemoveUser = useRequest(UserApi.RemoveUser, {manual: true,onSuccess: () => {loadUser.run(pageQuery);message.success('移除用户成功');}
})// 删除用户
const deleteUser = (id: number) => {Modal.confirm({title: '你确认删除当前用户吗?',icon: <ExclamationCircleFilled />,content: '删除用户会导致无法登录和操作任务',okText: '确认',okType: 'danger',cancelText: '取消',onOk() {loadRemoveUser.run(id)},onCancel() {},});
}

最后在给删除按钮添加点击事件,并将用户的 ID 传给接口。

<Button type="link" danger onClick={() => deleteUser(record.id)}>删除</Button>

四. 结束语

这篇文章我们介绍了如何利用 antd 提供的组件,快速开发一个 CRUD 功能的管理模块,相信大家可以从中收获很多东西了;下一篇文章我们将介绍执行器管理的模块开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在centos 7 中 安装 配置 并 远程连接 MySQL5.7

目录 安装MySQL 1.卸载CentOS7系统自带的mariadb 2.安装依赖库 3.上传MySQL并解压 4.安装MySQL 配置MySQL 1.修改登录密码 2.修改字符集 3.配置远程连接 前言&#xff1a; 安装MySQL版本&#xff1a;mysql-5.7.30-1.el7.x86_64.rpm-bundle 文件需求后台私信 以下7条为…

STM32学习笔记(四) —— 位段别名区的使用

STM32F103RCT6有两个位段区 (SRAM 最低1M空间和片内外设存储区最低1M空间)&#xff0c; 这两个区域都有各自的别名区&#xff0c;在别名区中每个字会映射到位段区的一个位&#xff0c;所以在别名区修改一个字相当于修改位段区中对应的一个位 映射公式( 别名区中的字与位段区中的…

实现vue3响应式系统核心-watch

简介 今天我们来看看 watch 的实现。 watch本质就是观测一个响应式数据&#xff0c;当数据发生变化时通知并执行相应的回调函数。实际上&#xff0c;watch的实现本质上就是利用了 effect 以及 options.scheduler选项。 代码地址&#xff1a; https://github.com/SuYxh/share-…

flask基于python的个人理财备忘录记账提醒系统vue

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。 “备忘记账系统”是基于Mysql数据库&#xff0c;在python程序设计的基础上实现的。为确保中国经济的持续发展&#xff0c;信息时代日益更新&#xff0c;蓬勃发展。同时&#xff0c;随着信息社…

【智能家居入门2】(MQTT协议、微信小程序、STM32、ONENET云平台)

此篇智能家居入门与前两篇类似&#xff0c;但是是使用MQTT协议接入ONENET云平台&#xff0c;实现微信小程序与下位机的通信&#xff0c;这里相较于使用http协议的那两篇博客&#xff0c;在主程序中添加了独立看门狗防止程序卡死和服务器掉线问题。后续还有使用MQTT协议连接MQTT…

输入和输出

按字符输入输出 按字符输出putchar&#xff08;&#xff09; 格式 #include <stdio.h> int putchar(int c); 功能&#xff1a;向终端输出一个字符 参数&#xff1a;要输出的字符的ASCII码值 返回值&#xff1a; 成功&#xff0c;返回输出字符的ASCII码值 失败&#xff…

基于springboot汽车租赁系统源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包括软件架构模式、整体功能模块、数据库设计。本项…

Missing or invalid credentials.(Git push报错解决方案)

前言 本文主要讲解git push后报错Missing or invalid credentials的解决方案。这里针对的是windows的。 编程环境&#xff1a;VsCode 问题原因 问题翻译起来就是 凭据缺失或无效。这里我们解决方案是取消vscode里面默认的控制终端git凭据来解决,具体方案如下. 解决方案 1…

3D效果图加树进去太卡,渲染太慢怎么办?

周末的时候&#xff0c;有个朋友私信来问&#xff1a;3dmax模型加树进去打开时特别的卡&#xff0c;是怎么回事。 不知道有没有朋友遇上这么个情况。 3dmax加树建议就用代理&#xff0c;这样相比于直接加而言&#xff0c;会流畅许多。 在3D效果图中&#xff0c;“树代理”是…

萝卜视频源码前后端带视频演示

萝卜影视源码前端是用JAVA开发的全原生APP源码&#xff0c;后端用的是二次开发的苹果CMS&#xff0c;支持局域网投屏&#xff0c;视频软解硬解&#xff0c;播放器自带弹幕功能。支持解析官方视频&#xff0c;支持M3U8&#xff0c;MP4。 开屏广告&#xff0c;全局广告&#xff0…

GitHub国内打不开(解决办法有效)

最近国内访问github.com经常打不开&#xff0c;无法访问。 github网站打不开的解决方法 1.打开网站http://tool.chinaz.com/dns/ &#xff0c;在A类型的查询中输入 github.com&#xff0c;找出最快的IP地址。 2.修改hosts文件。 在hosts文件中添加&#xff1a; # localhost n…

从0开始搭建若依微服务项目 RuoYi-Cloud(保姆式教程完结)

文章接上一章&#xff1a; 从0开始搭建若依微服务项目 RuoYi-Cloud&#xff08;保姆式教程 一&#xff09;-CSDN博客 四. 项目配置与启动 当上面环境全部准备好之后&#xff0c;接下来就是项目配置。需要将项目相关配置修改成当前相关环境。 数据库配置 新建数据库&#xff…

element ui组件 el-date-picker设置default-time的默认时间

default-time &#xff1a;选择日期后的默认时间值。 如未指定则默认时间值为 00:00:00 默认值修改 <el-form-item label"计划开始时间" style"width: 100%;" prop"planStartTime"><el-date-picker v-model"formData.planStart…

TortoiseSVN各版本汉化包下载

首先进入下载版本列表 1.下载地址&#xff1a;https://sourceforge.net/projects/tortoisesvn/files ​ 2.选择自己版本进入​ 3.选择Language Packs进入&#xff0c;选择对应语言包下载。 ​ 4.在TortoiseSVN根目录下点击安装即可。 ​

解密数据清洗,SQL中的数据分析

大家好&#xff0c;数据库表中的数据经常会很杂乱。数据可能包含缺失值、重复记录、异常值、不一致的数据输入等&#xff0c;在使用SQL进行分析之前清洗数据是非常重要的。 当学习SQL时&#xff0c;可以随意地创建数据库表&#xff0c;更改它们&#xff0c;根据需要更新和删除…

canvas测量文字长度(measureText)

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

数据结构——栈和队列(C语言)

栈种常见的数据结构&#xff0c;它用来解决一些数据类型的问题&#xff0c;那么好&#xff0c;我来带着大家来学习一下栈 文章目录 栈对栈的认识栈的模拟实现栈的练习方法一方法二 栈 对栈的认识 栈&#xff08;stack&#xff09;是限定只能在表的一端进行插入删除操作的线性…

SpringCloud LoadBalancer

SpringCloud LoadBalancer 1.什么是LoadBalancer LoadBalancer&#xff08;负载均衡器&#xff09;是一种网络设备或软件机制&#xff0c;用于分发传入的网络流量负载请求到多个后端目标服务器上&#xff0c;从而实现系统资源的均衡利用和提高系统的可用性和性能。 负载均衡器…

【Tomcat与网络4】Tomcat的连接器设计

目录 1 如何设计一个灵活可靠的连接器 2 主要组件介绍 在上一篇&#xff0c;我们介绍了Tomcat提供服务的整体结构&#xff0c;本文我们一起来看一下Tomcat的连接器的设计。 在前面我们提到Tomcat主要完成两个功能&#xff1a; 处理 Socket 连接&#xff0c;负责网络字节流与…

wifi配网(esp8266和esp32)-http get和post方式

wifi配网(esp8266和esp32)-http get和post方式 通过http get和post方式来给esp芯片配网 步骤&#xff1a; 开机&#xff0c;指示灯亮起后(需要灯闪烁3下后)&#xff0c;需在3s内&#xff08;超过3s则会正常启动&#xff09;&#xff0c;按一下按键&#xff08;注&#xff1a;切…