Node服务器 - koa框架

news2024/11/27 9:54:00

1 koa的基本使用

2 koa的参数解析

3 koa响应和错误

4 koa静态服务器

5 koa的源码解析

6 和express对比

koa的基本使用过程

const Koa = require('koa')

// 创建app对象
const app = new Koa()

// 注册中间件(middleware)
// koa的中间件有两个参数: ctx/next
app.use((ctx, next) => {
  console.log('匹配到koa的中间件')
    // 向客户端发送消息
  ctx.body = '哈哈哈哈哈'
})

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa中ctx参数的解析

ctx包含了请求对象和响应对象

注意区分ctx.req和ctx.request;

区分ctx.res和ctx.response.

还包括其他的属性,比如ctx.query和ctx.params等等。

next()和express的用法差不多

const Koa = require('koa')

// 创建app
const app = new Koa()

// 中间件
app.use((ctx, next) => {
  // 1.请求对象
  console.log(ctx.request) // 请求对象: Koa封装的请求对象
  console.log(ctx.req) // 请求对象: Node封装的请求对象

  // 2.响应对象
  console.log(ctx.response) // 响应对象: Koa封装的响应对象
  console.log(ctx.res) // 响应对象: Node封装的响应对象

  // 3.其他属性
  console.log(ctx.query)
  // console.log(ctx.params)

  next()
})

app.use((ctx, next) => {
  console.log('second middleware~')
})


// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa区分路径和方式

在koa里面没有像express里面的app.get()和app.post()这样子的写法,只有app.use()。

并且也没有像express里面的app.get("/home"(){})和app.post("/home"(){})这样子的写法,koa需要手动判断路径,ctx.path可以拿到客户端访问服务器时候的路径是什么。

通过ctx.method可以拿到客户端访问服务器时候采用的是什么方式。

这种情况多了是肯定不方便也很繁琐,解决办法是使用路由。看下面一节的代码。

const Koa = require('koa')

// 创建app
const app = new Koa()

// 中间件: path/method使用路由
app.use((ctx, next) => {
  if (ctx.path === '/users') {
    if (ctx.method === 'GET') {
      ctx.body = 'user data list'
    } else if (ctx.method === 'POST') {
      ctx.body = 'create user success~'
    }
  } else if (ctx.path === '/home') {
    ctx.body = 'home data list~'
  } else if (ctx.path === '/login') {
    ctx.body = '登录成功, 欢迎回来~'
  }
})

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa路由的使用方法

下载对应的koa的路由

npm install @koa/router

下面这段代码是没有封装路由的写法: 

const Koa = require('koa')

const KoaRouter = require('@koa/router')

// 创建服务器app
const app = new Koa()

// 路由的使用
// // 1.创建路由对象 /users对应的是后续路由的主要路径,即localhost:6000/users
// const userRouter = new KoaRouter({ prefix: '/users' })

// // 2.在路由中注册中间件: path/method
// userRouter.get('/', (ctx, next) => {
//   ctx.body = 'users list data~'
// })
// userRouter.get('/:id', (ctx, next) => {
//   const id = ctx.params.id
//   ctx.body = '获取某一个用户' + id
// })
// userRouter.post('/', (ctx, next) => {
//   ctx.body = '创建用户成功~'
// })
// userRouter.delete('/:id', (ctx, next) => {
//   const id = ctx.params.id
//   ctx.body = '删除某一个用户' + id
// })
// userRouter.patch('/:id', (ctx, next) => {
//   const id = ctx.params.id
//   ctx.body = '修改某一个用户' + id
// })

// 3.让路由中的中间件生效
app.use(userRouter.routes())
// 这个是用来提示客户端除了上面有的请求方式,其他的都是没有封装的方法,不能使用
app.use(userRouter.allowedMethods())

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

 下面的写法是针对封装了路由的:

 userRouter的代码:

const KoaRouter = require('@koa/router')

// 1.创建路由对象  /users对应的是后续路由的主要路径,即localhost:6000/users
const userRouter = new KoaRouter({ prefix: '/users' })

