前后端交互的弯弯绕绕

前后端交互:

🆗,收拾一下心情让我们来聊一聊AJax吧,随着前端的飞速发展,前后的交互也发生了天翻地覆的变化:

前后端交互的方式有很多: AJAX表单提交WebSocketRESTful API...

这对新入行的朋友很不友好,乱七八糟都不知道学什么怎么学了,学了没用??

傻傻呼呼让人头疼😵😵本篇文章学习至: 黑马前端AJAX入门到实战 ✅

官方文档也超级细致,细致到都不用看视频都能看懂了

Axios 快速上手

Axios框架全称 Ajax – I/O – system 官方文档🔗

不是一种新技术,本质上还是对原生XMLHttpRequest的封装,用于浏览器nodejs HTTP客户端:HTTP请求响应工具;

它基于 Promise,提供了一种简洁且强大的方式来发送异步请求,使用 Axios开发者可以轻松地发送:

GET、POST、PUT、DELETE 等 HTTP 请求,并处理响应;Axios 的主要特点包括:

  • 支持浏览器和 Node.js:在不同的环境中使用相同的 API
  • Promise-based:使得异步操作更加简洁
  • 取消请求:提供了一种方式来取消请求
  • 客户端支持防御 CSRF/XSRF:安全特性,防止跨站请求伪造
  • 转换请求数据和响应数据:自动将 JSON 数据转换为 JavaScript 对象
  • 拦截请求和响应:允许在请求或响应被 then 或 catch 处理之前拦截它们

安装使用:

常见安装方式:

  • npm安装: npm install axios 在框架中使用,本篇不涉及框架就不使用该方式;

  • 通过cdn引入: <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Axios基础语法: Demo案例——查询全国省份接口:http://localhost:3000/area/provinceList

axios({
    url: '目标资源地址',
}).then(result => {
    // 对服务器返回的数据做后续处理
})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AxiosDemo使用:</title>
</head>
<body>
  <!-- 目标: 使用axios库,获取省份列表数据,展示到页面上 -->
  <!-- 1.引入axios库 -->
  <h1>AxiosDemo使用: </h1>
  <p class="myp" ></p>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    // 2. 使用axios函数
    axios({
      url: 'http://localhost:3000/area/provinceList'
    }).then(result => {
      // 把准备好省份列表,插入到页面
      document.querySelector('.myp').innerHTML = result.data.provinceList.join('<br>') 
    })
  </script>
</body>
</html>

在这里插入图片描述

为方便测试,本人简单定义了一个:Node+Expresss+lowdb后端服务 获取地址:示例Demo

  • 关于Node的学习: Node快速入门、Express基础Deom、Express进阶升级

常用请求方法

Ok,上述展示了Axios 最基本的用法: 一个无参的GET请求,并将结果渲染至页面,

当然我们知道前后端交互是有很多规则的,不用担心Axios都可以应付通过调整各种配置,axios实例常用配置:

  • url 请求路径
  • method 接口请求类型
  • headers 设置请求头,类型:Object
  • params 请求参数,将参数拼接在URL上,类型:Object
  • data 请求参数,将参数放到请求体中,类型:Object
  • timeout 请求超时时长,单位ms,类型:Number
  • baseURL 请求的域名,基本地址,类型:String

下面让咱们来慢慢深入了解:

URL带参:

根据省份查询下属市区: GET请求http://localhost:3000/area/cityList?province=江苏省

方式一: 直接和上面案例一样,使用全URL,参数拼接在URL上进行请求;甚至如此简单⏬

axios('http://localhost:3000/area/cityList?province=江苏省').then(result => {
    console.log(result);
    console.log(result.data);
})

方式二:

method: 设置接口请求类型,常见的请求类型:GET(默认)POSTPUTDELETEPATCH 对应服务器执行的操作;

params: 上述直接URL拼接虽然可以满足请求,但对于非固定参数值,固定URL无法满足场景,

Params会将{键:值}处理拼接URL请求:url?键=值 而使前端更方便操作,请求数据;

axios({
    url:'http://localhost:3000/area/cityList',
    method: 'GET',
    params: { province:'江苏省' }
}).then(result => {
    console.log(result);
    console.log(result.data);
})

路由命名:

路由命名: 是在创建路由时为其指定一个唯一的名称,这样,你就可以在代码中引用路由名称,而不是写出完整的URL路径

