eggjs笔记

一、egg.js

1. 什么是egg.js

  • express是基于es5的web开发框架
  • koa1.x 是express原班人员打造的基于es6的web开发框架
  • koa2.x 是express原班人员打造的基于es7的web开发框架
  • egg 是阿里基于koa有约束和规范的企业级web开发框架

2. egg.js的基本使用

2.1 安装

# 初始化
npm init -y
# 安装egg,egg模块是egg.js的核心模块
npm i egg -S
# 安装egg-bin,这个模块用于快速启动项目
npm i egg-bin -D

2.2 启动:快速启动项目,用于本地开发调试的模块

// package.json
"scripts": {"dev": "egg-bin dev"
}

2.3 目录结构

egg-project
├── package.json
├── app.js(可选)
├── agent.js(可选)
├── app
|   ├── router.js
│   ├── controller
│   │   └── home.js
│   ├── service(可选)
│   │   └── user.js
│   ├── middleware(可选)
│   │   └── response_time.js
│   ├── schedule(可选)
│   │   └── my_task.js
│   ├── public(可选)
│   │   └── reset.css
│   ├── view(可选)
│   │   └── home.tpl
│   └── extend(可选)
│       ├── helper.js(可选)
│       ├── request.js(可选)
│       ├── response.js(可选)
│       ├── context.js(可选)
│       ├── application.js(可选)
│       └── agent.js(可选)
├── config
|   ├── plugin.js
|   ├── config.default.js
│   ├── config.prod.js
|   ├── config.test.js(可选)
|   ├── config.local.js(可选)
|   └── config.unittest.js(可选)
└── test├── middleware|   └── response_time.test.js└── controller└── home.test.js

由框架约定的目录:

  • app/router.js 用于配置 URL 路由规则,具体参见 Router。
  • app/controller/** 用于解析用户的输入,处理后返回相应的结果,具体参见 Controller。
  • app/service/** 用于编写业务逻辑层,建议使用,具体参见 Service。
  • app/middleware/** 用于编写中间件,具体参见 Middleware。
  • app/public/** 用于放置静态资源,具体参见内置插件 egg-static。
  • app/extend/** 用于框架的扩展,具体参见 框架扩展。
  • config/config.{env}.js 用于编写配置文件,具体参见 配置。
  • config/plugin.js 用于配置需要加载的插件,具体参见 插件。
  • test/** 用于单元测试,具体参见 单元测试。
  • app.js 和 agent.js 用于自定义启动时的初始化工作,具体参见 启动自定义。关于 agent.js 的作用,参见 Agent 机制。

由内置插件约定的目录:

  • app/public/** 用于放置静态资源,具体参见内置插件 egg-static。
  • app/schedule/** 用于定时任务,具体参见 定时任务。

若需自定义自己的目录规范,参见 Loader API

  • app/view/** 用于放置模板文件,具体参见 模板渲染。
  • app/model/** 用于放置领域模型,如 egg-sequelize 等领域类相关插件。

2.4 app/router.js

在router.js中必须暴露出去一个方法,这个方法接受一个参数,这个参数就算服务器的实例对象

module.exports = app => {console.log(app);/*** {env: 'local',name: 'egg',baseDir: 'C:\\Users\\Administrator\\Desktop\\egg',subdomainOffset: 2,config: '<egg config>',controller: '<egg controller>',httpclient: '<egg httpclient>',loggers: '<egg loggers>',middlewares: '<egg middlewares>',router: '<egg router>',serviceClasses: '<egg serviceClasses>'}*/// 从服务器实例上解构出处理路由的对象和处理控制器的对象const { router, controller } = app// 监听路由请求// controller.home:相当于拿到了controller目录下的home.js(如果有多级可以通过.语法使用)router.get('/', controller.home.index)
}

2.5 app/controller/xx.js(xx.js可自定义名称)

这里是app/controller/home.js

const Controller = require('egg').Controllerclass HomeController extends Controller {async index() {this.ctx.body = 'hello egg.js'}
}module.exports = HomeController