// 2.在路由中注册中间件: path/method
userRouter.get('/', (ctx, next) => {
  ctx.body = 'users list data~'
})
userRouter.get('/:id', (ctx, next) => {
  const id = ctx.params.id
  ctx.body = '获取某一个用户' + id
})
userRouter.post('/', (ctx, next) => {
  ctx.body = '创建用户成功~'
})
userRouter.delete('/:id', (ctx, next) => {
  const id = ctx.params.id
  ctx.body = '删除某一个用户' + id
})

module.exports = userRouter
const Koa = require('koa')
const userRouter = require('./router/userRouter')


// 创建服务器app
const app = new Koa()



// 3.让路由中的中间件生效
app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa中参数解析方式

解析get的两种数据是内置就能解决的,但是队与post的json格式的数据还得下载第三方的库:

npm install koa-bodyparser

这个库能解析json和urlencoded的消息体数据,但是不能成立formdata的数据 ,这个时候用到另外一个第三方库:

解析formdata的路径的路由才有必要使用这个解析,所以解析的方式是写在对应路由的中间件中 

npm install @koa-multer multer

 userRouter.post('/formdata', formParser.any(), (ctx, next) => {
  console.log(ctx.request.body)
  ctx.body = '用户的formdata信息'
})

const Koa = require('koa')
const KoaRouter = require('@koa/router')
const bodyParser = require('koa-bodyparser')
const multer = require('@koa/multer')

// 创建app对象
const app = new Koa()

// 使用第三方中间件解析body数据
app.use(bodyParser())
const formParser = multer()

// 注册路由对象 /users对应的是后续路由的主要路径,即localhost:6000/users
const userRouter = new KoaRouter({ prefix: '/users' })

/**
 * 1.get: params方式, 例子:/:id
 * 2.get: query方式, 例子: ?name=why&age=18
 * 3.post: json方式, 例子: { "name": "why", "age": 18 }
 * 4.post: x-www-form-urlencoded
 * 5.post: form-data
 */
// 1.get/params
userRouter.get('/:id', (ctx, next) => {
  const id = ctx.params.id
  ctx.body = 'user list data~:' + id
})

// 2.get/query
userRouter.get('/', (ctx, next) => {
  const query = ctx.query
  console.log(query)
  ctx.body = '用户的query信息' + JSON.stringify(query)
})

// 3.post/json(使用最多)
userRouter.post('/json', (ctx, next) => {
  // 注意事项: 不能从ctx.body中获取数据
  //第三方库解析的json内容就是放到ctx.request.body里面,
  //ctx.req.body在这里是underfine
  console.log(ctx.request.body, ctx.req.body)

  // ctx.body用于向客户端返回数据
  ctx.body = '用户的json信息'
})

// 4.post/urlencoded
userRouter.post('/urlencoded', (ctx, next) => {
//这个第三方库解析的urlencoded内容就是放到ctx.request.body里面,
  console.log(ctx.request.body)

  ctx.body = '用户的urlencoded信息'
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())


// 5.post/form-data
userRouter.post('/formdata', formParser.any(), (ctx, next) => {
  console.log(ctx.request.body)
  ctx.body = '用户的formdata信息'
})

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa中文件上传方式

const Koa = require('koa')
const KoaRouter = require('@koa/router')
const multer = require('@koa/multer')

// 创建app对象
const app = new Koa()

// const upload = multer({
//   dest: './uploads'
// })

// 给上传文件解析到 ./uploads文件夹里面并且添加文件后缀
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, cb) {
      cb(null, './uploads')
    },
    filename(req, file, cb) {
      cb(null, Date.now() + "_" + file.originalname)
    }
  })
})

// 注册路由对象 /upload对应的是后续路由的主要路径,即localhost:6000/uploads
const uploadRouter = new KoaRouter({ prefix: '/upload' })


// 当文件的上传
uploadRouter.post('/avatar', upload.single('avatar'), (ctx, next) => {
  console.log(ctx.request.file)
  ctx.body = '文件上传成功~'
})

//多文件上传
uploadRouter.post('/photos', upload.array('photos'), (ctx, next) => {
  console.log(ctx.request.files)
  ctx.body = '文件上传成功~'
})

app.use(uploadRouter.routes())
app.use(uploadRouter.allowedMethods())

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa中部署静态资源

需要下载对应的第三方包:

npm install koa-static

使用之后可以给客户端提供图片地址,比如:http://localhost:8000/uploads/XXXX.jpg 

const Koa = require('koa')
const static = require('koa-static')

const app = new Koa()