对于维护|管理大型应用的路由非常有帮助,当路径需要更改时,你只需要更新路由配置,而不需要修改引用该路由的每个地方

根据省份|市区查询下属区县: GET请求http://localhost:3000/area/district/:province/:city 动态参数

查询江苏省、徐州市下属区县: GET请求http://localhost:3000/area/district/江苏省/徐州市

//路由命名: 根据省份|市区查询下属区县
const {province,city} = { province:"江苏省",city:"徐州市" }
axios(`http://localhost:3000/area/district/${province}/${city}`).then(result => {
    console.log(result);
    console.log(result.data);
})

JSON 数据:

JSON请求: 程序开发中为了方便数据传输一种格式,通过在请求头设置:application/json 后端可以更方便解析对象;

用户注册请求: POST http://127.0.0.1:3000/users/register

请求JSON:{"userName": "wsm","Password": "000000"}

  • data: 属性中的信息将被包含在请求体中发送到服务器;
//JSON数据请求: 注册用户信息,POST请求JSON数据;
axios({
    url:'http://127.0.0.1:3000/users/register',
    method: 'POST',
    data: {
        userName: "wsm",
        Password: "000000"
    }
}).then(result =>{
    console.log(result);
    console.log(result.data);
})

表单文件上传:

文件上传: 使用 FormData 表单数据对象装入

因为文件不是以前的数字和字符串,一般需要放入 FormData 以键值对-文件流的数据传递,可以查看请求体-确认请求体结构
在这里插入图片描述

<body>
  <!-- 文件选择元素 -->
  <input type="file" class="upload">
  <img src="" alt="" class="my-img">
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /*** 目标:图片上传,显示到网页上 */
    // 文件选择元素->change改变事件
    document.querySelector('.upload').addEventListener('change', e => {
      // 1. 获取图片文件
      console.log(e.target.files[0])
      // 2. 使用 FormData 携带图片文件
      const fd = new FormData()
      fd.append('img', e.target.files[0])
      // 3. 提交到服务器,获取图片url网址使用
      axios({
        url: 'http://127.0.0.1:3000/users/userImg',
        method: 'POST',
        data: fd
      }).then(result => {
        console.log(result)
        // 取出图片url网址,用img标签加载显示
        const imgUrl = result.data.imgUrl
        document.querySelector('.my-img').src = imgUrl
      })
    })
  </script>
</body>
  • data: 属性支持将FormData对象直接,发送至后端服务器;

Axios 错误处理:

接口请求,过程中难免会遇到异常错误: axios 语法中要如何处理呢?根据响应状态码?

因为,普通用户不会去控制台里看错误信息,我们要编写代码拿到错误并展示给用户在页面上,

使用 axios 的 catch 方法,捕获这次请求响应的错误并做后续处理,具体的错误处理过程如下:

  • 如果请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围,
    Axios 会捕获到一个 error.response 对象,其中包含了响应的数据、状态码和头部信息
  • 如果请求已经成功发起,但没有收到响应,error.request 也会被捕获
  • 如果在发送请求时出了问题,比如请求配置有误;

开发者可以使用 .catch() 方法来处理这些错误;

Demo用户注册请求: 部分平台对用户名有唯一的限制,对于相同的用户会错误提醒;

  • POST http://127.0.0.1:3000/users/register
  • 请求JSON:{"userName": "wsm","Password": "000000"}
//JSON数据请求: 注册用户信息,POST请求JSON数据;
axios({
    url:'http://127.0.0.1:3000/users/register',
    method: 'POST',
    data: {
        userName: "wsm",
        Password: "000000"
    }
}).then(result =>{
    alert('成功');
    console.log(result);
    console.log(result.data);
}).catch(error => {
    alert('失败');
    console.log(error);
})

AJax

Ajax Asynchronous JavaScript and XML:异步网络请求,Ajax能够让页面无刷新的请求数据;

在旧浏览器页面在向服务器请求数据时,因为返回的是整个页面的数据,页面都会强制刷新一下,这对于用户来讲并不是很友好;

我们只是需要修改页面的部分数据,但是从服务器端发送的却是整个页面的数据,十分消耗网络资源;

我们只是需要修改页面的部分数据,也希望不刷新页面,因此 异步网络请求 就应运而生;