在eggjs中会自动给控制器挂载一些属性:

  • this.ctx:当前请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法。
  • this.app:当前应用 Application 对象的实例,通过它我们可以拿到框架提供的全局对象和方法。
  • this.service:应用定义的 Service,通过它我们可以访问抽象出的业务层,等价于 this.ctx.service。
  • this.config:应用运行时的配置项。
  • this.logger:logger 对象,上面有四个方法(debug、info、warn、error),分别代表打印四个不同级别的日志。使用方法和效果与 context logger 中介绍的相同,但是通过这个 logger 对象记录的日志,在日志前面会加上打印该日志的文件路径,以便快速定位日志打印位置。

3. egg.js 处理get/post请求

app/router.js

module.exports = app => {const { router, controller } = approuter.get('/getquery', controller.home.getquery)router.get('/getparams/:name/:age', controller.home.getparams)router.post('/postbody', controller.home.postbody)
}

app/controller/home.js

const Controller = require('egg').Controllerclass HomeController extends Controller {// 获取query参数async getquery() {// let query = this.ctx.request.querylet query = this.ctx.querythis.ctx.body = query}// 获取动态路由参数async getparams() {let params = this.ctx.paramsthis.ctx.body = params}// 获取post请求参数,post请求默认会被阻止掉,需要在 config/config.default.js 中添加配置async postbody() {let body = this.ctx.request.bodythis.ctx.body = body}
}module.exports = HomeController

注意:post请求默认会被阻止掉,需要在 config/config.default.js 中添加配置

