Node.js Koa框架学习笔记
Koa
基本介绍
Koa是Node.js中非常出名的一款WEB框架,其特点是短小精悍性能强。
它由Express原版人马打造,同时也是Egg框架的设计蓝图,可以说Koa框架的学习性价比是非常高的。
项目搭建
我们先初始化一个项目:
$ npm init
TypeScript可以让项目更加容易维护,所以安装TypeScript是不可或缺的一部分:
$ npm install typescript ts-node @types/node peer dependencies yourself --save
当安装完成后,需要在根目录中新建src目录以及server.ts文件:
$ mkdir ./src
$ touch ./src/server.ts
下一步是填入TypeScript的配置文件:
$ tsc --init
配置文件内容如下:
{
"include": [
"./src/**/*", // 仅编译src目录下的所有ts文件
],
"exclude": [
"./src/test/**/*", // 不编译src目录中test目录下所有的ts文件
],
"compilerOptions": {
"target": "ES6", // 编译后生成的js版本为es6
"module": "CommonJS", // 编译后的模块使用规范为CommonJs
"lib": [ // node环境中测试ts代码所需要使用的库
"ES6"
],
"outDir": "./dist", // 编译后生成的js文件存放路径
"allowJs": true, // 二次编译js文件
"checkJs": true, // 验证js文件语法
"removeComments": false, // 编译后的js文件删除注释信息
"noEmitOnError": true, // 如果编译时出现错误,编译将终止
"strict": true, // 启用TypeScript的严格模式
"alwaysStrict": true, // 启用JavaScript的严格模式
"noFallthroughCasesInSwitch": true, // 检测switch语句块是否正确的使用了break
"noImplicitReturns": true, // 检测函数是否具有隐式的返回值
"noUnusedLocals": false, // 检测是否具有未使用的局部变量
"noUnusedParameters": false, // 检测是否具有未使用的函数参数
"allowUnreachableCode": true, // 检测是否具有永远不会运行的代码
}
}
由于Koa是第三方框架,所以你应该先安装它:
$ npm install koa --save
$ npm install @types/koa --save
快速上手
使用Koa框架搭建一个HTTP服务器非常的简单,你只需要以下几行代码即可搞定。
import * as Koa from "koa"
const server: Koa = new Koa()
server.use(async (ctx: Koa.Context) => {
ctx.response.body = "HELLO KOA!";
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
级联操作
每一个视图函数中,都具有2个参数ctx和next,而通过next你可以实现级联操作。
如下所示,它将按顺序打印1、2、3、4、5:
import * as Koa from "koa"
const server: Koa = new Koa()
server.use(async (ctx: Koa.Context, next: Koa.Next) => {
const start: number = Date.now()
console.log("1");
await next()
console.log("5");
ctx.response.body = "HELLO KOA!"
})
server.use(async (ctx: Koa.Context, next: Koa.Next) => {
console.log("2");
await next();
console.log("4");
})
server.use(async (ctx: Koa.Context, next: Koa.Next) => {
console.log("3");
console.log("hello middleware");
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
路由系统
koa-router
默认的Koa框架路由系统不是很完善,对此你可以使用koa-router插件,官方所提供的文档非常齐全,你可以自行前往查看,包括嵌套路由、动态路由等知识在官方文档里面都有详细的示例,这里不再阐述。
首先需要进行下载:
$ npm install koa-router --save
$ npm install @types/koa-router --save
然后就可以进行使用了,注意现在Middleware View Function的编写不再是通过server.use()进行注册了而是通过router.use()进行注册,代码如下:
import * as Koa from "koa"
import * as Router from 'koa-router'
const server: Koa = new Koa()
const router: Router = new Router()
// 1. 装载插件
server.use(router.routes())
// 2.书写视图,注意后面都是编程router.use()
router.get("/api/get", async (ctx: Koa.Context, next: Koa.Next) => {
// 3.等待之前的插件处理完成后再运行Middleware View Function
await next()
ctx.response.body = "HELLO KOA!"
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
请求方式
koa-router能够限制请求方式,如下所示,其中all()方法能支持所有的请求:
router
.get('/', (ctx, next) => {
ctx.body = 'Hello World!';
})
.post('/users', (ctx, next) => {
// ...
})
.put('/users/:id', (ctx, next) => {
// ...
})
.del('/users/:id', (ctx, next) => {
// ...
})
.all('/users/:id', (ctx, next) => {
// ...
});
请求相关
ctx.request
ctx是一个上下文对象,你可以通过ctx.request获得本次HTTP服务的请求对象。
在请求对象中它提供了很多属性可供我们使用,以下只例举一些比较常见的:
属性 | 简写 | 描述 |
---|---|---|
ctx.request.header | ctx.header | 可获取或者设置请求头对象 |
ctx.request.headers | ctx.headers | 同上 |
ctx.request.method | ctx.method | 可获取或者设置请求方式 |
ctx.request.href | ctx.href | 可获取完整的href |
ctx.request.origin | ctx.origin | 仅获取协议、主机、端口号 |
ctx.request.host | ctx.host | 仅获取主机、端口号 |
ctx.request.hostname | ctx.hostname | 仅获取主机 |
ctx.request.url | ctx.url | 仅获取url部分 |
ctx.request.path | ctx.path | 仅获取path部分 |
ctx.request.query | ctx.query | 仅获取query部分 |
ctx.request.ip | ctx.ip | 获取请求的ip |
结果如下:
ctx.request.href http://localhost:3000/api/get?name=Jack
ctx.request.origin http://localhost:3000
ctx.request.host localhost:3000
ctx.request.hostname localhost
ctx.request.url /api/get?name=Jack
ctx.request.path /api/get
ctx.request.query { name: 'Jack' }
params
对于动态的URL params,可以使用ctx.params获取,注意!这是vue-router所提供的一个方法,它并不存在于ctx.request对象中:
import * as Koa from "koa"
import * as Router from 'koa-router'
const server: Koa = new Koa()
const router: Router = new Router()
server.use(router.routes())
router.get("/api/get/:id?", async (ctx: Koa.Context, next: Koa.Next) => {
await next()
// http://localhost:3000/api/get/8?k1=v1
console.log(ctx.params.id); // 8
ctx.response.body = "HELLO KOA!"
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
get请求参数
对于URL中的query请求参数来说,你可以直接通过ctx.request.query进行获取:
import * as Koa from "koa"
import * as Router from 'koa-router'
const server: Koa = new Koa()
const router: Router = new Router()
server.use(router.routes())
router.get("/api/get/:id?", async (ctx: Koa.Context, next: Koa.Next) => {
await next()
// http://localhost:3000/api/get/8?k1=v1
console.log(ctx.request.query); // { k1: 'v1' }
ctx.response.body = "HELLO KOA!"
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
post请求参数
对于请求体中的data请求参数来说,我们可以通过第三方插件koa-body来让它的获取更加的方便。
因为默认的ctx.request对象中没有获取请求体的方法,但是使用koa-body插件后它会向ctx.request中封装一个body属性,调用它你将会获得data请求参数对象。
要想使用koa-body插件,需要对其进行安装:
$ npm install koa-body --save
$ npm install @types/koa__cors --save
示例如下:
import * as Koa from "koa"
import * as Router from 'koa-router'
import * as koaBody from "koa-body"
const server: Koa = new Koa()
const router: Router = new Router()
server.use(router.routes())
server.use(koaBody({
// 是否支持 multipart-formdata 的表单
multipart: true,
}))
router.post('/api/post', async (ctx, next) => {
// 等待之前的插件处理完成后再运行Middleware View Function
// 否则你必须将server.use()的插件应用语句放在
// Middleware View Function的下面
await next()
console.log(ctx.request.body);
ctx.response.body = "HELLO KOA!"
});
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
上传文件
koa-body插件同样支持对文件自动上传,如下所示,我们在使用之前需要对其进行一些小小的配置,在获取文件后它将自动进行上传。
我们可通过ctx.request.files参数获取文件对象,与ctx.request.body一样,它也是koa-body所封装的方法:
import * as fs from "fs"
import * as path from "path"
import * as Koa from "koa"
import * as Router from 'koa-router'
import * as koaBody from "koa-body"
const server: Koa = new Koa()
const router: Router = new Router()
server.use(router.routes())
server.use(koaBody({
// 是否支持 multipart-formdata 的表单
multipart: true,
formidable: {
// 上传的目录
uploadDir: path.join(__dirname, 'upload'),
// 保持文件的后缀
keepExtensions: true,
// 最大支持上传8M的文件
maxFieldsSize: 8 * 1024 * 1024,
// 文件上传前的设置
onFileBegin: (name: string, file: any): void => {
const filePath: string = path.join(__dirname, "upload");
// 检查是否有upload目录
if (!fs.existsSync(filePath)) {
fs.mkdirSync(filePath);
console.log("mkdir success!");
}
}
}
}))
router.post('/api/upload', async (ctx, next) => {
// 等待之前的插件处理完成后再运行Middleware View Function
// 否则你必须将server.use()的插件导入语句放在
// Middleware View Function的下面
await next()
// 获取文件对象avatar
const avatar: any | null = ctx.request.files["avatar"]
// 自动写入...
// 将上传后的信息自动返回
ctx.response.set("Content-Type", "application/json")
ctx.response.body = JSON.stringify(avatar)
});
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
文件对象中包含的属性如下:
{
"size": 文件大小,
"path": "上传路径",
"name": "文件原本的名字",
"type": "image/jpeg",
"mtime": "文件最后修改时间"
}
koa-body配置
以下是koa-body在进行使用时的一级配置项:
参数名 | 描述 | 类型 | 默认值 |
---|---|---|---|
patchNode | 将请求体打到原生 node.js 的ctx.req中 | Boolean | false |
patchKoa | 将请求体打到 koa 的 ctx.request 中 | Boolean | true |
jsonLimit | JSON 数据体的大小限制 | String / Integer | 1mb |
formLimit | 限制表单请求体的大小 | String / Integer | 56kb |
textLimit | 限制 text body 的大小 | String / Integer | 56kb |
encoding | 表单的默认编码 | String | utf-8 |
multipart | 是否支持 multipart-formdate 的表单 | Boolean | false |
urlencoded | 是否支持 urlencoded 的表单 | Boolean | true |
text | 是否解析 text/plain 的表单 | Boolean | true |
json | 是否解析 json 请求体 | Boolean | true |
jsonStrict | 是否使用 json 严格模式,true 会只处理数组和对象 | Boolean | true |
formidable | 配置更多的关于 multipart 的选项 | Object | {} |
onError | 错误处理 | Function | function(){} |
stict | 严格模式,启用后不会解析 GET, HEAD, DELETE 请求 | Boolean | true |
以下是koa-body在进行使用时的二级(formidable)配置项:
参数名 | 描述 | 类型 | 默认值 |
---|---|---|---|
maxFields | 限制字段的数量 | Integer | 1000 |
maxFieldsSize | 限制字段的最大大小 | Integer | 2 * 1024 * 1024 |
uploadDir | 文件上传的文件夹 | String | os.tmpDir() |
keepExtensions | 保留原来的文件后缀 | Boolean | false |
hash | 如果要计算文件的 hash,则可以选择 md5/sha1 | String | false |
multipart | 是否支持多文件上传 | Boolean | true |
onFileBegin | 文件上传前的一些设置操作 | Function | function(name,file){} |
ctx.req
ctx.request是Koa框架所封装的请求对象,而ctx.req则是原生的http库的请求对象。
我们不建议对其进行使用,具体所包含的属性可以参照http库中的req对象。
响应相关
ctx.response
ctx是一个上下文对象,你可以通过ctx.response获得本次HTTP服务的响应对象。
在响应对象中它也提供了很多属性或者方法可供我们使用,以下只例举一些比较常见的:
属性/方法 | 简写 | 描述 |
---|---|---|
ctx.response.header | 无 | 可获取或者设置响应头对象 |
ctx.response.headers | 无 | 同上 |
response.get() | ctx.get() | 可获取某个响应头字段 |
response.has() | ctx.has() | 可检测某个响应头字段是否存在 |
response.set() | ctx.set() | 用来设置单个响应头字段与值,也可用一个对象来设置多个响应头字段与值 |
response.remove() | ctx.remove() | 可删除某个响应头字段 |
ctx.response.body | ctx.body | 可获取或者设置响应体,可设置string、Buffer、Stream、Object或者Array的JSON字符串以及null |
ctx.response.status | ctx.status | 可获取或者设置响应码 |
ctx.response.message | ctx.message | 可获取或者设置响应信息,它与响应码相关联 |
ctx.response.redirect | ctx.redirect | 可进行重定向跳转 |
ctx.response.type | ctx.type | 获取或者设置响应的mime-type类型 |
设置响应码
响应码一般来说不需要我们手动设置,它的默认值大多数情况下总是200或者204.
如果你想手动进行设置,可参照下面这个示例:
router.get("/api/get", async (ctx: Koa.Context, next: Koa.Next) => {
ctx.response.status = 403;
ctx.response.message = "Reject service";
})
设置响应头
如果你没有使用TypeScript来规范你的项目代码,则可以直接对响应头做出结构改变的操作:
router.get("/api/get", async (ctx: Koa.Context, next: Koa.Next) => {
ctx.response.headers = { "Content-Type": "text/plain; charset=utf-8" };
ctx.response.body = "HELLO KOA!";
})
如果你使用了TypeScript来规范你的项目代码,则必须通过ctx.response.set()方法来设置响应头:
// 设置一个 ctx.response.set(k, v)
ctx.response.set("Content-Type", "text/plain; charset=utf-8");
// 设置多个 ctx.response.set({k1 : v1, k2 : v2, ...})
ctx.response.set({
"Content-Type": "text/plain; charset=utf-8",
"Token" : "=fdss9d9k!-=f23"
});
重定向
对于需要跳转的路由,可以使用ctx.response.redirect()方法来进行跳转:
import * as Koa from "koa"
import * as Router from 'koa-router'
const server: Koa = new Koa()
const router: Router = new Router()
server.use(router.routes())
router.get("/", async (ctx: Koa.Context, next: Koa.Next) => {
ctx.redirect("/index");
ctx.response.status = 302;
})
router.get("/index", async (ctx: Koa.Context, next: Koa.Next) => {
ctx.response.body = "HELLO KOA!";
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
CORS跨域
利用第三方插件@koa/cors解决跨域问题:
$ npm install @koa/cors
它的使用非常简单,直接server.use()即可,当然你也可以对其进行详细配置,这里不再进行配置举例:
import * as Koa from "koa"
import * as cors from "@koa/cors"
const server: Koa = new Koa()
server.use(cors())
ctx.res
ctx.response是Koa框架所封装的响应对象,而ctx.res则是原生的http库的响应对象。
我们不建议对其进行使用,具体所包含的属性可以参照http库中的res对象。
jsonwebtoken
基本介绍
Koa框架中提供了Cookie相关的操作,但是Cookie在目前的项目开发中使用的比较少,故这里不再进行例举,而是推荐使用第三方插件jsonwebtoken来生成JWT进行验证。
如果你不了解JWT,我之前也有写过相关的技术文章,你可以搜索并进行参考。
现在我假设你已经了解过了JWT相关的知识,让我开始第一步,安装jsonwebtoken这个插件吧。
$ npm install jsonwebtoken --save
安装后之后我们需要在src目录中新建一个JWT目录以及一个index.js文件,用来JWT存放相关的代码:
$ mkdir ./src/jwt
$ touch ./src/jwt/index.ts
封装使用
一般的手动签发token我们需要用到下面3种类型的数据:
- header:头部信息,可定义加密类型、加密方式
- playload:荷载信息,可定义token过期时间、签发者、接受者以及私有声明信息,但不建议存放敏感信息
- secret:密钥,该密钥只能由服务端所知晓
但是jsonwebtoken对其进行封装,直接使用config来配置即可,以下是签发和验证token的案例,默认它将采用HASH256算法进行JWT格式封装:
import * as JWT from "jsonwebtoken"
// 服务端的字符串,绝对保密
const secret = "=937dce32&?f99"
function issueToken(userID: number, userName: string, expiration: number = 86400 * 14) {
// 定义荷载信息,不要存放敏感的诸如用户密码之类的数据
const playLoad = {
id: String(userID),
name: userName,
}
// 定义配置文件,下面有一些选项也是属于荷载信息的一部分,如过期时间、签发时间、面向谁签发的
const config = {
// 定义头部信息
header: {},
// 过期时间、按秒计算,也可以是字符串,如1day、1min等
expiresIn: expiration,
// 在签发后多久之前这个token是无用的,如果是数字则是按秒计算
notBefore: `120ms`,
// 面向谁签发的
audience: userName,
// 发行者是谁
issuer: "Node.js KOA",
// 该token的发布主题
subject: "demo",
// 不使用时间戳
noTimestamp: true,
}
// 第一个对象中也可以添加额外的属性,它将作为荷载信息被格式化
return JWT.sign(playLoad, secret, config)
}
function verifyToken(token: string | string[]): { verify: boolean, playLoad: { id: string, name: string, nbf: number, exp: number, aud: string, iss: string, sub: string } | null } {
// 如果没有抛出异常,则验证成功
try {
return {
playLoad: JWT.verify(token, secret),
verify: true
}
}
// 如果抛出了异常,则验证失败
catch {
return {
playLoad: null,
verify: false
}
}
}
export { issueToken, verifyToken }
使用案例:
// 手动传入用户ID以及用户姓名还有token过期时间
const token = issueToken(19, "Jack", 7);
// 传入token验证是否成功
console.log(verifyToken(token));
验证成功返回的结果:
{
playLoad: {
id: '19',
name: 'Jack',
nbf: 1633537512,
exp: 1633537519,
aud: 'Jack',
iss: 'Node.js KOA',
sub: 'demo'
},
verify: true
}
实战演示
我们以一个简单的案例来进行说明,后端有2个api接口,分别是index和login。
若用户第一次访问主页,则必须先进行登录后才能访问主页,此后的20s内用户不用再重新登录:
import * as Koa from "koa"
import * as Router from 'koa-router'
import * as koaBody from 'koa-body'
import * as cors from "@koa/cors"
import * as JWT from "./jwt/index"
// 模拟数据库
const userDataBase: { id: number, username: string, password: string, age: number }[] = [
{ id: 1, username: "Jack", password: "123456", age: 18 }
]
const server: Koa = new Koa()
const router: Router = new Router()
server.use(cors())
server.use(koaBody({
// 是否支持 multipart-formdata 的表单
multipart: true,
}))
server.use(router.routes())
server.use(async (ctx: any, next: any) => {
await next()
// 由于所有返回的数据格式都是JSON,故这里直接进行生命
ctx.response.set("Content-Type", "application/json");
})
router.get("/api/index", async (ctx: Koa.Context, next: Koa.Next) => {
await next()
const token: string | string[] = ctx.request.get("JWT");
// 如果能获取token就进行验证,判断是否是伪造请求
if (token) {
const { verify, playLoad } = JWT.verifyToken(token)
if (verify) {
// 验证通过,直接返回playLoad给前端
ctx.response.body = JSON.stringify({
code: 200,
message: playLoad
})
}
else {
// 验证未通过,token无效或者已过期
ctx.response.body = JSON.stringify({
code: 403,
message: "Please do not forgery information"
})
}
}
// 获取不到token,你应该先进行登录
else {
ctx.response.body = JSON.stringify({
code: 401,
message: "please log in first"
})
}
})
router.post("/api/login", async (ctx: Koa.Context, next: Koa.Next) => {
await next()
const name: string = ctx.request.body.name;
const pwd: string = ctx.request.body.pwd;
// 如果用户存在于数据库中,就签发token,并且设置在响应头中返回
for (const row of userDataBase) {
if (row.username === name && row.password === pwd) {
const token = JWT.issueToken(row.id, row.username, 20);
// 设置响应头JWT
ctx.response.set("JWT", token);
ctx.response.body = JSON.stringify({
code: 200,
message: "login successful"
});
return
}
}
// 用户不存在
ctx.response.body = JSON.stringify({
code: 406,
message: "Login error, username or password is incorrect"
})
})
server.listen(3000, "localhost", 128, (): void => {
console.log("server started at http://localhost:3000");
})
代码测试
下面我们使用postMan来测试一下这个功能过程。
首先是用户第一次到我们的网站尝试访问主页,此时会提示它应该先进行登录:
然后我们进行登录,下面是登录错误的情况,数据库没有这个用户:
下面是登录成功后的情况,它会返回给你一个JWT的响应字段:
我们需要复制这个JWT响应字段的value值,并且将它添加到访问index时的请求头里,注意请求头的字段也必须是JWT,因为我们的后端做了限制,那么接下来的20s内你对index的访问都将是正常的:
如果token过期或者被伪造,它将提示你不要伪造token,其实这里有心的朋友可以处理的更细节一点:
其他插件推荐
好了,关于Koa框架的基本使用目前就到此结束了。
下面推荐一些Koa框架中可能会被使用到的插件:
- koa-compress:用于压缩内容,以便更快的完成HTTP响应
- koa-logger:提供日志输出
- koa-static:提供静态文件服务
- koa-view:提供视图模板渲染,适用于前后端混合开发
- koa-jwt:也是一款提供JWT认证的插件,不同于jsonwebtoken,它的局限性比较清
Node.js Koa框架学习笔记的更多相关文章
- Node.js Express 框架学习
转载:http://JavaScript.ruanyifeng.com/nodejs/express.html#toc0 感觉很牛的样子,不过觉得对初学者没太大用,里面很多例子用的api都没有详细的说 ...
- NODE.JS开发指南学习笔记2
1.核心模块 核心模块是Node.js的心脏,由一些精简高效的库组成,为其提供了基本的API.2.全局对象 global.所有的的全局变量都是其属性.其根本的作用是作为全局变量的宿主.3.全局变量 1 ...
- NODE.JS开发指南学习笔记
1.Node.js是什么 Node.js是一个让JS运行在服务器端的开发平台,它可以作为服务器向用户提供服务.Node.js中的javascript只是Core javascript,或者说是ECMA ...
- Koa – 更加强大的下一代 Node.js Web 框架
Koa 是 Express 的开发团队设计的下一代 Web 框架,其目的是为 Web 应用程序提供更小,更具表现力,更坚实的基础.Koa 没有核捆绑任何中间件,并提供了一套优雅的方法,使服务器端开 ...
- 全端开发必备!10个最好的 Node.js MVC 框架
Node.js 是最流行的 JavaScript 服务端平台,它允许建立可扩展的 Web 应用程序.Node.js 包含不同类型的框架,如 MVC 框架.全栈框架.REST API 以及大量的服 ...
- 【360开源】thinkjs:基于Promise的Node.js MVC框架 (转)
thinkjs是360奇舞团开源的一款Node.js MVC框架,该框架底层基于Promise来实现,很好的解决了Node.js里异步回调的问题.360奇舞团(奇虎75Team),是奇虎360公司We ...
- Yii框架学习笔记(二)将html前端模板整合到框架中
选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...
- 十款最佳Node.js MVC框架
十款最佳Node.js MVC框架摘要:Node.js是JavaScript中最为流行的框架之一,易于创建可扩展的Web应用.本文分享十款最佳的JavaScript框架. Node.js是JavaSc ...
- Underscore.js 源码学习笔记(上)
版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}()); 这样的东西,我们应该知道这是一个 IIFE(立即执行 ...
随机推荐
- docker 安装Hive
转自:https://www.cnblogs.com/upupfeng/p/13452385.html#%E9%83%A8%E7%BD%B2hive 使用docker快速搭建hive环境 记录一下 ...
- return 和 return false 的区别
return返回null,起到中断方法执行的效果,只要不return false事件处理函数将会继续执行,表单将提交. return false,事件处理函数会取消事件,不再继续向下执行.比如表单将终 ...
- Jemeter压力测试
Jmeter教程 简单的压力测试 Jmeter是一个非常好用的压力测试工具. Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测试需要的脚本写好. 转载自小坦克:https: ...
- Java编码的问题
<转> 由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定我们的Java源程序的编码格式,则javac.exe首先获得我们操作系统默认采用的编码格式,也即在编译j ...
- 技术调研,IDEA 插件怎么开发「脚手架、低代码可视化编排、接口生成测试」?
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 不踩些坑,根本不是成熟的码农! 你觉得肯德基全家桶是什么?一家人一起吃的桶吗,就那么 ...
- MySQL alter table时执行innobackupex全备再看Seconds_Behind_Master
1.场景描述 早上7:25 接到Report中心同学告警,昨天业务报表数据没有完整跑出来,缺少500位业务员的数据,并且很快定位到,缺少的是huabei_order库上的数据.Report中心的数据是 ...
- Spring系列之不同数据库异常如何抽象的?
前言 使用Spring-Jdbc的情况下,在有些场景中,我们需要根据数据库报的异常类型的不同,来编写我们的业务代码.比如说,我们有这样一段逻辑,如果我们新插入的记录,存在唯一约束冲突,就会返回给客户端 ...
- 详细解读go语言中的chnanel
Channel 底层数据结构 type hchan struct { qcount uint // 当前队列中剩余元素个数 dataqsiz uint // 环形队列长度,即可以存放的元素个数 buf ...
- Mysql常用sql语句(5)- as 设置别名
测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 需要注意,创建数据库和创建表的语句博文都在前面哦 整个 ...
- Abp Vnext3 vue-admin-template(三获取用户信息)
因为获取用户比较简单,只需要把用户名及头像地址赋值即可(也许理解错误,如果发现请告知谢谢), 首先将src\api\usr.js中的url请求地址改为以下代码 export function getI ...