实现ajax的方式有多种: 原生XMLHttpRequest,JQuery封装Ajax,以及Axios:

  • 原生的XMLHttpRequest的配置和调用方式都很繁琐,实现异步请求十分麻烦

  • JQuery的ajax相对于原生的ajax是非常好用的,但是没有必要因为要用ajax异步网络请求而引用jQuery框架;

  • Axios 是一个基于Promise 用于浏览器和Nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,它是Promise实现版本;

    Axios设计简洁,API简单,支持浏览器和Node,很好的与各种前端框架整合 因此,推荐大家在项目中使用Axios库;

学习 XHR 也是了解 axios 内部与服务器交互过程的真正原理: 语法如下:

//创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
//配置请求
xhr.open('请求方法', '请求url网址');

//监听处理响应结果: 需要声明在请求的前面;
xhr.addEventListener('loadend', () => {
  console.log(xhr.response)
})

//发送请求
xhr.send();   

XMLHttpRequest 对象: AJAX 的核心对象,它提供了在 JavaScript 中发送 HTTP 请求和接收 HTTP 响应的能力;

配置请求: 使用 open 方法配置请求的类型(如 “GET” 或 “POST”)、URL 和是否异步

发送请求: 使用 send 请求,send({});参数是通过请求体携带的数据,

而GET请求是通过请求头携带数据的,所以要把send的参数置为null

处理服务器响应: 通过监听 XMLHttpRequest 对象的 onreadystatechange 事件来处理服务器的响应

//在xhr对象执行收发数据的时候,它会经历五种状态:
//0 未初始化|未启动、1 启动,已经调用 open(),尚未调用 send();
//2 发送状态,已经调用 send(),但尚未接收到响应、3 接收 已经接收到部分响应数据
//4 完成,已经接收到全部响应数据,而且已经可以在浏览器中使用了
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 ){
    console.log(xhr.responseText);
    }
};

可以通过上述监听来进行响应处理: 当然比较麻烦,所以还有一种方式:为 XMLHttpRequest 对象添加一个事件监听器

用来监听 loadend 事件,loadend 事件在请求结束时触发,无论请求是成功还是失败;

常用请求方法:

URL带参:

查询参数原理要携带的位置和语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2

原生 XHR 需要自己在 url 后面携带查询参数字符串,没有 axios 帮助我们把 params 参数拼接到 url 字符串后面了

//创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();

//配置请求
xhr.open('GET', 'http://localhost:3000/area/cityList?province=江苏省');
//监听处理响应结果: 
xhr.addEventListener('loadend', () => {
    const data = JSON.parse(xhr.response);  //解析响应内容
    console.log(data);  
});
//发送请求
xhr.send();

多参数查询:

多个查询参数,如果自己拼接很麻烦: URLSearchParams 把参数对象转成“参数名=值&参数名=值“格式的字符串

// 1. 创建 URLSearchParams 对象
const paramsObj = new URLSearchParams({
  参数名1:1,
  参数名2:2
})

// 2. 生成指定格式查询参数字符串
const queryString = paramsObj.toString()
// 结果:参数名1=值1&参数名2=值2

上述Demo升级🆙:

//创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
//创建 URLSearchParams 对象
const paramsObj = new URLSearchParams({ province : "江苏省" });
//配置请求
xhr.open('GET', `http://localhost:3000/area/cityList?${paramsObj.toString()}`); //拼接请求参数;
//监听处理响应结果: 
xhr.addEventListener('loadend', () => {
    const data = JSON.parse(xhr.response);  //解析响应内容
    console.log(data);  
});
//发送请求
xhr.send();

JSON 请求数据:

原生AJax请求JSON数据: 没有 axios 方便:

  • 需要手动设置请求头:Content-Type:application/json 告诉服务器端,发送的内容类型是 JSON 字符串;
  • 传递的请求体数据,也需要手动的进行JSON转换;send({k:v}); 方法中调用;
const xhr = new XMLHttpRequest()
xhr.open('请求方法', '请求url网址')
xhr.addEventListener('loadend', () => {
  console.log(xhr.response)
})

// 1. 告诉服务器,我传递的内容类型,是 JSON 字符串
xhr.setRequestHeader('Content-Type', 'application/json')
// 2. 准备数据并转成 JSON 字符串
const user = { userName: 'wsm', Password: '000000' }
const userStr = JSON.stringify(user)
// 3. 发送请求体数据
xhr.send(userStr)

Promise

Promise是异步编程的一种解决方案: 它代表了一个异步操作的最终完成(或失败)及其结果值