// app.use((ctx, next) => {
//   ctx.body = "哈哈哈哈"
// })

app.use(static('./uploads'))
app.use(static('./build'))

app.listen(8000, () => {
  console.log('koa服务器启动成功~')
})

koa响应结果的方式

const fs = require('fs')
const Koa = require('koa')
const KoaRouter = require('@koa/router')

// 创建app对象
const app = new Koa()

// 注册路由对象
const userRouter = new KoaRouter({ prefix: '/users' })

userRouter.get('/', (ctx, next) => {
  // 1.body的类型是string
  // ctx.body = 'user list data~'

  // 2.body的类型是Buffer
  // ctx.body = Buffer.from('你好啊, 李银河~')

  // 3.body的类型是Stream
  // const readStream = fs.createReadStream('./uploads/1668331072032_kobe02.png')
  // ctx.type = 'image/jpeg'
  // ctx.body = readStream

  // 4.body的类型是数据(array/object) => 使用最多
  ctx.status = 201
  ctx.body = {
    code: 0,
    data: [
      { id: 111, name: 'iphone', price: 100 },
      { id: 112, name: 'xiaomi', price: 990 },
    ]
  }

  // 5.body的值是null, 自动设置http status code为204
  // ctx.body = null
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa的错误处理方案

const Koa = require('koa')
const KoaRouter = require('@koa/router')

// 创建app对象
const app = new Koa()

// 注册路由对象
const userRouter = new KoaRouter({ prefix: '/users' })

userRouter.get('/', (ctx, next) => {
  const isAuth = false
  if (isAuth) {
    ctx.body = 'user list data~'
  } else {
    // ctx.body = {
    //   code: -1003,
    //   message: '未授权的token, 请检测你的token'
    // }
    // EventEmitter
    ctx.app.emit('error', -1003, ctx)
  }
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

// 独立的文件: error-handle.js
app.on('error', (code, ctx) => {
  const errCode = code
  let message = ''
  switch (errCode) {
    case -1001:
      message = '账号或者密码错误~'
      break
    case -1002:
      message = '请求参数不正确~'
      break
    case -1003:
      message = '未授权, 请检查你的token信息'
      break
  }

  const body = {
    code: errCode,
    message
  }

  ctx.body = body
})

// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa和express对比

这里提前先说一点:在中间件中遇到next()就会马上跳到下一个中间件中执行中间件的内容;这个时候前一个中间件的next()后面如果还有一段代码的话就暂时先不执行了,等后续中间件没有next()了会以洋葱模型的方式回来继续执行每一个中间件的next()后面的一段代码。入下图显示的中间件。但是express 的异步情况不满足洋葱模型。

 

express中间件-执行同步

代码的执行顺序是

1、console.log('koa middleware01')   ctx.msg = 'aaa';2、aaa中的next()  ; 3、console.log('koa middleware02')  ctx.msg += 'bbb';4、bbb中的next()

4、console.log('koa middleware03')  ctx.msg += 'ccc'  ;  ;5、回到ccc看看有没有执行的代码;  6、回到aaa中的剩余代码ctx.body = ctx.msg ;。

最后向客户端发送的是aaabbbccc。

res.json(aaabbbccc)

const express = require('express')

// 创建app对象
const app = express()

// 编写中间件
app.use((req, res, next) => {
  console.log('express middleware01')
  req.msg = 'aaa'
  next()
  // 返回值结果
  res.json(req.msg)
})

app.use((req, res, next) => {
  console.log('express middleware02')
  req.msg += 'bbb'
  next()
})

app.use((req, res, next) => {
  console.log('express middleware03')
  req.msg += 'ccc'
})


// 启动服务器
app.listen(9000, () => {
  console.log('express服务器启动成功~')
})

express中间件-执行异步

这里的执行顺序是1、console.log('koa middleware01')   ctx.msg = 'aaa';2、aaa中的next()  ; 3、console.log('koa middleware02')  ctx.msg += 'bbb';4、回到aaa中的剩余代码ctx.body = ctx.msg ;。

这里 res.json(req.msg)最后向客户端发送的是aaabbb

const express = require('express')
const axios = require('axios')

// 创建app对象
const app = express()

// 编写中间件
app.use((req, res, next) => {
  console.log('express middleware01')
  req.msg = 'aaa'
  next()
  // 返回值结果
   res.json(req.msg)
})

app.use((req, res, next) => {
  console.log('express middleware02')
  req.msg += 'bbb'
  next()
})

// 执行异步代码
app.use(async (req, res, next) => {
  console.log('express middleware03')
  const resData = await axios.get('http://123.207.32.32:8000/home/multidata')
  req.msg += resData.data.data.banner.list[0].title

  // 只能在这里返回结果
  
})


// 启动服务器
app.listen(9000, () => {
  console.log('express服务器启动成功~')
})

express像koa一样把所有中间件变成异步的也不能做到像koa一样执行顺序可以回到第一步。

下面代码的res.json(req.msg)结果还是aaabbb

​
const express = require('express')
const axios = require('axios')

// 创建app对象
const app = express()

// 编写中间件
app.use(async (req, res, next) => {
  console.log('express middleware01')
  req.msg = 'aaa'
  await next()
  // 返回值结果
   res.json(req.msg)
})

app.use(async (req, res, next) => {
  console.log('express middleware02')
  req.msg += 'bbb'
  await next()
})

// 执行异步代码
app.use(async (req, res, next) => {
  console.log('express middleware03')
  const resData = await axios.get('http://123.207.32.32:8000/home/multidata')
  req.msg += resData.data.data.banner.list[0].title

  // 只能在这里返回结果
  
})


// 启动服务器
app.listen(9000, () => {
  console.log('express服务器启动成功~')
})

​

使用expree解决异步请求的办法就是在最后一个中间件res.json(req.msg)再输出客户端数据。顺序和同步一样

​
const express = require('express')
const axios = require('axios')

// 创建app对象
const app = express()

// 编写中间件
app.use(async (req, res, next) => {
  console.log('express middleware01')
  req.msg = 'aaa'
  await next()

   
})

app.use(async (req, res, next) => {
  console.log('express middleware02')
  req.msg += 'bbb'
  await next()
})

// 执行异步代码
app.use(async (req, res, next) => {
  console.log('express middleware03')
  const resData = await axios.get('http://123.207.32.32:8000/home/multidata')
  req.msg += resData.data.data.banner.list[0].title

  // 只能在这里返回结果
  res.json(req.msg)
})


// 启动服务器
app.listen(9000, () => {
  console.log('express服务器启动成功~')
})

​

koa中间件-执行同步

这里执行的结果是ctx.body = aaabbbccc返回给客户端数据是aaabbbccc。

执行顺序是先执行

1、console.log('koa middleware01')   ctx.msg = 'aaa';2、aaa中的next()  ; 3、console.log('koa middleware02')  ctx.msg += 'bbb';4、bbb中的next()

4、console.log('koa middleware03')  ctx.msg += 'ccc'  ;  ;5、回到ccc看看有没有执行的代码;  6、回到aaa中的剩余代码ctx.body = ctx.msg ;。

这种执行顺序又叫洋葱模型。

const Koa = require('koa')
const KoaRouter = require('@koa/router')

// 创建app对象
const app = new Koa()

// 注册中间件
app.use((ctx, next) => {
  console.log('koa middleware01')
  ctx.msg = 'aaa'
  next()

  // 返回结果
  ctx.body = ctx.msg
})

app.use((ctx, next) => {
  console.log('koa middleware02')
  ctx.msg += 'bbb'
  next()
})

app.use((ctx, next) => {
  console.log('koa middleware03')
  ctx.msg += 'ccc'
})


// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

koa中间件-执行异步

比如执行的中间件中有异步请求的代码,axios的请求。

下面这段代码有异步的中间件时,执行顺序是:1、console.log('koa middleware01')   ctx.msg = 'aaa';2、aaa中的next();3、console.log('koa middleware02')  ctx.msg += 'bbb'  ;4、 aaa中的剩余代码ctx.body = ctx.msg ; 。      这里 最后向客户端发送的是aaabbb

const Koa = require('koa')
const axios = require('axios')

// 创建app对象
const app = new Koa()

// 注册中间件
// 1.koa的中间件1
app.use( (ctx, next) => {
  console.log('koa middleware01')
  ctx.msg = 'aaa'
   next()

  // 返回结果
  ctx.body = ctx.msg
})

// 2.koa的中间件2
app.use( (ctx, next) => {
  console.log('koa middleware02')
  ctx.msg += 'bbb'
  // 如果执行的下一个中间件是一个异步函数, 那么next默认不会等到中间件的结果, 就会执行下一步操作
  // 如果我们希望等待下一个异步函数的执行结果, 那么需要在next函数前面加await
  next()
  console.log('----')
})

// 3.koa的中间件3
app.use(async (ctx, next) => {
  console.log('koa middleware03')
  // 网络请求
  const res = await axios.get('http://123.207.32.32:8000/home/multidata')
  ctx.msg += res.data.data.banner.list[0].title
})


// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

所以,如果想要使得有异步中间件的情况下还是能够像同步那样都执行完中间件之后在返回结果的办法就是全部中间件转成异步的。最后向客户端发送的是aaabbbXXXX,顺序和同步一样

const Koa = require('koa')
const axios = require('axios')

// 创建app对象
const app = new Koa()

// 注册中间件
// 1.koa的中间件1
app.use(async (ctx, next) => {
  console.log('koa middleware01')
  ctx.msg = 'aaa'
  await next()

  // 返回结果
  ctx.body = ctx.msg
})

// 2.koa的中间件2
app.use(async (ctx, next) => {
  console.log('koa middleware02')
  ctx.msg += 'bbb'
  // 如果执行的下一个中间件是一个异步函数, 那么next默认不会等到中间件的结果, 就会执行下一步操作
  // 如果我们希望等待下一个异步函数的执行结果, 那么需要在next函数前面加await
  await next()
  console.log('----')
})

// 3.koa的中间件3
app.use(async (ctx, next) => {
  console.log('koa middleware03')
  // 网络请求
  const res = await axios.get('http://123.207.32.32:8000/home/multidata')
  ctx.msg += res.data.data.banner.list[0].title
})


// 启动服务器
app.listen(6000, () => {
  console.log('koa服务器启动成功~')
})

 

 

 

 

 

 

 

 

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

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

相关文章

Apple Vision Pro:空间计算的未来已来,你准备好了吗?

“ 正如iPhone带我们进入移动计算时代,Apple Vision Pro将带我们进入空间计算时代。” 我虽然没有亲身体验,但观看了许多国内外第一批体验者的体验分享,看得出来,这些体验者都十分兴奋,根据他们的描述,我…

Mac安装zookeeper

文章目录 1.下载zookeeper安装包2.解压安装包3.修改配置文件4.启动服务端5.启动客户端 1.下载zookeeper安装包 https://archive.apache.org/dist/zookeeper/ 选择需要的版本下载 下载的时候要注意下载已经编译好的二进制版本 2.解压安装包 将下载的安装包解压到你想要的位…

基于Faster RCNN时间钢铁表面的缺陷检测

目标检测在许多行业中都有许多实际应用。大多数时候,在工业环境中,物体检测目标很小。因此,有效地训练目标检测模型变得非常困难。其中一个问题是钢材表面缺陷检测。即使使用深度学习,也很难高精度地解决问题。在本文中,我们将使用 PyTorch 库训练 Faster RCNN 对象检测模…

【3DsMAX】从零开始建房(5)

目录 1. 制作护栏 2. 制作梯子 3. 制作二层窗户 1. 制作护栏 选中顶部三条边线 点击“利用所选内容创建图形” 选择线性 此时我们就成功的创建了一个二维样条线 选中样条线上其中的一个点,移动点使线条缩短 缩小一点 渲染 同样的方法再制作一根 新建一个圆柱体 …

浅谈Spring Cloud OpenFeign

OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。 Spring Cloud OpenFe…

临期食品电商 APP 的设计与开发

摘 要 : 在移动互联网和电子商务产业的快速发展中,越来越多的消费者开始慢慢的接触网上购 物,互联网经济的全面动员将席卷全球,各种电商应用将在时代的浪潮中层出不穷。在未来各国的 不断发展中互联网很可能会成为销售各种货物的…

在线商城前台开发环境配置

一、项目配置 node 15.14.0 官网下载 https://nodejs.org/zh-cn/download/releases npm 7.7.6 下载node后自动安装npm,如果版本不对就更换对应版本 npm install react7.7.6 下载项目源码 链接:https://www.123pan.com/s/bT07Vv-WICcv.html 解压到一…

【P50】JMeter 汇总报告(Summary Report)

文章目录 一、汇总报告(Summary Report)参数说明二、准备工作三、测试计划设计 一、汇总报告(Summary Report)参数说明 可以查看事务或者取样器在某个时间范围内执行的汇总结果 使用场景:用于评估测试结果 使用频率…

java boot将一组yml配置信息装配在一个对象中

其实将一组yml数据封进一个对象中才是以后的主流开发方式 我们创建一个springboot项目 找到项目中的启动类所在目录 在同目录下创建一个类 名字你们可以随便取 我这里直接叫 dataManager 然后 在yml中定义这样一组数据信息 然后 我们在类中定义三个和这个配置信息相同的字段…

全志V3S嵌入式驱动开发(触摸屏驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 所谓的触摸屏,其实就是在普通的lcd屏幕之上,再加一层屏而已。这个屏是透明的,这样客户就可以看到下面lcd屏幕的…

想要提高办公效率,可以采用表单自定义工具

当前,随着社会的进步和科技的发展,表单自定义工具逐渐在现代化办公场所中得到重用和喜爱。因为它的灵活、简便、易操作等优势特性,使得其突破了传统表单制作工具的局限,成为广大中大型企业实现流程化管理和数字化进程的得力助手。…

UnityVR--组件5--Animation动画

目录 新建动画Animation Animation组件解释 应用举例1:制作动画片段 应用举例2:添加动画事件 Animator动画控制器 应用举例3:在Animator中设置动画片段间的跳转 本篇使用的API:Animation、Animator以及Animator类中的SetFlo…

程序语言排行榜有哪些

程序语言排名 程序语言排行NO.1Java Java是基于类的面向对象的编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。任职于Sun Microsystems的詹姆斯高斯林等人于1990年代初开发Java语言的雏形,最初被…

超低功耗待机血压计语音IC方案,智能提示NV080C-S8

随着我国步入21世纪的步伐和改革开放的不断深入,我国医疗水平和人民的生活水平不断提高,致使我国已经成为了全球老龄化为严重的国家,老年人占据的比重越来越大,一些常见的却不容易治愈的老年性疾病的预防工作已成为现今确保老年人…

LVM逻辑卷元数据丢失恢复案例 —— 筑梦之路

Lvm常见的故障主要是pv出现异常,有以下几种情况 一个是pv所在的磁盘发生了lvm的元数据损坏一个是系统无法识别到pv所在的磁盘一个是系统异常,断电等导致重启后盘符发生变化,也就是系统识别的磁盘uuid发生变化,但是wwid还是可以对应…

4.6 Monitor概念

目录 1、对象头2、原理Monitor3、原理之Synchronized4、原理之Synchronized进阶1)轻量级锁2)锁膨胀3)自旋优化4)偏向锁5)锁消除 1、对象头 64 位虚拟机 在加锁的过程中,Mark Word中的62位将会指向操作系统…