// config/config.default.js
module.exports = {security: {// 跨站点请求csrf: {ignoreJSON: true, // 默认为 false,设置为 true 时,会忽略所有 content-type 为 `application/json` 的请求}},
};

4. 处理静态资源

app目录下,新建public目录,在浏览器中通过http://xxx.com/public/xxx.png即可访问

5. 处理动态资源

需要使用插件(插件:特殊的中间件)

5.1 插件的使用

  1. 安装
npm i egg-view-ejs
  1. 对插件进行配置,在config目录下新建plugin.js文件
// exports.xxx
exports.ejs = {enable: true,package: 'egg-view-ejs' // 配置使用的插件
}
  1. config.default.js中添加配置
// config/config.default.js
module.exports = {// view目录下的文件view: {mapping: {'.html': 'ejs' // 在哪个后缀的文件使用插件}}
};
  1. app目录中新建view目录,将动态网页放到这个目录下,在控制器中通过上下文render方法渲染
const Controller = require('egg').Controllerclass HomeController extends Controller {async index() {// app/view/demo.htmlawait this.ctx.render('demo', { msg: '数据' })}
}module.exports = HomeController

6. 数据处理

在eggjs中无论是数据库中的数据还是处理网络数据,都是在Service中处理的

每一次用户请求,框架都会实例化对应的 Service 实例。因为它继承自 egg.Service。和控制器一样,Service类的this上也挂载了很多属性:

  • this.ctx:当前请求的上下文 Context 对象实例。通过它,我们可以获取框架封装的处理当前请求的各种便捷属性和方法。

  • this.app:当前应用 Application 对象实例。通过它,我们可以访问框架提供的全局对象和方法。

  • this.service:应用定义的 Service。通过它,我们可以访问到其他业务层,等同于 this.ctx.service。

  • this.config:应用运行时的 配置项。

  • this.logger:logger 对象。它有四个方法(debug,info,warn,error),分别代表不同级别的日志。使用方法和效果与 context logger 所述一致。但通过这个 logger 记录的日志,在日志前会加上文件路径,方便定位日志位置。

this.ctx上下文对象上还挂载了其他的属性:

  • 使用 this.ctx.curl 发起网络调用。
  • 通过 this.ctx.service.otherService 调用其他 Service。
  • 调用 this.ctx.db 发起数据库操作,db 可能是插件预挂载到 app 上的模块。
  1. app目录下,新建service目录,新建js文件
// app/service/home.js
const Service = require('egg').Serviceclass HomeService extends Service {async findNews() {// 在Service定义的方法中处理数据库和网络的数据即可// 1. 发送get请求,不带参数let response = await this.ctx.curl('http://jsonplaceholder.typicode.com/posts')// 2. 发送get请求,带参数let response = await this.ctx.curl('http://jsonplaceholder.typicode.com/comments?postId=1')// 3. 发送post请求,不带参数let response = await this.ctx.curl('http://jsonplaceholder.typicode.com/posts', {method: 'POST'})// 4. 发送post请求,带参数let response = await this.ctx.curl('xxx', {method: 'POST',data: {id: 1}})return response.data}
}module.exports = HomeService

注意:

  1. service目录必须放在app目录中
  2. service目录支持多级目录,如果是多级目录,在调用的时候可以通过链式调用
  3. service目录下的js文件,如果是以_首字母大写,那么在调用的时候必须转换成驼峰命名:
    get_user.js => getUser
    GetUser.js => getUser
  1. 在控制器中调用

通过ctx上下文的service获取

// app/controller/home.js
const Controller = require('egg').Controllerclass HomeController extends Controller {async news() {let data = await this.ctx.service.home.findNews()this.ctx.body = data}
}module.exports = HomeController
  1. 路由写接口
// app/router.js
module.exports = app => {const { router, controller } = approuter.get('/news', controller.home.news)
}

7. 处理cookie

生成cookie和获取cookie

  1. 不加密
class HomeController extends Controller {async setCookie() {this.ctx.cookies.set('name', 'xiaotian', {path: '/',maxAge: 24 * 60 * 60 * 1000, // 有效时间httpOnly: true, // 只允许在服务端修改signed: true, // 生成cookie的时候,同时生成一个签名,根据config/config.default.js的keys设置。默认为true})this.ctx.body = '设置成功'}async getCookie() {let cookie = this.ctx.cookies.get('name')this.ctx.body = '获取cookie成功, ' + cookie}
}
  1. 加密和解密 encrypt: true
class HomeController extends Controller {async setCookie() {this.ctx.cookies.set('name', 'xiaotian', {path: '/',maxAge: 24 * 60 * 60 * 1000, // 有效时间httpOnly: true, // 只允许在服务端修改signed: true, // 生成cookie的时候,同时生成一个签名,根据config/config.default.js的keys设置。默认为trueencrypt: true // 对cookie加密后再保存})this.ctx.body = '设置成功'}async getCookie() {let cookie = this.ctx.cookies.get('name', {signed: true,encrypt: true})this.ctx.body = '获取cookie成功, ' + cookie}
}

8. 处理日志

eggjs自动生成logs目录

8.1 日志分类

  • ${appInfo.name}-web.log,例如 example-app-web.log,应用相关日志,供应用开发者使用的日志。我们在绝大多数情况下都在使用它。
  • egg-web.log:框架内核、插件日志。
  • common-error.log:ctx.logger.err 输出的错误日志
  • egg-agent.log:进程日志,框架和使用到 agent 进程执行任务的插件会打印一些日志到这里。
  • egg-schedule.log:定时任务的日志。

8.2 日志切割

在eggjs中默认会自动切割日志,每一天就是一个新的日志文件

9. 定时任务

9.1 使用场景:

  • 定时进行文件切割,临时文件删除
  • 定时上报应用状态

9.2 如何编写定时任务:

  1. app目录下新建schedule目录

所有的定时任务都统一存放在 app/schedule 目录下,每一个文件都是一个独立的定时任务,可以配置定时任务的属性和要执行的方法。

const Subscription = require('egg').Subscription;class UpdateCache extends Subscription {// 通过 schedule 属性来设置定时任务的执行间隔等配置static get schedule() {return {interval: '1m', // 1 分钟间隔type: 'all', // all表示当前服务器上所有相同node进程(之前说过同一个node项目可以开启多个进程)都执行};}// subscribe 是真正定时任务执行时被运行的函数async subscribe() {const res = await this.ctx.curl('http://www.api.com/cache', {dataType: 'json',});// cache 是自定义的this.ctx.app.cache = res.data;}
}module.exports = UpdateCache;

还可以简写为:

module.exports = {schedule: {interval: '1m', // 1 分钟间隔type: 'all',},async task(ctx) {const res = await ctx.curl('http://www.api.com/cache', {dataType: 'json',});ctx.app.cache = res.data;},
};

这个定时任务会在每一个 Worker 进程上每 1 分钟执行一次,将远程数据请求回来挂载到 app.cache 上。(cache是自定义的)

10. 启动自定义

我们常常需要在应用启动期间进行一些初始化工作,待初始化完成后,应用才可以启动成功,并开始对外提供服务。

框架提供了统一的入口文件(app.js)进行启动过程自定义。这个文件需要返回一个 Boot 类。我们可以通过定义 Boot 类中的生命周期方法来执行启动应用过程中的初始化工作。

框架提供了以下 生命周期函数 供开发人员处理:

  • 配置文件即将加载,这是最后动态修改配置的时机(configWillLoad);
  • 配置文件加载完成(configDidLoad);
  • 文件加载完成(didLoad);
  • 插件启动完毕(willReady);
  • worker 准备就绪(didReady);
  • 应用启动完成(serverDidReady);
  • 应用即将关闭(beforeClose)。

在根目录下新建app.js

// app.js
class AppBootHook {constructor(app) {this.app = app;}configWillLoad() {// 此时 config 文件已经被读取并合并,但还并未生效// 这是应用层修改配置的最后机会// 注意:此函数只支持同步调用// 例如:参数中的密码是加密的,在此处进行解密this.app.config.mysql.password = decrypt(this.app.config.mysql.password);// 例如:插入一个中间件到框架的 coreMiddleware 之间const statusIdx = this.app.config.coreMiddleware.indexOf('status');this.app.config.coreMiddleware.splice(statusIdx + 1, 0, 'limit');}async didLoad() {// 所有配置已经加载完毕// 可以用来加载应用自定义的文件,启动自定义服务// 例如:创建自定义应用的实例this.app.queue = new Queue(this.app.config.queue);await this.app.queue.init();// 例如:加载自定义目录this.app.loader.loadToContext(path.join(__dirname, 'app/tasks'), 'tasks', {fieldClass: 'tasksClasses',});}async willReady() {// 所有插件已启动完毕,但应用整体尚未 ready// 可进行数据初始化等操作,这些操作成功后才启动应用// 例如:从数据库加载数据到内存缓存this.app.cacheData = await this.app.model.query(QUERY_CACHE_SQL);}async didReady() {// 应用已启动完毕const ctx = await this.app.createAnonymousContext();await ctx.service.Biz.request();}async serverDidReady() {// http/https 服务器已启动,开始接收外部请求// 此时可以从 app.server 获取 server 实例// 可以执行一些需要初始化的文件}
}module.exports = AppBootHook;

11. 操作mysql

11.1 安装

npm i --save egg-mysql

11.2 开启插件

// config/plugin.js
exports.mysql = {enable: true,package: 'egg-mysql'
};

11.3 配置

// config/config.default.js
exports.mysql = {// 单数据库信息配置client: {// hosthost: 'mysql.com',// 端口号port: '3306',// 用户名user: 'test_user',// 密码password: 'test_password',// 数据库名database: 'test'},// 是否加载到 app 上,默认开启app: true,// 是否加载到 agent 上,默认关闭agent: false
};

11.4 使用

await app.mysql.query(sql, values); // 单实例可以直接通过 app.mysql 访问

11.5 如何编写 CRUD 语句

Create

可以直接使用 insert 方法插入一条记录

// 插入
const result = await this.app.mysql.insert('posts', { title: 'Hello World' }); // 在 posts 表中,插入 title 为 Hello World 的记录// SQL 语句相当于
// INSERT INTO `posts`(`title`) VALUES('Hello World');console.log(result);
// 输出为
// {
//   fieldCount: 0,
//   affectedRows: 1,
//   insertId: 3710,
//   serverStatus: 2,
//   warningCount: 2,
//   message: '',
//   protocol41: true,
//   changedRows: 0
// }// 判断插入成功
const insertSuccess = result.affectedRows === 1;
Read

可以直接使用 get 方法或 select 方法获取一条或多条记录。select 方法支持条件查询与结果定制。 可以使用 count 方法对查询结果的所有行进行计数。

  • 查询一条记录
const post = await this.app.mysql.get('posts', { id: 12 });// SQL 语句相当于
// SELECT * FROM `posts` WHERE `id` = 12 LIMIT 0, 1;
  • 查询全表
const results = await this.app.mysql.select('posts');// SQL 语句相当于
// SELECT * FROM `posts`;
  • 条件查询和结果定制
const results = await this.app.mysql.select('posts', { // 搜索 posts 表where: { status: 'draft', author: ['author1', 'author2'] }, // WHERE 条件columns: ['author', 'title'], // 要查询的字段orders: [['created_at','desc'], ['id','desc']], // 排序方式limit: 10, // 返回数据量offset: 0, // 数据偏移量
});// SQL 语句相当于
// SELECT `author`, `title` FROM `posts`
// WHERE `status` = 'draft' AND `author` IN('author1','author2')
// ORDER BY `created_at` DESC, `id` DESC LIMIT 0, 10;
  • 统计查询结果的行数
const total = await this.app.mysql.count('posts', { status: 'published' }); // 统计 posts 表中 status 为 published 的行数// SQL 语句相当于
// SELECT COUNT(*) FROM `posts` WHERE `status` = 'published'
Update

可以直接使用 update 方法更新数据库记录。

// 修改数据
const row = {id: 123,name: 'fengmk2',otherField: 'other field value', // 其他想要更新的字段modifiedAt: this.app.mysql.literals.now, // 数据库服务器上的当前时间
};
const result = await this.app.mysql.update('posts', row); // 更新 posts 表中的记录// SQL 语句相当于
// UPDATE `posts` SET `name` = 'fengmk2', `modifiedAt` = NOW() WHERE `id` = 123;// 判断更新成功
const updateSuccess = result.affectedRows === 1;// 如果主键是自定义的 ID 名称,如 custom_id,则需要在 `where` 里配置
const row2 = {name: 'fengmk2',otherField: 'other field value', // 其他想要更新的字段modifiedAt: this.app.mysql.literals.now, // 数据库服务器上的当前时间
};const options = {where: {custom_id: 456}
};
const result2 = await this.app.mysql.update('posts', row2, options); // 更新 posts 表中的记录// SQL 语句相当于
// UPDATE `posts` SET `name` = 'fengmk2', `modifiedAt` = NOW() WHERE `custom_id` = 456 ;// 判断更新成功
const updateSuccess2 = result2.affectedRows === 1;
Delete

可以直接使用 delete 方法删除数据库记录。

const result = await this.app.mysql.delete('posts', {author: 'fengmk2',
});// SQL 语句相当于
// DELETE FROM `posts` WHERE `author` = 'fengmk2';

11.6 直接执行 SQL 语句

插件本身也支持拼接与直接执行 SQL 语句。使用 query 方法可以执行合法的 SQL 语句。

const postId = 1;
const results = await this.app.mysql.query('update posts set hits = (hits + ?) where id = ?', [1, postId]);// => update posts set hits = (hits + 1) where id = 1;

12. eggjs的配置文件

config
|- config.default.js  所有环境都会加载(如果其他文件有同名,会覆盖掉默认的)
|- config.prod.js  只有上线环境才会加载
|- config.unittest.js  只有测试环境才会加载
|- config.local.js  只有开发环境才会加载

config.default.js 为默认的配置文件,所有环境都会加载这个配置文件,一般也会作为开发环境的默认配置文件。

当指定 env 时,会同时加载默认配置和对应的配置(具名配置)文件。具名配置和默认配置将合并成最终配置,具名配置项会覆盖默认配置文件的同名配置。例如,prod 环境会加载 config.prod.jsconfig.default.js 文件,config.prod.js 会覆盖 config.default.js 的同名配置。

但通常会用 cross-env 第三方库来配置项目环境

二、pm2

1. pm2 的好处

  1. pm2 进程守护可以在程序崩溃后自动重启
  2. pm2 自带日志记录功能,可以很方便的记录错误日志和自定义日志
  3. pm2 可以启动多个node进程,充分利用服务器资源

2. pm2 的基本使用

2.1 安装pm2

npm i pm2 -g

2.2 查看pm2版本

pm2 --version

2.3 启动pm2

pm2 start index.js

3. pm2 常用指令

3.1 启动应用程序

pm2 start index.js

3.2 列出启动的所有应用程序

pm2 list

3.3 重启应用程序

pm2 restart 应用id/name

3.4 杀死并重启所有进程

pm2 restart all

3.5 查看应用程序详细信息

pm2 info 应用id/namepm2 show

3.6 显示指定应用程序的日志

pm2 log 应用id/name

3.7 监控应用程序

pm2 monit 应用id/name

3.8 停止应用程序

pm2 stop 应用id/name

3.9 停止所有应用程序

pm2 stop all

3.10 关闭并删除指定应用程序

pm2 delete 应用id/name

3.11 关闭并删除所有应用程序

pm2 delete all

3.12 杀死pm2管理的所有进程

pm2 kill

4. pm2常用配置

  1. 新建pm2.confif.json文件
{"name": "应用程序名称","script": "入口文件名称","watch": true, // 文件被修改是否自动重启"ignore_watch": [ // 忽略监听哪些文件的改变"node_modules","logs"],"error_file": "logs/错误日志文件名称.log","out_file": "logs/自定义日志文件名称.log","log_date_format": "yyyy-MM-dd HH:mm:ss" // 给日志添加时间
}
  1. 运行
pm2 start pm2.config.json

5. 负载均衡

node是单线程的,服务器是多核的,要充分利用服务器资源,可以使用pm2启动多个node进程,只需要在配置文件中增加 instances 配置,可以启动多个node进程(想启动几个就启动几个,但是不能超过服务器cpu的核数)

{"name": "应用程序名称","script": "入口文件名称","watch": true, // 文件被修改是否自动重启"ignore_watch": [ // 忽略监听哪些文件的改变"node_modules","logs"],"error_file": "logs/错误日志文件名称.log","out_file": "logs/自定义日志文件名称.log","log_date_format": "yyyy-MM-dd HH:mm:ss", // 给日志添加时间"instances": 4 // 开启多个node进程,不能超过cpu核数
}

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

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

相关文章

【python】OpenCV—Nighttime Low Illumination Image Enhancement

文章目录 1 背景介绍2 代码实现3 原理分析4 效果展示5 附录np.ndindexnumpy.ravelnumpy.argsortcv2.detailEnhancecv2.edgePreservingFilter 1 背景介绍 学习参考来自&#xff1a;OpenCV基础&#xff08;24&#xff09;改善夜间图像的照明 源码&#xff1a; 链接&#xff1a…

目标检测中损失函数的精妙作用:精确度与鲁棒性的双重保障

目标检测中损失函数的精妙作用&#xff1a;精确度与鲁棒性的双重保障 目标检测是计算机视觉领域的核心任务之一&#xff0c;它旨在从图像或视频中识别和定位多个对象。在目标检测算法中&#xff0c;损失函数扮演着至关重要的角色&#xff0c;它指导模型学习如何准确地预测边界…

Linux 文件系统以及日志管理

一、inode 与block 1. inode 与block详解 在文件存储硬盘上&#xff0c;硬盘的最小存储单位叫做“扇区”&#xff0c;每个为512字节。 操作系统读取硬盘的时候&#xff0c;不会一个个扇区地读取&#xff0c;这样效率太低&#xff0c;而是一次性连续读取多个扇区,即一次性读取…

利用Java构建高可用的实时数据监控系统

利用Java构建高可用的实时数据监控系统 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 随着信息技术的迅猛发展&#xff0c;实时数据监控系统在现代软件…

PyMuPDF 操作手册 - 09 API - Page属性方法和简短说明

文章目录 一、Page属性方法和简短说明一、Page属性方法和简短说明 https://pymupdf.readthedocs.io/en/latest/page.html Method/Attribute属性方法Short Description简短说明Page.add_caret_annot()仅限 PDF:添加插入符号注释Page.add_circle_annot()仅限 PDF:添加圆圈…

微服务粒度难题:找到合适的微服务大小

序言 在微服务架构风格中&#xff0c;微服务通常设计遵循SRP&#xff08;单一职责原则&#xff09;&#xff0c;作为一个独立部署的软件单元&#xff0c;专注于做一件事&#xff0c;并且做到极致。作为开发人员&#xff0c;我们常常倾向于在没有考虑为什么的情况下尽可能地将服…

头歌资源库(20)最大最小数

一、 问题描述 二、算法思想 使用分治法&#xff0c;可以将数组递归地分割成两部分&#xff0c;直到数组长度为1或2。然后比较这两部分的最大、次大、次小、最小数&#xff0c;最终得到整个数组中的最大两个数和最小两个数。 算法步骤如下&#xff1a; 定义一个函数 findMinM…

Java - 程序员面试笔记记录 实现 - Part3

4.1 线程与进程 线程是程序执行的最小单元&#xff0c;一个进程可以拥有多个线程&#xff0c;各个线程之间共享程序的内存空间以及一些进程级资源&#xff0c;但拥有自己的栈空间。 4.3 Java 多线程 方法一&#xff1a;继承 Thread 类&#xff0c;重写 run 方法&#xff1b;…

如何在Java中实现实时数据同步与更新

如何在Java中实现实时数据同步与更新 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. 引言 在现代的分布式系统中&#xff0c;实时数据同步和更新是保持数…

二分法查找有序表的通用算法(可查链表,数组,字符串...等等)

find_binary函数 注意事项&#xff1a; &#xff08;1&#xff09;你设计的迭代器模板中必须有using value_type T&#xff0c;且有加减运算功能&#xff0c;其本上能与C标准库std中一样。 &#xff08;2&#xff09;集合必须是有序的。 下面是函数代码&#xff1a; /// &…

一次建表语句触发的ORA-600报错分析

​ 某次在客户Oracle数据库执行一条建表语句时&#xff0c;报出ORA-600错误。 报错代码如下&#xff1a; ORA-00600: 内部错误代码, 参数: [rwoirw: check ret val], [], [], [], [], [], [], [], [], [], [], [] 相关的建表语句如下&#xff1a; ​ 在报错发生后&#xff0c;…

Ubuntu / Openwrt使用lua发送http和https请求

Ubuntu / Openwrt使用lua发送http和https请求 1、Ubuntu配置以支持lua发送http和https请求1.1、配置apt镜像源1.2、安装相关lua关联包 2、Openwrt配置menuconfig支持lua发送http和https请求2.1、配置menuconfig 3、Ubuntu / Openwrt 使用lua发送http和https请求3.1、测试发送ht…

Android studio开发入门教程详解(复习)

引言 本文为个人总结Android基础知识复习笔记。如有不妥之处&#xff0c;敬请指正。后续将持续更新更多知识点。 文章目录 引言UITextView文本基本用法实际应用常用属性和方法 Button按钮处理点击事件 EditText输入框基本属性高级特性 ImageView图片ImageView的缩放模式 Prog…

Qt中udp指令,大小端,帧头帧尾实际示例

前言 虽然QT中&#xff0c;udp发送和接收&#xff0c;其实非常简单&#xff0c;但是实际工作中&#xff0c;其实涉及到帧头帧尾&#xff0c;字节对齐&#xff0c;以及大小端序的问题。比如网络中&#xff0c;正规的一般都是大端序&#xff0c;而不是小端序&#xff0c;大多数的…

不到 5 元的随身 WiFi 刷 Debian 系统 做轻量家庭服务器

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 前不久在某宝均价 5 元买了两个随身 WiFi,拆机看了看丝印都是 MSM8916 ,正好是红米 2 同款的骁龙 410 的芯片,可以刷个 Debian 当作家庭服务器来跑一些轻量的服务。 不过手气不是很好,两个都是 512M + 4G 的配置…

go 泛型函数里调用公共方法

在go泛型中&#xff0c;有时候会用到从泛型函数中调用结构体变量的方法 demo&#xff1a; package mainimport "fmt"type T1 struct {Name stringAge int }func (this T1) F1() string {return fmt.Sprintf("name: %v", this.Name) fmt.Sprintf("…

单机安装基于LNMP结构的WordPress网站 web与数据库服务分离

网站的类型&#xff1a; Jave:LNMT PHP:LNMP Python: LNMU 项目部署&#xff1a; 1.项目的类型&#xff08;项目的开发语言&#xff09; 2.项目运营平台的技术选择 3.尽快让项目运行起来 all in one部署 4. 架构的优化 配置ansible管理环境 配置nginx 配置数据库服务…

day11_homework_need2submit

Homework 编写—个将ts或mp4中视频文件解码到yuv的程序 yuv数据可以使用如下命令播放: ffplay -i output yuv-pix_fmt yuv420p-s 1024x436 要求: ffmpeg解析到avpacket并打印出pts和dts字段完成解码到avframe并打印任意字段完成yuv数据保存 // teminal orders on bash cd ex…

11.SQL注入-盲注基于(base on boolian)

SQL注入-盲注基于boolian案例利用 首先总结一下sql语句中的函数意思 #查看当前所在的数据库 mysql> select database(); ------------ | database() | ------------ | pikachu | ------------ 1 row in set (0.00 sec)#函数substr里1是从第几位开始取字符&#xff0c;2…

油猴Safari浏览器插件:Tampermonkey for Mac 下载

Tampermonkey 是一个强大的浏览器扩展&#xff0c;用于运行用户脚本&#xff0c;这些脚本可以自定义和增强网页的功能。它允许用户在网页上执行各种自动化任务&#xff0c;比如自动填写表单、移除广告、改变页面布局等。适用浏览器&#xff1a; Tampermonkey 适用于多数主流浏览…