简单来说,Promise是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果

  • Promise逻辑更清晰,是axios 函数内部运作的机制,主要用来解决回调地狱:

Promise 管理异步任务,语法:

  • 创建Promise对象: new Promise; 构造函数是 同步执行的,并可以在其中定义异步任务;

    它接受一个执行器,函数作为参数,执行器函数又接受两个参数,resolvereject

    分别用于在异步操作成功时兑现Promise,或者在出现错误时拒绝Promise

  • Promise.then 方法是异步执行,当执行器中执行resolve 触发回调函数;

  • Promise.catch 方法是异步执行,当执行器中执行reject 触发回调函数;支持链式编程,使代码结构清晰;

// 1. 创建 Promise 对象
const p = new Promise((resolve, reject) => {
 // 2. 执行异步任务-并传递结果
 // 成功调用: resolve(值) 触发 then() 执行
 // 失败调用: reject(值) 触发 catch() 执行
})
// 3. 接收结果
p.then(result => {
 // 成功
}).catch(error => {
 // 失败
})

示例代码: 使用Promise管理异步任务,通过切换调用的函数,而分别输出:then`catch`回调函数;

// 1. 创建Promise对象
const p = new Promise((resolve, reject) => {
  // 2. 执行异步代码
  setTimeout(() => {
    // resolve('模拟AJAX请求-成功结果')
    reject(new Error('模拟AJAX请求-失败结果'))
  }, 2000)
})

// 3. 获取结果
p.then(result => {
  console.log(result)
}).catch(error => {
  console.log(error)
})

Promise 常用函数:

  • then():添加处理程序来处理Promise的兑现或拒绝
  • catch():添加一个拒绝(操作失败)的回调函数,并返回一个Promise
  • finally():添加一个事件处理器,无论Promise对象最后的状态如何都会被调用

Promise 的状态

Promise对象的状态是对异步操作的描述,Promise对象有三种状态:

  • 待定(pending):这是Promise创建后的初始状态,在这个状态下,异步操作还没有完成,也没有失败

    Promise对象将保持这个状态直到它被兑现(fulfilled)或被拒绝(rejected)

  • 已兑现(fulfilled):当异步操作成功完成,并且Promise对象得到了一个值时,它就会转变为兑现状态

    在这个状态下,我们可以通过then()方法设置的回调函数来获取这个值;

  • 已拒绝(rejected):如果异步操作失败,或者在执行过程中抛出了一个错误,Promise对象就会变为拒绝状态

    在这个状态下,我们可以通过then()方法或catch()方法设置的回调函数来处理这个错误;

    但是如果程序上的错误,得通过catch()去拿到失败消息,在then()中是获取不了的;

    //then 支持多参数,eroor函数处理异常结果;
    promise.then(
      value => { console.log('兑现:', value); },
      error => { console.log('拒绝:', error); }
    );
    //catch 处理异常结果;
    promise.catch(error=>{ console.log('拒绝:', error); });
    
  • 三种状态:遇到resolve或者reject之前,都处于这个状态,且可以改变:

    但如果确定了状态fulfilled/reject,则结果将永远不变,不能再次修改;

Promise 结合 XHR

使用Promise➕XHR请求省份列表: 模拟 axios 函数封装,更深入了解 axios 内部运作原理

需求:基于 Promise 和 XHR 封装 myAxios 函数,获取省份列表展示到页面:

function myAxios(config) {
  return new Promise((resolve, reject) => {
    // XHR 请求
    // 调用成功/失败的处理程序
  })
}

myAxios({
  url: '目标资源地址'
}).then(result => {
    
}).catch(error => {
    
})
/* 目标:封装_简易axios函数_获取省份列表 */
// 1. 定义myAxios函数,接收配置对象,返回Promise对象
function myAxios(config) {
    return new Promise((resolve, reject) => {
        // 2. 发起XHR请求,默认请求方法为GET
        const xhr = new XMLHttpRequest()

        xhr.open(config.method || 'GET', config.url);

        xhr.addEventListener('loadend', () => {
            // 3. 调用成功/失败的处理程序
            if (xhr.status >= 200 && xhr.status < 300) {
                resolve(JSON.parse(xhr.response))
            } else {
                reject(new Error(xhr.response))
            }
        })
        xhr.send();
    })
}

// 4. 使用myAxios函数,获取省份列表展示
myAxios({
    url: 'http://localhost:3000/area/provinceList'
}).then(result => {
    console.log(result);
}).catch(error => {
    console.log(error);
})