外包呆了5年终上岸,劝各位别去了...

有些测试员朋友找工作过程中问我,或者网上问有外包公司的offer,要不要去外包公司?在这里我结合我自己的经历和身边一些朋友的情况来谈谈这个问题。首先我呆过两家外包公司,并且身边有不少朋友是在外包公司工作。所以我只是尽量客观的分析这个…

Python 接口自动化测试导入接口无法上传文件有什么原因? 详细教程

在Python接口自动化测试中,上传文件通常需要使用requests库来发送HTTP请求。以下是一个示例代码来实现上传文件的功能: 如果你想学习自动化测试,我这边给你推荐一套视频,这个视频可以说是B站百万播放全网第一的自动化测试教程&am…

畅聊趣坊项目测试报告

文章目录 项目背景项目功能测试计划与设计功能测试自动化测试 测试结果功能测试结果UI自动化测试结果 项目背景 在浏览网站时,发现好多网站开放出聊天的窗口,我们一发送消息就会收到一条消息,好奇这个功能是怎么实现的,最后查阅资…

七日杀EOS错误,开服出现房间无法被搜索的问题

如题,本问题建立在你的服务器已经正常启动的情况下。 如果你的服务器根本做不到正常启动,那么这个方案可能并不适合你。 这里只提供windows端的配套过程,如果你的os是linux,那么需要自行bing一下证书导入方法。 本文默认你的serve…