Axios回调地狱:

回调地狱 Callback Hell,有时也被称为**“金字塔厄运”:**Pyramid of Doom

指在 JavaScript 中使用回调函数嵌套过多、层级过深,导致代码难以理解、难以维护和可读性差的一种情况

  • 这种情况通常出现在处理异步操作的场景,比如文件读取、数据库查询、网络请求等:

  • 在回调地狱中,每个异步操作结果都依赖于前一个操作的完成,这就导致了大量的回调函数嵌套,形成了深层次的嵌套结构

Demo需求: 展示默认第一个省,第一个城市,第一个地区在下拉菜单中

  • 因为: 查询地区接口需要,省份|城市参数,查询城市又需要省份参数,默认省份处于第一层
  • 所以: 在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱;
// 1. 获取默认第一个省份的名字
axios({url: 'http://localhost:3000/area/provinceList'}).then(result => {
    const province = result.data.provinceList[0]
    document.querySelector('.province').innerHTML = province
    // 2. 获取默认第一个城市的名字
    axios({url: 'http://localhost:3000/area/cityList', params: { province }}).then(result => {
        const city = result.data.cityList[0]
        document.querySelector('.city').innerHTML = city
        // 3. 获取默认第一个地区的名字
        axios({url: `http://localhost:3000/area/district/${province}/${city}` }).then(result => {
            console.log(result)
            const areaName = result.data.district[0]
            document.querySelector('.area').innerHTML = areaName
        })
    })
}).catch(error => {
    console.dir(error)
})

Promise 链式解决回调地狱:

概念:依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束

细节:then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果

每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来

好处:通过链式调用,解决回调函数嵌套问题

/**
* 目标:把回调函数嵌套代码,改成Promise链式调用结构
* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
*/
let province = ''
// 1. 得到-获取省份Promise对象
axios({url: 'http://localhost:3000/area/provinceList'}).then(result => {
    province = result.data.provinceList[0]
    document.querySelector('.province').innerHTML = province
    // 2. 得到-获取城市Promise对象
    return axios({ url: 'http://localhost:3000/area/cityList', params: { province }})
}).then(result => {
    const city = result.data.cityList[0]
    document.querySelector('.city').innerHTML = city
    // 3. 得到-获取地区Promise对象
    return axios({url: `http://localhost:3000/area/district/${province}/${city}` })
}).then(result => {
    console.log(result)
    const areaName = result.data.district[0]
    document.querySelector('.area').innerHTML = areaName
})

async 函数和 await 解决回调地狱:

asyncawait 是 JavaScript 中用于简化异步编程的关键字

它们让你能够以一种更接近同步编程的方式来写异步代码,这样可以让代码更加清晰和易于维护:

Async: async 关键字用于声明一个异步函数,定义:函数声明、函数表达式前面;

  • 当你在一个函数前面加上 async,这个函数就会返回一个 Promise 对象;
  • 如果函数正常执行结束,Promise 的状态将变为 fulfilled,并且返回值会作为 Promise的结果;
  • 如果函数抛出错误,Promise 的状态将变为 rejected,并且抛出的错误会作为 Promise 的结果;

Await: await 关键字用于等待一个 Promise 完成,且只能在 async 函数内部使用;

  • 它会暂停 async 函数的执行,直到 Promise 的状态变为 fulfilledrejected
  • 如果 Promise 成功解决,await 表达式的值就是 Promise 的结果
  • 如果 Promise 被拒绝,await 表达式会抛出拒绝的值
/* 目标:async和await_错误捕获 */
async function getData() {
    // 1. try包裹可能产生错误的代码
    try {
        const pObj = await axios({ url: 'http://localhost:3000/area/provinceList' })
        const province = pObj.data.provinceList[0]
        const cObj = await axios({ url: 'http://localhost:3000/area/cityList', params: { province } })
        const city = cObj.data.cityList[0]
        const aObj = await axios({ url: `http://localhost:3000/area/district/${province}/${city}` })
        const area = aObj.data.district[0]

        document.querySelector('.province').innerHTML = province
        document.querySelector('.city').innerHTML = city
        document.querySelector('.area').innerHTML = area
    } catch (error) {
        // 2. 接着调用catch块,接收错误信息
        console.dir(error)
    }
}
getData();

Promise.all 静态方法

Promise.all() 方法用于将多个 Promise 实例,

包装成一个新的 Promise 实例: const p = Promise.all([p1,p2,p3]);

  • 只有p1、p2、p3的状态都变成fulfilled:

    p的状态才会变成fulfilledp1、p2、p3的返回值组成一个数组,传递给p的回调函数;

  • 只要p1、p2、p3之中有一个被rejected:

    p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数;

let p1 = new Promise((resolve, reject) => {
  resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
  resolve('success')
})

let p3 = Promise.reject('失败')

Promise.all([p1, p2]).then((result) => {
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
  console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)      			// 失败了,打出 '失败'
})

本文章学习资源🔗:

黑马程序员前端AJAX入门到实战 ✅

Axios 3分钟让你学会axios在vue项目中的基本用法、Axios使用方法详解,从入门到进阶 当作进阶观看:

  • ajax与XHR的理解和使用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

九、(正点原子)Linux定时器

一、Linux中断简介 1、中断号 每个中断都有一个中断号&#xff0c;通过中断号即可区分不同的中断&#xff0c;有的资料也把中断号叫做中断线。在 Linux 内核中使用一个 int 变量表示中断号。在Linux中&#xff0c;我们可以使用已经编写好的API函数来申请中断号&#xff0c;定义…

微服务中不同服务使用openfeign 相互调用

首先 我们上文 已经知道了 nacos 的注册服务&#xff0c;现在 我们 在不同服务中相互调用就可以使用openfeign 直接调用&#xff0c;而不是 再写冗余的调用代码啦 首先 我们的微服务组件如下 因为我这个微服务是我在 员工登录demo 中 拆出来的&#xff0c;在userlogin模块中…

基于4G工业路由器的连锁品牌店铺组网监测

基于4G工业路由器的连锁品牌店铺组网监测是智慧城市建设中至关重要的任务&#xff0c;它涉及到营运管理等多方面&#xff0c;应用物联网技术可确保店铺运营的高效、安全和可靠。 连锁品牌店铺遍布城市各领域&#xff0c;甚至跨城市部署&#xff0c;分布广泛。这对集团总部的管…

HTTP/2 头部压缩 Header Compress(HPACK)详解

文章目录 1. HPACK 的工作原理1.1 静态表1.2 动态表 2. 压缩过程2.1 编码过程2.2 解码过程 3. HPACK 的优势 在HTTP1.0中&#xff0c;我们使用文本的形式传输header&#xff0c;在header中携带cookie的话&#xff0c;每次都需要重复传输几百到几千的字节&#xff0c;这着实是一…

JavaWeb——MySQL:navicate客户端工具简单使用

目录 1. 连接 2. 新建数据库 3. 使用数据库 4. 新建表 5.使用表 6. 导出数据库 我这里是英文版&#xff0c;没有进行汉化。 1. 连接 点击左上角Connection&#xff0c;选择MySQL&#xff0c;&#xff08;我连接的是自己计算机上的数据库&#xff09;连接名输入&#x…

F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践

在这个数字化转型加速的时代&#xff0c;DNS&#xff08;域名系统&#xff09;的重要性不言而喻。每一次重大事件都凸显了DNS的可靠性和安全性问题。对企业而言&#xff0c;它不仅关系到业务连续性&#xff0c;更是提供永续数字服务的关键。本文根据F5公司发布的《企业DNS建设白…

Mybatis-Plus学习|快速入门CRUD、主键生成策略(雪花算法、主键自增等)、自动填充、乐观锁、分页插件、逻辑删除

MyBatisPlus概述 为什么要学习它呢?MyBatisPlus可以节省我们大量工作时间&#xff0c;所有的CRUD代码它都可以自动化完成! JPA、tk-mapper、MyBatisPlus 偷懒的! MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff…

基于JSP的列车票务信息管理系统

开头语&#xff1a; 你好&#xff0c;我是专注于计算机科学与技术研究的学长。如果你对列车票务信息管理系统感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、数据库管理工具…

spring boot jar 启动报错 Zip64 archives are not supported

spring boot jar 启动报错 Zip64 archives are not supported 原因、解决方案问题为什么 spring boot 不支持 zip64zip、zip64 功能上的区别zip 的文件格式spring-boot-loader 是如何判断是否是 zip64 的&#xff1f; 参考 spring boot 版本是 2.1.8.RELEASE&#xff0c;引入以…

HBDNY-40/1端子排电压继电器 DC110V 导轨安装 约瑟JOSEF

HBDNY系列端子排型电压电流继电器 系列型号&#xff1a;&#xff08;3、4过/低电压型&#xff0c;5、6过/低电流型&#xff09; HBDNY-30/1端子排型电压继电器&#xff1b;HBDNY-30/2端子排型电压继电器&#xff1b; HBDNY-30/3端子排型电压继电器&#xff1b;HBDNY-30/4端子…

摩柏BI,轻松实现word报告自动更新

|| 导语 告别手工&#xff01;在数字化办公的今天&#xff0c;高效、准确的数据处理能力已经成为职场人士必备的技能之一。尤其是对于财务分析师、市场研究员和管理人员&#xff0c;他们需要处理的报告不仅数量庞大&#xff0c;而且对数据的准确性和实时性要求极高。传统WORD报…

python爬虫需要什么HTTP代理?

用来爬虫的话&#xff0c;还是建议用高匿名代理&#xff0c;但显然题主用了高匿名代理还是出现了一部分问题&#xff0c;我们可以先找到问题关键再解决它&#xff0c;一般爬虫用了高匿名代理出现被封会有以下几种原因&#xff1a; 1.代理IP的质量不过关 一般来说每个网站都有…

解锁小红书新玩法:中小企业出海营销的集成策略

随着全球数字化浪潮的推进&#xff0c;小红书作为生活方式分享平台的崛起&#xff0c;为中小企业提供了一个全新的营销舞台。NetFarmer&#xff0c;作为专注于企业数字化出海的服务商&#xff0c;深谙小红书的营销策略&#xff0c;并致力于通过HubSpot产品销售与实施&#xff0…

HarmonyOS应用开发学习经验

一、HarmonyOS学习官网 开发者能力认证 HarmonyOS应用开发者基础认证6月之前的学习资源官网已经关闭过期&#xff0c;大家不要慌&#xff0c;官方更新了最新资源&#xff0c;但是&#xff0c;对于之前没有学习完的学员不友好&#xff0c;存在知识断片的现象&#xff0c;建议官…

微型导轨:手术机器人的高精度“骨骼”

微型导轨精度高&#xff0c;摩擦系数小&#xff0c;自重轻&#xff0c;结构紧凑&#xff0c;被广泛应用在医疗器械中&#xff0c;尤其是在手术机器人中的应用&#xff0c;通过手术机器人&#xff0c;外科医生可以远离手术台操纵机器人进行手术。可以说&#xff0c;是当之无愧的…

C语言实现:贪心算法

算法基础原理 贪心算法是一种在求解问题时&#xff0c;总是做出在当前看来是最好的选择的算法。它不从整体最优上进行考虑&#xff0c;而是通过每一步的局部最优选择&#xff0c;希望达到全局的最优解. 贪心算法的特点:贪心算法在每一步都选择当前状态下的最优解&#xff0c;即…

SSH的基本使用

文章目录 1. SSH使用介绍2. 如何配置OpenSSH Client和OpenSSH Server2.1 Windows系统配置2.2 Linux系统配置2.2.1. 安装OpenSSH服务2.2.2. 启动和检查SSH服务 3. SSH具体使用方式4. vscode中使用ssh远程连接 1. SSH使用介绍 SSH 最常见的用途是通过加密连接在不安全的网络中进…

fiddler抓https包

1&#xff0c;安装fiddler省略 2&#xff0c;下载证书步骤&#xff1a;tools-options-https 点击确认&#xff0c;点击OK&#xff0c;点击是 把证书安装到谷歌浏览器上步骤&#xff1a;点击谷歌浏览器右上角的设置&#xff0c;在搜索框中搜索证书&#xff0c;点击“证书管理”…

常见的排序算法【总结】

目录 排序的基本概念与分类排序的稳定性内排序与外排序简单排序冒泡排序时间复杂度&#xff1a; O ( n 2 ) O(n^2) O(n2) 简单选择排序排序原理&#xff1a;时间复杂度&#xff1a; O ( n 2 ) O(n^2) O(n2) 插入排序排序原理&#xff1a;时间复杂度&#xff1a; O ( n 2 ) O(n^…

MFC GDI绘制卡通人物

文章目录 主要代码完整visual studio工程下载 主要代码 // DrawFrogView.cpp : implementation of the CDrawFrogView class //#include "stdafx.h" #include "DrawFrog.h"#include "DrawFrogDoc.h" #include "DrawFrogView.h"#inclu…