MongoDB从入门到实战之Docker快速安装MongoDB

前言      在上一篇文章中带领带同学们快速入门MongoDB这个文档型的NoSQL数据库,让大家快速的了解了MongoDB的基本概念。这一章开始我们就开始实战篇教程,为了快速把MongoDB使用起来我将会把MongoDB在Docker容器中安装起来作为开发环境使用。然后我这边MongoDB的可视化工具用的是Navicate。废话不多说,我们先花了几分钟开始的把MongoDB环境搭建起来。MongoDB从入门到实战的相关教程MongoDB从入门到实战之MongoDB简介👉MongoDB从入门到实战之MongoDB快速入门👉MongoDB从入门到实战之Docker快速安装MongoDB👉YyFlight.ToDoList项目源码地址GitHub地址:https://github.com/YSGStudyHards/YyFlight.ToDoList查看可用的MongoDB版本访问DokcerHub中的MongoDB镜像库地址:https://hub.docker.com/_/mongo/tags可以通过 Sort by 查看其他版本的MongoDB,查看最新版本MongoDB镜像(mongo:latest):https://hub.docker.com/_/mongo/tags?page=1&name=latest 此外,我们还可以用docker search mongo命令来查看可用版本: 拉取最新版本的MongoDB镜像docker pull mongo:latest注意:tag是可选的,tag表示标签,多为软件的版本,默认是latest版本(最新版)验证MongoDB镜像是否成功拉取到本地使用以下命令来查看MongoDB镜像是否成功拉取到本地:docker images创建并运行一个MongoDB容器docker run -itd --name mongo-test -p 27017:27017 mongo --auth参数说明:-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。--name mongo-test:容器名称-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务(注意:安全问题,MongoDB默认是不开启权限验证的,不过设置了这里就相当于修改MongoDB的配置auth=ture启用权限访问)。进入创建的MongoDB容器docker exec -it  mongo-test mongoshMongoDB报错"ongoServerError: not authorized on admin to execute command"MongoDB默认是不需要用户密码就可以连接的,如果使用命令报错"ongoServerError: not authorized on admin to execute command ",则表示当前登陆用户不具备相应权限。解决办法:在admin数据库中通过创建一个用户,赋予用户root权限。# 进入admin数据库use admin# 创建一个超级用户db.createUser(    {        user:"root",        pwd:"123456",        roles:[{role:"root",db:"admin"}]    });#授权登录db.auth('root','123456')MongoDB用户权限管理MongoDB添加用户命令说明user字段,为新用户的名字。pwd字段,用户的密码。cusomData字段,为任意内容,例如可以为用户全名介绍。roles字段,指定用户的角色,可以用一个空数组给新用户设定空角色。在roles字段,可以指定内置角色和用户定义的角色。超级用户的role有两种,userAdmin或者userAdminAnyDatabase(比前一种多加了对所有数据库的访问,仅仅是访问而已)。db是指定数据库的名字,admin是管理数据库。不能用admin数据库中的用户登录其他数据库。注:只能查看当前数据库中的用户,哪怕当前数据库admin数据库,也只能查看admin数据库中创建的用户。首先切换到admin数据库中# 进入admin数据库use admin创建admin超级管理员用户指定用户的角色和数据库:(注意此时添加的用户都只用于admin数据库,而非你存储业务数据的数据库)(在cmd中敲多行代码时,直接敲回车换行,最后以分号首尾)db.createUser(    { user: "admin",      customData:{description:"superuser"},    pwd: "admin",      roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]    }  )创建一个不受访问限制的超级用户拥有所有权限,不受任何限制db.createUser(    {        user:"root",        pwd:"123456",        roles:[{role:"root",db:"admin"}]    });创建一个业务数据库管理员用户只负责某一个或几个数据库的増查改删db.createUser({    user:"user001",    pwd:"123456",    customData:{        name:'jim',        email:'jim@qq.com',        age:18,    },    roles:[        {role:"readWrite",db:"db001"},        {role:"readWrite",db:"db002"},        'read'// 对其他数据库有只读权限,对db001、db002是读写权限    ]})MongoDB数据库角色说明数据库用户角色:read、readWrite;数据库管理角色:dbAdmin、dbOwner、userAdmin;集群管理角色:clusterAdmin、clusterManager、4. clusterMonitor、hostManage;备份恢复角色:backup、restore;所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase超级用户角色:root内部角色:__systemMongoDB中的role详解Read:允许用户读取指定数据库readWrite:允许用户读写指定数据库dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profileuserAdmin:允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限root:只在admin数据库中可用。超级账号,超级权限服务器配置27017的开放端口Navicat连接mongoDB并创建集合和添加数据1.连接MongoDB点击这个位置2、连接参数介绍:stand alone:独立的shard cluster:分片集群replica set:复制集SRV record:SRV记录是DNS服务器的数据库中支持的一种资源记录的类型,它记录了哪台计算机提供了哪个服务这么一个简单的信息。SRV 记录:一般是为Microsoft的活动目录设置时的应用。DNS可以独立于活动目录,但是活动目录必须有DNS的帮助才能工作。为了活动目录能够正常的工作,DNS服务器必须支持服务定位(SRV)资源记录,资源记录把服务名字映射为提供服务的服务器名字。活动目录客户和域控制器使用SRV资源记录决定域控制器的IP地址。一般情况下,我们连接只需要连接主库查数据,所以选择独立的这个连接方式就可以,填写好常规参数可以点击测试连接是否正常,即可连接!3、新建MongoDB数据库(MyMondoDBTest)     4、新建MongoDB文档(Books)并添加数据

MongoDB从入门到实战之MongoDB快速入门

前言   上一章节主要概述了MongoDB的优劣势、应用场景和发展史。这一章节将快速的概述一下MongoDB的基本概念,带领大家快速入门MongoDB这个文档型的NoSQL数据库。MongoDB从入门到实战的相关教程MongoDB从入门到实战之MongoDB简介👉MongoDB从入门到实战之MongoDB快速入门👉MongoDB从入门到实战之Docker快速安装MongoDBMongoDB从入门到实战之MongoDB工作常用操作命令MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(1)-后端项目框架搭建MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-系统数据集合设计MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-MongoDB连接和基本操作封装MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(4)-Blazor快速入门MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(5)-Blazor前端框架搭建MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(6)-用户登录注册模块开发MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(7)-用户JWT授权验证MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(8)-TodoList增删改查功能开发MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(9)-Docker打包并部署MongoDB是什么?MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似Json的Bson格式,因此可以存储比较复杂的数据类型。MongoDB 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。并且MongoDB-4.2版本开始已经支持分布式事务功能。简而言之的话就是:MongoDB是一个文档型的NoSQL数据库,用于构建高并发、高可用和高扩展的互联网应用程序。MongoDB概念解析  无论我们学习什么数据库都应该先了解对应数据库的基本概念,在MongoDB中基本的概念是文档、集合、数据库,下面我们挨个介绍。MongoDB和RDBMS术语概念对比虽然 MongoDB 与传统的 RDBMS 共享一些相同的术语,但其他一些是 NoSQL 数据库所独有的。为了帮助了解它们的分别,下表将 RDBMS 使用的术语与 MongoDB 使用的术语进行比较:RDBMS术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins 嵌入式文档表连接,MongoDB不支持表连接只支持嵌入式文档primary keyprimary key主键,MongoDB自动将_id字段设置为主键(默认键 _id 由 MongoDB 提供)MongoDB文档(Documment)概述:文档是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点。MongoDB 的文档可以理解为关系型数据库(Mysql)的一行记录MongoDB 将数据记录为 BSON 格式的文档BSON 是 JSON 文档的二进制表示,但它支持的数据类型更加丰富MongoDB文档由字段和值对组成,并具有以下结构: field1: value1, field2: value2, field3: value3, fieldN: valueN }MongoDB Bson格式介绍Bson是一种类Json的一种二进制形式的存储格式,简称Binary Json,它和Json一样,支持内嵌的文档对象和数组对象,但是Bson有Json没有的一些数据类型,如Date和BinData类型。Bson可以做为网络数据交换的一种存储形式,这个有点类似于Google的Protocol Buffer,但是Bson是一种schema-less的存储形式,它的优点是灵活性高,但它的缺点是空间利用率不是很理想,Bson有三个特点:轻量性、可遍历性、高效性,{“hello":"world"} 这是一个Bson的例子,其中"hello"是key name,它一般是cstring类型,字节表示是cstring::= (byte*) "/x00" ,其中*表示零个或多个byte字节,/x00表示结束符;后面的"world"是value值,它的类型一般是string,double,array,binarydata等类型。JSON vs BSON:       JSON的局限性,比如它只有null、布尔、数字、字符串、数组和对象这几种数据类型,没有日期类型,只有一种数字类型,无法区分浮点数和整数,也没法表示正则表达式或者函数。BSON是一种类JSON的二进制形式的存储格式,Binary JSON,支持内嵌的文档对象和数组对象,如Date和BinData类型,MongoDB使用BSON做为文档数据存储和网络传输格式。MongoDB数据类型下表为MongoDB中常用的一些数据类型:详情介绍:参见BSON Types:https://www.docs4dev.com/docs/zh/mongodb/v3.6/reference/reference-bson-types.html数据类型描述String字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。Integer整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。Boolean布尔值。用于存储布尔值(真/假)。Double双精度浮点值。用于存储浮点值。Min/Max keys将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。Arrays用于将数组或列表或多个值存储为一个键。Timestamp时间戳。记录文档修改或添加的具体时间。Object用于内嵌文档。Null用于创建空值。Symbol符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。Date日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。Object ID对象 ID。用于创建文档的 ID。Binary Data二进制数据。用于存储二进制数据。Code代码类型。用于在文档中存储 JavaScript 代码。Regular expression正则表达式类型。用于存储正则表达式。下面简单介绍一下其中几个比较重要的类型:ObjectId       每次插入一条数据系统都会自动插入一个_id键,键值不可以重复,它可以是任何类型的,也可以手动的插入,默认情况下它的数据类型是ObjectId,由于MongoDB在设计之初就是用作分布式数据库,所以使用ObjectId可以避免不同数据库中_id的重复(如果使用自增的方式在分布式系统中就会出现重复的_id的值)。ObjectId使用12字节的存储空间,每个字节可以存储两个十六进制数字,所以一共可以存储24个十六进制数字组成的字符串,在这24个字符串中,前8位表示时间戳,接下来6位是一个机器码,接下来4位表示进程id,最后6位表示计数器。601e2b6b aa203c c89f 2d31aa ↑ ↑ ↑ ↑时间戳 机器码 进程id 计数器String      BSON 字符串为 UTF-8.通常,在对 BSON 进行序列化和反序列化时,每种编程语言的驱动程序都会从该语言的字符串格式转换为 UTF-8.这样就可以轻松地将大多数国际字符存储在 BSON 字符串中。[1]此外,MongoDB $regex查询在正则表达式字符串中支持 UTF-8。Timestamps       BSON 具有特殊的时间戳类型供内部 MongoDB 使用,并且不与常规Date类型关联。此内部时间戳记类型是 64 位值,其中:最重要的 32 位是time_t值(自 Unix 时代以来的秒数),最低有效 32 位是在给定的秒内进行操作的ordinal增量。尽管 BSON 格式为低位字节序,因此首先存储了最低有效位,但是mongod实例在所有平台上始终将time_t值先于ordinal值进行比较,无论字节序如何。在单个mongod实例中,时间戳记值始终是唯一的。在复制中,oplog有一个ts字段。该字段中的值反映了使用 BSON 时间戳值的操作时间。Date      BSON Date 是一个 64 位整数,代表自 Unix 纪元(1970 年 1 月 1 日)以来的毫秒数。这导致可以 traceback 到过去和 Future 约 2.9 亿年的日期范围。MongoDB索引种类:_id索引:绝大多数集合默认建立的索引;对于每个插入的数据,mongodb都会自动生成一条唯一的_id字段。单键索引:不自动创建,值单一,例如字符串,数字或者日期。多键索引:不自动创建,值有多个,如数组,与单键索引创建形式相同,区别在于字段的值。复合索引:查询条件不只一个时,需要建立复合索引。过期索引TTL:是在一段时间后会过期的索引,索引过期后,相应的数据会删除(不仅仅是索引删除,还有数据);适用场景:在一段时间之后会时效的数据,比如用户的登陆信息、存储的日志;建立方法,db.test.ensureIndex({time:1},{expireAfterSeconds:10})秒数。其限制:存储在过期索引字段的值必须是指定的时间类型(ISODate或者其数据,不能使用时间戳,否则不能被自动删除);指定ISODate数组,则按照最小的时间进行删除;过期索引不能是复合索引;删除时间不精确(MongoDB默认60s执行一个删除过程,删除本身也需要时间)全文索引:对字符串与字符串数组创建全文课搜索的索引。地理位置索引:将一些点的位置存储在MongoDB中,创建索引后,可以按照位置来查找其他点。MongoDB GUI可视化工具  俗话说工欲善其事,必先利其器。选择一款高效的GUI可视化客户端管理工具,对于我们的日常开发效率都有大大的提升。下面推荐几款比较好用的MongoDB GUI可视化管理工具!Navicat for MongoDB官网下载地址:http://www.navicat.com.cn/download/navicat-for-mongodb在 Navicat for MongoDB 使用文档:https://www.navicat.com.cn/company/aboutus/blog/257-working-with-documents-in-navicat-for-mongodb  老牌的数据库管理工具,支持多种数据库的集成,已集成 MongoDB 类型,属于付费型管理工具。好处是用会了一个 DB 版的 Navicat,所有 DB 版都会很顺手,维持一套操作习惯,如果再肌肉记忆一些快捷键,会更加高效。Robo 3T (Robomong) 官网下载地址:https://robomongo.org/  Robo 3T 前身是 Robomongo,后被 3T 公司收购,是一款免费开源的 GUI 管理工具。支持 MongoDB 4.0+,轻量级 GUI,支持语法填充等等。适用于 Windows,macOS 和 Linux 系统。Studio 3T官网下载地址:https://studio3t.com/download/  超过 100,000 的开发人员和数据库管理员使用 Studio 3T 作为 MongoDB GUI 的首选。Studio 3T 属于收费工具,30 天的免费试用期,Studio 3T 具有更多更强大的功能并提供企业支持服务,支持副本集、独立主机和分片集群连接,支持导入导出,SQL 查询,语法填充,支持 MongoDB 4.0+ 等等。适用于 Windows,macOS 和 Linux。MongoDB Compass官网下载地址:https://www.mongodb.com/try/download/compass官网教程:https://www.mongodb.com/docs/manual/reference/connection-string/  MongoDB 亲儿子系列,官方自己推出的 GUI 可视化管理工具,功能有限。免费简洁,不支持 SQL 查询,支持性能监控。适用于 Windows,macOS 和 Linux 系统。NoSQLBooster for MongoDB官网下载地址:https://nosqlbooster.com/downloads  NoSQLBooster for MongoDB(以前叫 MongoBooster)风格有点类似于 EasyUI,支持副本集,独立主机和分片群集连接,提供了全面的服务器监控工具、fluent 查询构建器、SQL 查询、查询代码、任务调度、ESNext 支持和真正的智能感知体验等。提供了付费和免费两种版本。适用于 Windows,macOS 和 Linux 系统。NoSQL Manager for MongoDB Professional官网下载地址:https://www.mongodbmanager.com/download  从 2.2 到 4.4 全面支持 MongoDB 和 MongoDB Enterprise 版本。功能齐全的 MongoDB UI Shell。具有代码自动完成功能,语法突出显示和提示。支持副本集,独立主机和分片群集连接,导入导出,简单查看和管理所有 MongoDB 对象:数据库,集合,视图,索引,用户,角色和功能等等。提供了付费和免费两种版本。参考文章MongoDB 概念解析MongoDB GUI可视化客户端管理工具推荐

MongoDB从入门到实战之MongoDB简介

前言  相信很多同学对MongoDB这个非关系型数据库都应该挺熟悉的,在一些高性能、动态扩缩容、高可用、海量数据存储、数据价值较低、高扩展的业务场景下MongoDB可能是我们的首选,因为MongoDB通常能让我们以更低的成本解决问题(包括学习、开发、运维等成本)。接下来的一个月博主将会从基础出发,编写一个关于使用MongoDB从入门到实战的相关教程,该项目后端使用的是.NET7、前端页面使用Blazor、使用MongoDB存储数据,更多相关内容大家可以看目录中的MongoDB从入门到实战的相关教程。该系列教程可作为.NET Core入门项目进行学习,感兴趣的小伙伴可以关注博主和我一起学习共同进步。MongoDB从入门到实战的相关教程MongoDB从入门到实战之MongoDB简介👉MongoDB从入门到实战之MongoDB快速入门MongoDB从入门到实战之Docker快速安装MongoDBMongoDB从入门到实战之MongoDB工作常用操作命令MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(1)-后端项目框架搭建MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-系统数据集合设计MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-MongoDB连接和基本操作封装MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(4)-Blazor快速入门MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(5)-Blazor前端框架搭建MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(6)-用户登录注册模块开发MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(7)-用户JWT授权验证MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(8)-TodoList增删改查功能开发MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(9)-Docker打包并部署MongoDB是什么?MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似Json的Bson格式,因此可以存储比较复杂的数据类型。MongoDB 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。并且MongoDB-4.2版本开始已经支持分布式事务功能。简而言之的话就是:MongoDB是一个文档型的NoSQL数据库,用于构建高并发、高可用和高扩展的互联网应用程序。什么是Bson格式?Bson是一种类Json的一种二进制形式的存储格式,简称Binary Json,它和Json一样,支持内嵌的文档对象和数组对象,但是Bson有Json没有的一些数据类型,如Date和BinData类型。Bson可以做为网络数据交换的一种存储形式,这个有点类似于Google的Protocol Buffer,但是Bson是一种schema-less的存储形式,它的优点是灵活性高,但它的缺点是空间利用率不是很理想,Bson有三个特点:轻量性、可遍历性、高效性,{“hello":"world"} 这是一个Bson的例子,其中"hello"是key name,它一般是cstring类型,字节表示是cstring::= (byte*) "/x00" ,其中*表示零个或多个byte字节,/x00表示结束符;后面的"world"是value值,它的类型一般是string,double,array,binarydata等类型。MongoDB的优势1.高性能MongoDB提供高性能的数据持久性。对嵌入式数据模型的支持减少了数据库系统上的IO活动。索引支持更快的查询,并且包含嵌入式文档和数组的键。文本索引解决搜索的需求;TTL索引解决历史数据自动过期的需求;地理位置索引可用于构建各种 O2O 应用;2.高可用MongoDB的复制工具称为副本集(reolica set),它包含提供自动故障转移和数据冗余。3.海量数据存储内置GridFS,支持海量存储。4.丰富的查询支持MongoDB支持丰富的查询语言,支持读写(CRUD)操作、比如数据聚合、文本搜索、地理空间查询等。5.支持多种编程语言MongoDB支持多种流行编程语言如C,C++,C# / .NET,Erlang,Haskell,Java,PHP,Python,Go等多种语言。6、其他特点如可拓展性强模式自由、动态模式、灵活的文档模型等。MongoDB的劣势单机可靠性比较差。在集群分片中的数据分布不均匀。磁盘空间占用比较大。大数据量持续插入,写入性能有较大波动。MongoDB业务应用场景四高场景应对:传统的关系型数据库(如MySQL,MS SQL Server),在数据操作的四高需求以及应对Web2.0的网站需求面前显得力不从心,而MongoDB可更好的应对四高需求:High performance(高性能):对数据库高并发读写的需求。Huge Storage(海量存储):对海量数据的高效率存储和访问的需求。High Scalability && High Availability(高可扩展性和高可用性):对数据库的高可扩展性和高可用性的需求。具体应用场景:游戏应用:使用MongoDB作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便进行查询与更新。物流应用:使用MongoDB存储订单信息,订单状态在运送过程中会不断更新,以MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。社交应用:使用MongoDB存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且MongoDB非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并在写入和读取方面都相对较快。视频直播:使用MongoDB存储用户信息、礼物信息等。大数据应用:使用MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。这些应用场景中,数据操作方面的共同特点是:对于下面的这些数据,我们更适合使用 MongoDB来实现数据的存储:数据量大。读写操作频繁。价值较低的数据,对事务性要求不高。MongoDB语言支持MongoDB有官方的驱动如下:CC++C# / .NETGoErlangHaskellJavaJavaScriptLispnode.JSPerlPHPPythonRubyScalaMongoDB发展史MongoDB 最初由一个名为 10gen 的组织在 2007 年开发的,并在 2009 年 2 月发布了 MongoDB 1.0 版本,其中提供了大部分基本的查询功能。2009 年 12 月发布了 MongoDB 1.2 版本,其中引入了 map-reduce(一种编程模型,用于大规模数据集(大于 1TB)的并行运算),让 MongoDB 拥有了支持大规模数据处理的能力。2010 年 3 月发布了 MongoDB 1.4 版本,该版本中引入了创建后台索引的功能。2010 年 8 月发布了 MongoDB 1.6 版本,该版本种引入了一些主要特性,比如用于水平伸缩的分片、具备自动故障转移能力的副本集以及对 IPv6 的支持。2012 年 8 月发布了 MongoDB 2.2 版本,该版本引入了聚合管道功能,可以将多个数据处理步骤组合成一个操作链。2013 年 3 月发布了 MongoDB 2.4 版本,并在 Mongo Shell(一个与 MongoDB 交互的组件)中引入了文本搜索和谷歌的 V8 JS 引擎等增强功能。另外,还发布了 MongoDB 的企业版,企业版中另外提供了监控和安全集成等附加功能。2015 年 3 月发布了 MongoDB 3.0 版本,该版本中引入了新的 WiredTiger 存储引擎、可插拔存储引擎 API 并增加了 50 个副本集限制和安全改进。同年晚些时候又发布了 MongoDB 3.2 版本,该版本增加了文档验证、部分索引的功能。2017 年 11 月发布了 MongoDB 3.6 版本,该版本为多集合连接查询、变更流和使用 JSON 模式进行文档验证提供了更好的支持。MongoDB 3.6 是微软 Azure CosmosDB(截止到 2020 年 8 月)能够支持的最新版本。2018 年 6 月发布了 MongoDB 4.0 版本,该版本提供了跨文档处理事务的能力。2019 年 8 月发布了 MongoDB 4.2 版本,该版本中引入分布式事务处理的能力。参考文章https://www.mongodb.com/docs/drivers/

MongoDB安全加固,防止数据库攻击删除勒索威胁

前言:  今天发现前段时间自己搭建的一个系统的MongoDB数据找不到了,觉得很奇妙,然后登上MongoDB数据库发现多了一个名为READ__ME_TO_RECOVER_YOUR_DATA的数据库,里面还有一个README的集合里面包含了下面描述的勒索信息。没错我的MongoDB数据库被攻击了,不过还好这个系统里面的数据都是自己学习的一些没有任何价值的数据。但是换个角度,假如在公司层面遇到这样的事情那一定是天大的事情了,你要面临公司、客户信息安全问题。所以无论是自己学习,还是工作方面我们都要养成时刻做好保护自己软件程序,及其数据源安全的问题。今天主要来讲讲为什么MongoDB这么容易遭遇勒索的原因和我们该如何做好防护措施。README文档内容如下:All your data is a backed up. You must pay 0.06 BTC to 168i2g62fcXwu3GYAJM4FAksxEmNnDjCkm 48 hours for recover it. After 48 hours expiration we will leaked and exposed all your data. In case of refusal to pay, we will contact the General Data Protection Regulation, GDPR and notify them that you store user data in an open form and is not safe. Under the rules of the law, you face a heavy fine or arrest and your base dump will be dropped from our server! You can buy bitcoin here, does not take much time to buy https://localbitcoins.com or https://buy.moonpay.io/ After paying write to me in the mail with your DB IP: rambler+1duuz@onionmail.org and/or mariadb@mailnesia.com and you will receive a link to download your database dump.翻译过来就是:你所有的数据都有备份。你必须支付0.06比特币到168i2g62fcXwu3GYAJM4FAksxEmNnDjCkm 48小时来恢复它。在48小时到期后,我们将泄露和暴露您的所有数据。在拒绝付款的情况下,我们将联系通用数据保护条例(GDPR),并通知他们您以公开形式存储用户数据,这是不安全的。根据法律规定,你将面临巨额罚款或逮捕你的数据库将从我们的服务器上删除!你可以在这里购买比特币,不需要太多时间购买https://localbitcoins.com或https://buy.moonpay.io/支付后写信给我的邮件与你的DB IP: rambler+1duuz@onionmail.org和/或mariadb@mailnesia.com,你会收到一个链接下载你的数据库转储。MongoDB漏洞成因:  在初始安装完毕的时候MongoDB都默认有一个admin数据库,此时admin数据库是空的,没有记录权限相关的信息!当admin.system.users一个用户都没有时,即使mongod启动时添加了—auth参数,如果没有在admin数据库中添加用户,此时不进行任何认证还是可以做任何操作(不管是否是以—auth 参数启动),直到在admin.system.users中添加了一个用户。加固的核心是只有在admin.system.users中添加用户之后,mongodb的认证,授权服务才能生效。遭遇勒索的原因分析:  首先我这个MongoDB数据库是安装在Docker上面的,因为都是是有默认安装的方式,并且安装完成以后都没有开启默认权限验证登录的功能。开启MongoDB服务时不添加任何参数时默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增删改高危动作)而且可以远程访问数据库。并且我还使用了27017这个默认端口,所以黑客可以通过批量扫描Ip很快就能检索到。MongoDB安全加固措施: 1、配置账号密码,开启MongoDB的权限访问Docker安装MongoDB时开启权限验证的命令:docker run -itd --name mongo-test -p 27017:27017 mongo --auth参数说明:-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。--name mongo-test:容器名称-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务(注意:安全问题,MongoDB默认是不开启权限验证的,不过设置了这里就相当于修改MongoDB的配置auth=ture启用权限访问)。2、使用非默认的端口,减少互联网上被端口扫描并定向爆破的概率对MongoDB监听的端口和IP做调整有下面2个目的IP: 默认监听IP为127.0.0.1,我们可能需要开放特定的CIDR来让处于不同主机上的客户端可以连接. 最简单的就是直接允许任意IP的客户端连接,这时CIDR为0.0.0.0.但是这也是很危险的一个操作,意味着全球互联网上的任意一台电脑都可以连接上来,这虽然方便但是也是最危险的,建议指定具体的CIDR,这样可以排除互联网的大量肉鸡进行恶意的连接。端口: 默认的监听端口为27017,我们可以改为其他端口,躲开互联网上的恶意程序的扫描和连接。修改/etc/mongod.confvim /etc/mongod.conf在端口和IP监听部分我们改为如下设置:#network interfacesnet: port: 7017 bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.修改完成后重启服务:systemctl restart mongod如果重启失败,可能是SELinux的安全策略限制了MongoDB使用新的端口,我们需要放行MongoDB使用新的端口:[root@localhost thinktik]# semanage port -a -t mongod_port_t -p tcp 7017bash: semanage: command not found# 如果出现上面的错误,可以这样这个解决:[root@localhost thinktik]# dnf install policycoreutils-python-utilsLast metadata expiration check: 0:10:50 ago on Mon 27 Dec 2021 03:11:19 PM CST....SELinux放行后,我们继续重启即可.配置防火墙如果你需要服务被互联网上的其他电脑访问,那么你需要配置防火墙,运行你的端口被访问# 开放7017端口[root@thinkvm01 thinktik]# firewall-cmd --zone=public --add-port=7017/tcp --permanent# 重载防火墙[root@thinkvm01 thinktik]# firewall-cmd --reload3、限制访问IPMongoDB可以限制只允许某一特定IP来访问,只要在启动时加一个参数bind_ip即可,或者在/etc/mongodb.conf中添加bind_ip配置,如下:# 方法一mongod --bind_ip 127.0.0.1,10.0.133.14 # 方法二在/etc/mongodb.conf文件中添加以下内容:bind_ip = 127.0.0.1,10.0.133.14这样之后,MongoDB服务端只有127.0.0.1和10.0.133.14这两个 IP 可以访问了。4、关闭万网访问权限关闭外网访问权限,也就是限定只能是内网访问。在/etc/mongodb.conf中配置:bind_ip 127.0.0.1预防方法:经过这里勒索经历,我总结了一下几点:不要裸奔,首先把你数据库的账户密码设置好,做好权限验证登录!尽量不要把你的数据库摆上公网,业务处理都尽量在内网进行!如果要摆上公网,一定要设置好访问权限,绑定访问源 IP!记得养成数据备份的好习惯!参考文章:https://new.qq.com/rain/a/20210330A06AYX00https://www.cnblogs.com/fundebug/p/how-to-protect-mongodb.htmlhttps://juejin.cn/post/7049315722039656479

值得推荐的.NET/.NET Core ORM框架汇总

前言:最近有很多同学问我.NET方面有哪些好用的ORM框架,我觉得这方面的介绍网上应该会介绍的比较全面文章,于是我想搜一篇全面的介绍文章发给他们结果我发现网上说来说去基本上就是那几个,于是就有了这篇文章。该篇文章已收录到【DotNetGuide(C#/.NET/.NET Core学习、工作、面试指南)👉】GitHub知识库中欢迎大家前往订阅(有帮助的话别忘了给我一颗小星星⭐),假如大家有更好的ORM框架推荐可以前往GitHub仓库中留言💖!什么是ORM?ORM 是 Object Relational Mapping 的缩写,译为“对象关系映射”,是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。它解决了对象和关系型数据库之间的数据交互问题,ORM的作用是在关系型数据库和业务实体对象之间作一个映射,这样我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。如何选择合适自己的ORM框架?对于我们而言选择ORM框架的目的其实都是为了让我们的程序更好的操作数据库,提高开发编程效率和程序的维护拓展性。因此我们在为自己负责的项目选择合适的ORM框架的时候需要从项目的业务场景出发,选择最适合自己团队的ORM框架(注意没有完美的框架,适合团队的才是最好的)。以下是一些比较好用且优秀的.NET-ORM框架汇总,排名不分先后可供大家参考学习(假如您有更好的.NET相关ORM推荐请在文末留言,谢谢)。EF/EF CoreEntity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技术,EF Core 是适用于 .NET 的现代对象数据库映射器。它支持 LINQ 查询、更改跟踪、更新和架构迁移。EF Core 通过提供程序插件 API 与 SQL Server、Azure SQL 数据库、SQLite、Azure Cosmos DB、MySQL、PostgreSQL 和其他数据库一起使用。(微软官方出品)。EF Core 可用作对象关系映射程序 (O/RM),这可以实现以下两点:使 .NET 开发人员能够使用 .NET 对象处理数据库。无需再像通常那样编写大部分数据访问代码。官方文档教程:https://docs.microsoft.com/zh-cn/ef/GitHub地址:https://github.com/dotnet/efcore以下是EF/EF Core相关拓展程序包:EFCore.BulkExtensions - EF的批量操作库。EntityFramework-Plus - EF的增强工具集,包括过滤器,审核,缓存,查询,批删除,批更新等。EntityFramework.Exceptions - 当您的SQL查询违反SqlServer,MySql或PostgreSQL中的数据库约束时,请对EntityFrameworkCore使用类型化的异常处理。EntityFramework.Triggers - EF触发器。EntityFramework.Rx - EF的Reactive 扩展程序。Npgsql.EntityFrameworkCore.PostgreSQL - PostgreSQL的EF驱动程序。EntityFramework.TypedOriginalValues - 通过某些特殊方法来获得数据库对象在本次修改前的原始值。常见的使用场景是对数据库操作的数据做审计。EntityFramework.VersionedProperties -  将对象里每次变更历史自动保存到一个特定的属性里。审计或者做历史版本时比较适用。LINQKit - LINQKit是LINQ对SQL和Entity Framework的免费扩展集。Pomelo.EntityFrameworkCore.MySql - mysql的EF驱动程序。spectre.query - EF的简单查询库。StoredProcedureEFCore-用于执行存储过程的 Entity Framework Core 扩展。ShardingCore - EF Core分表分库读写分离的扩展。DapperDapper是一个简单的.NET对象映射器,在速度方面具有"King of Micro ORM"的头衔,几乎与使用原始的ADO.NET数据读取器一样快。ORM是一个对象关系映射器,它负责数据库和编程语言之间的映射。Dapper通过扩展IDbConnection提供一些有用的扩展方法去查询您的数据库。主要特点:高性能、易排查、易运维、灵活可控。GitHub地址:https://github.com/DapperLib/Dapper以下是Dapper相关拓展程序包:Dapper-Extensions - Dapper Extensions 是一个小型ORM库,通过为您的 POCO 添加基本的 CRUD 操作(获取、插入、更新、删除)来补充Dapper。对于更高级的查询场景,Dapper Extensions 提供了一个谓词系统。这个库的目标是通过不需要任何属性或基类继承来保持你的 POCO 纯净。Dapper-FluentMap - Dapper的扩展。Dommel - Dapper的CRUD操作。MicroOrm.Dapper.Repositories - Dapper的CRUD操作。FreeSqlFreeSql 是一款功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。主要特点:支持 CodeFirst 模式,即便使用 Access 数据库也支持数据迁移;支持 DbFirst 模式,支持从数据库导入实体类,或使用实体类生成工具生成实体类;支持 深入的类型映射,比如 PgSql 的数组类型等;支持 丰富的表达式函数,以及灵活的自定义解析;支持 导航属性一对多、多对多贪婪加载,以及延时加载;支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/Access 等数据库;官方文档地址:http://www.freesql.net/GitHub地址:https://github.com/dotnetcore/FreeSqlSqlSugarSqlSugar是一款老牌 .NET 开源ORM框架,支持.NET CORE 和 MySql、SqlServer、Sqlite、Oracle 、 postgresql 、达梦、人大金仓 数据库,具有EF NH的功能,比EF更人性化的语法,支持真实的批量操作,另外还有媲美Dapper的性能。主要特点:简单易用、功能齐全、高性能、轻量级、服务齐全、支持全自动分表组件,SAAS分库,大数据处理的ORM。官网地址:http://www.donet5.comGitHub地址:https://github.com/donet5/SqlSugarChloeChloe 是一个轻量级的对象/关系映射(ORM)库。查询接口类似于 LINQ。您可以使用 Chloe.ORM 通过 lambda 查询 LINQ 之类的数据并执行任何操作(加入查询 | 组查询 | 聚合查询 | 插入 | 批量更新 | 批量删除)。文档地址:https ://github.com/shuxinqin/Chloe/wikiGitHub地址:https://github.com/shuxinqin/Chloenhibernate-core  NHibernate 是一个成熟的开源对象关系映射器,适用于 .NET 框架。它被积极开发,功能齐全,并在数千个成功的项目中使用。NHibernate社区网站 - https://nhibernate.info GitHub地址:https://github.com/nhibernate/nhibernate-coreSmartSqlSmartSql = C# 中的 MyBatis + .NET Core+ 缓存(内存 | Redis)+ R/W 拆分 + PropertyChangedTrack +动态存储库 + InvokeSync + 诊断。SmartSql 借鉴了 MyBatis 的思想,使用 XML 来管理 SQL ,并且提供了若干个筛选器标签来消除代码层面的各种 if/else 的判断分支。SmartSql将管理你的 SQL ,并且通过筛选标签来维护本来你在代码层面的各种条件判断,使你的代码更加优美。主要特点:简洁、高效、高性能、扩展性、监控、渐进式开发!文档地址: https://smartsql.net/guide/GitHub地址:https://github.com/dotnetcore/SmartSqlPetaPocoPetaPoco 是一个用于 .NET(4、4.5+、net standard 2.0+)和 Mono 的微型、快速、易于使用的 micro-ORM。由于 PetaPoco 所代表的简单性和易用性,它受到许多人的喜爱。PetaPoco 是首选的微 ORM,也是任何体面的开发人员工具包中必不可少的实用程序。主要特点:与Dapper一样,它很快,因为它使用动态方法生成 (MSIL) 将列值分配给属性。像Massive一样,它现在也支持动态 Expandos。与ActiveRecord一样,它支持对象和数据库表之间的密切关系。与SubSonic一样,它支持使用 T4 模板生成 poco 类(仅限 V5)。与Massive一样,它以单个文件的形式提供,您可以轻松地将其添加到任何项目或编译(仅限 V5)。文档地址:https://discoverdot.net/projects/peta-pocoGitHub地址:https://github.com/CollaboratingPlatypus/PetaPoco linq2dbLINQ to DB 是最快的LINQ数据库访问库,在POCO对象和数据库之间提供了一个简单、轻量、快速且类型安全的层。在架构上,它比 Dapper、Massive 或 PetaPoco 等微 ORM 高出一步,因为您使用 LINQ 表达式,而不是魔术字符串,同时在代码和数据库之间维护一个薄抽象层。您的查询由 C# 编译器检查并允许轻松重构。但是,它不像 LINQ to SQL 或实体框架那么重。没有更改跟踪,因此您必须自己进行管理,但从积极的方面来说,您可以获得更多控制权并更快地访问您的数据。文档地址:https://linq2db.github.io/ GitHub地址:https://github.com/linq2db/linq2dbRepoDb RepoDB 是一个开源的 .NET ORM 库,它弥补了微 ORM 和全 ORM 的差距。它可以帮助您在开发过程中简化何时使用 BASIC 和 ADVANCE 操作的切换。主要特点:易于使用- 这些操作都作为您的 IDbConnection 对象的扩展方法实现。只要您的连接处于打开状态,就可以对您的数据库调用任何操作。高性能- 它缓存已经生成的编译表达式以供将来重用和执行。它了解您的架构以创建最佳的编译表达式 AOT。内存高效- 它提取并缓存您的对象属性、执行上下文、对象映射和 SQL 语句。它在整个转换和执行过程中重用它们。动态和混合- 它提供了成熟 ORM 的一些高级功能。它极大地帮助开发人员在开发过程中进行上下文切换时简化体验。开源软件——它是一个开源软件,并且永远是免费的。它旨在进一步改进 .NET 数据访问体验和解决方案,以及社区的集体思想。高质量- 它是一个高质量的微型 ORM,由 10K+ 真实单元和集成测试支持。它经过高度测试,并被生产环境中运行的各种关键系统使用。GitHub地址:https://github.com/mikependon/RepoDBServiceStack.OrmLite OrmLite是一个快速、简单、类型化的.NET ORM,OrmLite 的目标是提供一个方便、DRY、无配置、与 RDBMS 无关的类型包装器,该包装器与 SQL 保持高度亲和性,公开直观的 API,生成可预测的 SQL 并干净地映射到断开连接和数据传输对象 (DTO) 友好、普通的旧C# 对象 (POCO)。这种方法更容易推理您的数据访问,从而清楚地知道什么 SQL 在什么时间执行,同时减轻意外行为、隐式 N+1 查询和重对象关系映射器 (ORM) 中普遍存在的泄漏数据访问。文档地址:https://docs.servicestack.net/ormlite/GitHub地址:https://github.com/ServiceStack/ServiceStack.OrmLiteSQLite-net 简单、强大、跨平台的 SQLite 客户端和 .NET 的 ORM。主要特点:非常容易与现有项目集成并在所有 .NET 平台上运行。SQLite 上的瘦包装器,快速高效。(这个库不应该是您查询的性能瓶颈。)用于安全执行 CRUD 操作和查询(使用参数)并以强类型方式检索这些查询结果的非常简单的方法。与您的数据模型一起工作,而不会强迫您更改您的类。(包含一个小的反射驱动 ORM 层。)GitHub地址:https://github.com/praeclarum/sqlite-netInsight.DatabaseInsight.Database是一个用于 .NET 的快速、轻量级的 micro-orm。GitHub地址:https://github.com/jonwagner/Insight.Databasecyqdata cyq.data是一个高性能且功能最强大的orm(支持.NET Core),支持Txt、Xml、Access、Sqlite、Mssql、Mysql、Oracle、Sybase、Postgres、DB2、Redis、MemCache。GitHub地址:https://github.com/cyq1162/cyqdataTinyORMTinyORM是一个简单、快速且安全的微型.NET ORM。Wiki地址:https://github.com/sdrapkin/SecurityDriven.TinyORM/wikiGitHub地址:https://github.com/sdrapkin/SecurityDriven.TinyORMquerybuilderSQL 查询构建器,用 c# 编写,帮助您轻松构建复杂的查询,支持 SqlServer、MySql、PostgreSql、Oracle、Sqlite 和 Firebird。官网地址:https://sqlkata.com/GitHub地址:https://github.com/sqlkata/querybuilderC#/.NET/.NET Core推荐学习书籍C#/.NET/.NET Core学习视频汇总C#/.NET/.NET Core优秀项目框架推荐C#/.NET/.NET Core面试宝典(基础版)C#/.NET/.NET Core学习、工作、面试指南2022年了有哪些值得推荐的.NET ORM框架?[提高工作开发效率,远离996]程序员常用的工具软件推荐了解作者&获取更多学习资料&加入DotNetGuide技术交流群

Docker安装MongoDB并使用Navicat连接

MongoDB简介:  MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。查看可用的MongoDB版本:访问DokcerHub中的MongoDB镜像库地址:https://hub.docker.com/_/mongo/tags可以通过 Sort by 查看其他版本的MongoDB,查看最新版本MongoDB镜像(mongo:latest):https://hub.docker.com/_/mongo/tags?page=1&name=latest 此外,我们还可以用docker search mongo命令来查看可用版本: 拉取最新版本的MongoDB镜像:docker pull mongo:latest注意:tag是可选的,tag表示标签,多为软件的版本,默认是latest版本(最新版)验证MongoDB镜像是否成功拉取到本地:使用以下命令来查看MongoDB镜像是否成功拉取到本地:docker images创建并运行一个MongoDB容器:docker run -itd --name mongo-test -p 27017:27017 mongo --auth参数说明:-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。--name mongo-test:容器名称-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务(注意:安全问题,MongoDB默认是不开启权限验证的,不过设置了这里就相当于修改MongoDB的配置auth=ture启用权限访问)。解决无法正常执行mongo命令问题进入容器:docker exec -it mongo-test mongo异常原因:OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown官网解决方案:https://github.com/docker-library/mongo/issues/558mongo5.0以上的版本使用mongo来执行mongodb命令已经不支持了,你需要改用mongosh来替代mongo!进入创建的MongoDB容器docker exec -it mongo-test mongoshMongoDB报错"ongoServerError: not authorized on admin to execute command":MongoDB默认是不需要用户密码就可以连接的,如果使用命令报错"ongoServerError: not authorized on admin to execute command ",则表示当前登陆用户不具备相应权限。解决办法:在admin数据库中通过创建一个用户,赋予用户root权限。# 进入admin数据库 use admin # 创建一个超级用户 db.createUser( user:"root", pwd:"123456", roles:[{role:"root",db:"admin"}] #授权登录 db.auth('root','123456')MongoDB用户权限管理:MongoDB添加用户命令说明user字段,为新用户的名字。pwd字段,用户的密码。cusomData字段,为任意内容,例如可以为用户全名介绍。roles字段,指定用户的角色,可以用一个空数组给新用户设定空角色。在roles字段,可以指定内置角色和用户定义的角色。超级用户的role有两种,userAdmin或者userAdminAnyDatabase(比前一种多加了对所有数据库的访问,仅仅是访问而已)。db是指定数据库的名字,admin是管理数据库。不能用admin数据库中的用户登录其他数据库。注:只能查看当前数据库中的用户,哪怕当前数据库admin数据库,也只能查看admin数据库中创建的用户。首先切换到admin数据库中# 进入admin数据库 use admin创建admin超级管理员用户指定用户的角色和数据库:(注意此时添加的用户都只用于admin数据库,而非你存储业务数据的数据库)(在cmd中敲多行代码时,直接敲回车换行,最后以分号首尾)db.createUser( { user: "admin", customData:{description:"superuser"}, pwd: "admin", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] )创建一个不受访问限制的超级用户拥有所有权限,不受任何限制db.createUser( user:"root", pwd:"123456", roles:[{role:"root",db:"admin"}] );创建一个业务数据库管理员用户只负责某一个或几个数据库的増查改删db.createUser({ user:"user001", pwd:"123456", customData:{ name:'jim', email:'jim@qq.com', age:18, roles:[ {role:"readWrite",db:"db001"}, {role:"readWrite",db:"db002"}, 'read'// 对其他数据库有只读权限,对db001、db002是读写权限 })MongoDB数据库角色说明数据库用户角色:read、readWrite;数据库管理角色:dbAdmin、dbOwner、userAdmin;集群管理角色:clusterAdmin、clusterManager、4. clusterMonitor、hostManage;备份恢复角色:backup、restore;所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase超级用户角色:root内部角色:__systemMongoDB中的role详解Read:允许用户读取指定数据库readWrite:允许用户读写指定数据库dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profileuserAdmin:允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限root:只在admin数据库中可用。超级账号,超级权限服务器配置27017的开放端口:Navicat连接mongoDB:1.连接MongoDB点击这个位置2、连接参数介绍:stand alone:独立的shard cluster:分片集群replica set:复制集SRV record:SRV记录是DNS服务器的数据库中支持的一种资源记录的类型,它记录了哪台计算机提供了哪个服务这么一个简单的信息。SRV 记录:一般是为Microsoft的活动目录设置时的应用。DNS可以独立于活动目录,但是活动目录必须有DNS的帮助才能工作。为了活动目录能够正常的工作,DNS服务器必须支持服务定位(SRV)资源记录,资源记录把服务名字映射为提供服务的服务器名字。活动目录客户和域控制器使用SRV资源记录决定域控制器的IP地址。一般情况下,我们连接只需要连接主库查数据,所以选择独立的这个连接方式就可以,填写好常规参数可以点击测试连接是否正常,即可连接!参考文章:https://blog.csdn.net/zhanghongshuang/article/details/117461225

MongoDB安全加固,防止数据库攻击删除勒索威胁

前言:  今天发现前段时间自己搭建的一个系统的MongoDB数据找不到了,觉得很奇妙,然后登上MongoDB数据库发现多了一个名为READ__ME_TO_RECOVER_YOUR_DATA的数据库,里面还有一个README的集合里面包含了下面描述的勒索信息。没错我的MongoDB数据库被攻击了,不过还好这个系统里面的数据都是自己学习的一些没有任何价值的数据。但是换个角度,假如在公司层面遇到这样的事情那一定是天大的事情了,你要面临公司、客户信息安全问题。所以无论是自己学习,还是工作方面我们都要养成时刻做好保护自己软件程序,及其数据源安全的问题。今天主要来讲讲为什么MongoDB这么容易遭遇勒索的原因和我们该如何做好防护措施。README文档内容如下:All your data is a backed up. You must pay 0.06 BTC to 168i2g62fcXwu3GYAJM4FAksxEmNnDjCkm 48 hours for recover it. After 48 hours expiration we will leaked and exposed all your data. In case of refusal to pay, we will contact the General Data Protection Regulation, GDPR and notify them that you store user data in an open form and is not safe. Under the rules of the law, you face a heavy fine or arrest and your base dump will be dropped from our server! You can buy bitcoin here, does not take much time to buy https://localbitcoins.com or https://buy.moonpay.io/ After paying write to me in the mail with your DB IP: rambler+1duuz@onionmail.org and/or mariadb@mailnesia.com and you will receive a link to download your database dump.翻译过来就是:你所有的数据都有备份。你必须支付0.06比特币到168i2g62fcXwu3GYAJM4FAksxEmNnDjCkm 48小时来恢复它。在48小时到期后,我们将泄露和暴露您的所有数据。在拒绝付款的情况下,我们将联系通用数据保护条例(GDPR),并通知他们您以公开形式存储用户数据,这是不安全的。根据法律规定,你将面临巨额罚款或逮捕你的数据库将从我们的服务器上删除!你可以在这里购买比特币,不需要太多时间购买https://localbitcoins.com或https://buy.moonpay.io/支付后写信给我的邮件与你的DB IP: rambler+1duuz@onionmail.org和/或mariadb@mailnesia.com,你会收到一个链接下载你的数据库转储。MongoDB漏洞成因:  在初始安装完毕的时候MongoDB都默认有一个admin数据库,此时admin数据库是空的,没有记录权限相关的信息!当admin.system.users一个用户都没有时,即使mongod启动时添加了—auth参数,如果没有在admin数据库中添加用户,此时不进行任何认证还是可以做任何操作(不管是否是以—auth 参数启动),直到在admin.system.users中添加了一个用户。加固的核心是只有在admin.system.users中添加用户之后,mongodb的认证,授权服务才能生效。遭遇勒索的原因分析:  首先我这个MongoDB数据库是安装在Docker上面的,因为都是是有默认安装的方式,并且安装完成以后都没有开启默认权限验证登录的功能。开启MongoDB服务时不添加任何参数时默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增删改高危动作)而且可以远程访问数据库。并且我还使用了27017这个默认端口,所以黑客可以通过批量扫描Ip很快就能检索到。MongoDB安全加固措施: 1、配置账号密码,开启MongoDB的权限访问Docker安装MongoDB时开启权限验证的命令:docker run -itd --name mongo-test -p 27017:27017 mongo --auth参数说明:-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。--name mongo-test:容器名称-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务(注意:安全问题,MongoDB默认是不开启权限验证的,不过设置了这里就相当于修改MongoDB的配置auth=ture启用权限访问)。2、使用非默认的端口,减少互联网上被端口扫描并定向爆破的概率对MongoDB监听的端口和IP做调整有下面2个目的IP: 默认监听IP为127.0.0.1,我们可能需要开放特定的CIDR来让处于不同主机上的客户端可以连接. 最简单的就是直接允许任意IP的客户端连接,这时CIDR为0.0.0.0.但是这也是很危险的一个操作,意味着全球互联网上的任意一台电脑都可以连接上来,这虽然方便但是也是最危险的,建议指定具体的CIDR,这样可以排除互联网的大量肉鸡进行恶意的连接。端口: 默认的监听端口为27017,我们可以改为其他端口,躲开互联网上的恶意程序的扫描和连接。修改/etc/mongod.confvim /etc/mongod.conf在端口和IP监听部分我们改为如下设置:#network interfacesnet:  port: 7017  bindIp: 0.0.0.0  # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.修改完成后重启服务:systemctl restart mongod如果重启失败,可能是SELinux的安全策略限制了MongoDB使用新的端口,我们需要放行MongoDB使用新的端口:[root@localhost thinktik]# semanage port -a -t mongod_port_t -p tcp 7017 bash: semanage: command not found # 如果出现上面的错误,可以这样这个解决: [root@localhost thinktik]# dnf install policycoreutils-python-utils Last metadata expiration check: 0:10:50 ago on Mon 27 Dec 2021 03:11:19 PM CST. ...SELinux放行后,我们继续重启即可.配置防火墙如果你需要服务被互联网上的其他电脑访问,那么你需要配置防火墙,运行你的端口被访问# 开放7017端口 [root@thinkvm01 thinktik]# firewall-cmd --zone=public --add-port=7017/tcp --permanent # 重载防火墙 [root@thinkvm01 thinktik]# firewall-cmd --reload3、限制访问IPMongoDB可以限制只允许某一特定IP来访问,只要在启动时加一个参数bind_ip即可,或者在/etc/mongodb.conf中添加bind_ip配置,如下:# 方法一 mongod --bind_ip 127.0.0.1,10.0.133.14 # 方法二 在/etc/mongodb.conf文件中添加以下内容: bind_ip = 127.0.0.1,10.0.133.14 这样之后,MongoDB服务端只有127.0.0.1和10.0.133.14这两个 IP 可以访问了。4、关闭万网访问权限关闭外网访问权限,也就是限定只能是内网访问。在/etc/mongodb.conf中配置:bind_ip 127.0.0.1预防方法:经过这里勒索经历,我总结了一下几点:不要裸奔,首先把你数据库的账户密码设置好,做好权限验证登录!尽量不要把你的数据库摆上公网,业务处理都尽量在内网进行!如果要摆上公网,一定要设置好访问权限,绑定访问源 IP!记得养成数据备份的好习惯!参考文章:https://new.qq.com/rain/a/20210330A06AYX00https://www.cnblogs.com/fundebug/p/how-to-protect-mongodb.htmlhttps://juejin.cn/post/7049315722039656479

OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown

前言:  今天按照以往在Docker安装MongoDB的方式安装,但是到最后使用mongo命令执行mongodb命令的时候一直执行不成功,最后还是按照官网的Issues解决了。🚀回到顶部创建并运行​一个MongoDB容器:docker run -itd --name mongo-test -p 27017:27017 mongo --auth参数说明:-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。--name mongo-test:容器名称-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务。解决无法正常执行mongo命令问题进入容器:docker exec -it  mongo-test mongo异常原因:OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown官网解决方案:https://github.com/docker-library/mongo/issues/558mongo5.0以上的版本使用mongo来执行mongodb命令已经不支持了,你需要改用mongosh来替代mongo!

.NET HttpWebRequest(请求被中止: 未能创建 SSL/TLS 安全通道)和(基础连接已经关闭: 发送时发生错误)问题查找解决

前言:  前段时间在对接第三方接口的时候发生了一个非常奇葩的问题,就是使用 .NET Framework 4.6 HttpWebRequest进行网络请求的相关问题。背景,关于调用第三方的接口都是使用使用自己封装的一个HttpWebRequestHepler帮助类,在本地开发时调用第三方接口都是正常的。然而当我部署到运维给我一个服务器(阿里云服务器)时刚开始提示是请求被中止: 未能创建 SSL/TLS 安全通道,之后经过一番修改以后就是提示基础连接已经关闭: 发送时发生错误。之后尝试了各种方法,还是没有办法解决基础连接已经关闭: 发送时发生错误这个问题。最后真的是无能为力,光这个问题找了一下午的解决方案,最后换到了我自己的阿里云服务器是可以正常调通第三方接口的。然后让运维看了下服务器结果是这个服务器都没有开通外网,所以导致了这个问题的出现。下面记录下问题排除的过程,希望能够帮助到遇到这种坑的小伙伴。一、自己封装的一个通用的HttpWebRequestHepler Http Web网络请求帮助类:/// <summary> /// Http Web网络请求帮助类 /// </summary> public class HttpWebRequestHepler private static HttpWebRequestHepler _httpWebRequestHepler; private string _resContent;//响应内容 private string _errInfo;//错误信息 private int _responseCode;//响应状态码 public static HttpWebRequestHepler _ get => _httpWebRequestHepler ?? (_httpWebRequestHepler = new HttpWebRequestHepler()); set => _httpWebRequestHepler = value; /// <summary> /// 数据请求 /// </summary> /// <param name="requestUrl">请求地址</param> /// <param name="postData">请求参数</param> /// <param name="accessToken">授权token</param> /// <param name="contentType">请求标头值类型</param> /// <param name="method">请求方式</param> /// <returns></returns> public string HttpWebResponseData(string requestUrl, string postData, string accessToken = "", string contentType = "application/json", string method = "POST") HttpWebResponse wr = null; var hp = (HttpWebRequest)WebRequest.Create(requestUrl); hp.Timeout = 60 * 1000 * 10;//以毫秒为单位,设置等待超时10分钟 hp.Method = method; hp.ContentType = contentType; if (!string.IsNullOrWhiteSpace(accessToken)) hp.Headers.Add("Authorization", "Bearer " + accessToken);//增加headers请求头信息 if (postData != "")//带参数请求 byte[] data = Encoding.UTF8.GetBytes(postData); hp.ContentLength = data.Length; Stream ws = hp.GetRequestStream(); // 发送数据 ws.Write(data, 0, data.Length); ws.Close(); wr = (HttpWebResponse)hp.GetResponse(); var sr = new StreamReader(wr.GetResponseStream() ?? throw new InvalidOperationException(), Encoding.UTF8); this._resContent = sr.ReadToEnd(); sr.Close(); wr.Close(); catch (Exception exp) this._errInfo += exp.Message; if (wr != null) this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; }二、请求被中止: 未能创建 SSL/TLS 安全通道问题解决:  把项目部署到阿里云服务器中,请求第三方提示请求被中止: 未能创建 SSL/TLS 安全通道。首先字面上可以看出来这个https请求安全协议的问题。微软官方说明是,NET 4.6需要添加ServicePointManager.SecurityProtocol属性,指定schnanel安全包支持的安全协议。微软官方解释:此属性选择要用于新连接的安全套接字层 (SSL) 或传输层安全性 (TLS) 协议的版本;不会更改现有连接。从 .NET Framework 4.7 开始,此属性的默认值为 SecurityProtocolType.SystemDefault 。 这允许基于 SslStream ((如 FTP、HTTP 和 SMTP) )的 .NET Framework 网络 api 从操作系统或系统管理员执行的任何自定义配置继承默认安全协议。 有关默认情况下在每个版本的 Windows 操作系统上启用了哪些 SSL/TLS 协议的信息,请参阅 TLS/SSL (SCHANNEL SSP) 中的协议 。对于通过 .NET Framework 4.6.2 的 .NET Framework 版本,不会列出此属性的默认值。 安全环境不断变化,默认的协议和保护级别会随着时间的推移而更改,以避免已知的漏洞。 默认值因单独的计算机配置、已安装的软件和应用的修补程序而异。 解决方案://todo:指定请求包的安全协议,因为不知道你当前项目到底是哪个版本所以为了安全保障都加上 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;三、基础连接已经关闭: 发送时发生错误        这个问题查阅了网上几个比较典型的博客试了下,结果都没有办法解决我的问题,一下记录下这几个博客的解决方案,希望可以帮助到遇到这样问题的小伙伴。1、一般来说添加了上面的ServicePointManager.SecurityProtocol属性就可以解决这个基础连接关闭的问题。2、C# HttpRequest基础连接已经关闭: 接收时发生意外错误(原文地址)://增加下面两个属性即可 hp.KeepAlive = false; hp.ProtocolVersion = HttpVersion.Version10;四、开启阿里云服务器外网(我的解决方案)  查看一下你的服务器是否开通了外网,假如没有开通服务器外网在进行尝试。阿里云服务器配置外网访问参考。因为这个奇葩问题花费了一天宝贵的时间,考虑问题还是得多方面考虑。

.NET HttpWebRequest(请求被中止: 未能创建 SSL/TLS 安全通道)和(基础连接已经关闭: 发送时发生错误)问题查找解决

前言:  前段时间在对接第三方接口的时候发生了一个非常奇葩的问题,就是使用 .NET Framework 4.6 HttpWebRequest进行网络请求的相关问题。背景,关于调用第三方的接口都是使用使用自己封装的一个HttpWebRequestHepler帮助类,在本地开发时调用第三方接口都是正常的。然而当我部署到运维给我一个服务器(阿里云服务器)时刚开始提示是请求被中止: 未能创建 SSL/TLS 安全通道,之后经过一番修改以后就是提示基础连接已经关闭: 发送时发生错误。之后尝试了各种方法,还是没有办法解决基础连接已经关闭: 发送时发生错误这个问题。最后真的是无能为力,光这个问题找了一下午的解决方案,最后换到了我自己的阿里云服务器是可以正常调通第三方接口的。然后让运维看了下服务器结果是这个服务器都没有开通外网,所以导致了这个问题的出现。下面记录下问题排除的过程,希望能够帮助到遇到这种坑的小伙伴。一、自己封装的一个通用的HttpWebRequestHepler Http Web网络请求帮助类:/// <summary> /// Http Web网络请求帮助类 /// </summary> public class HttpWebRequestHepler private static HttpWebRequestHepler _httpWebRequestHepler; private string _resContent;//响应内容 private string _errInfo;//错误信息 private int _responseCode;//响应状态码 public static HttpWebRequestHepler _ get => _httpWebRequestHepler ?? (_httpWebRequestHepler = new HttpWebRequestHepler()); set => _httpWebRequestHepler = value; /// <summary> /// 数据请求 /// </summary> /// <param name="requestUrl">请求地址</param> /// <param name="postData">请求参数</param> /// <param name="accessToken">授权token</param> /// <param name="contentType">请求标头值类型</param> /// <param name="method">请求方式</param> /// <returns></returns> public string HttpWebResponseData(string requestUrl, string postData, string accessToken = "", string contentType = "application/json", string method = "POST") HttpWebResponse wr = null; var hp = (HttpWebRequest)WebRequest.Create(requestUrl); hp.Timeout = 60 * 1000 * 10;//以毫秒为单位,设置等待超时10分钟 hp.Method = method; hp.ContentType = contentType; if (!string.IsNullOrWhiteSpace(accessToken)) hp.Headers.Add("Authorization", "Bearer " + accessToken);//增加headers请求头信息 if (postData != "")//带参数请求 byte[] data = Encoding.UTF8.GetBytes(postData); hp.ContentLength = data.Length; Stream ws = hp.GetRequestStream(); // 发送数据 ws.Write(data, 0, data.Length); ws.Close(); wr = (HttpWebResponse)hp.GetResponse(); var sr = new StreamReader(wr.GetResponseStream() ?? throw new InvalidOperationException(), Encoding.UTF8); this._resContent = sr.ReadToEnd(); sr.Close(); wr.Close(); catch (Exception exp) this._errInfo += exp.Message; if (wr != null) this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; }二、请求被中止: 未能创建 SSL/TLS 安全通道问题解决:  把项目部署到阿里云服务器中,请求第三方提示请求被中止: 未能创建 SSL/TLS 安全通道。首先字面上可以看出来这个https请求安全协议的问题。微软官方说明是,NET 4.6需要添加ServicePointManager.SecurityProtocol属性,指定schnanel安全包支持的安全协议。微软官方解释:此属性选择要用于新连接的安全套接字层 (SSL) 或传输层安全性 (TLS) 协议的版本;不会更改现有连接。从 .NET Framework 4.7 开始,此属性的默认值为 SecurityProtocolType.SystemDefault 。 这允许基于 SslStream ((如 FTP、HTTP 和 SMTP) )的 .NET Framework 网络 api 从操作系统或系统管理员执行的任何自定义配置继承默认安全协议。 有关默认情况下在每个版本的 Windows 操作系统上启用了哪些 SSL/TLS 协议的信息,请参阅 TLS/SSL (SCHANNEL SSP) 中的协议 。对于通过 .NET Framework 4.6.2 的 .NET Framework 版本,不会列出此属性的默认值。 安全环境不断变化,默认的协议和保护级别会随着时间的推移而更改,以避免已知的漏洞。 默认值因单独的计算机配置、已安装的软件和应用的修补程序而异。 解决方案://todo:指定请求包的安全协议,因为不知道你当前项目到底是哪个版本所以为了安全保障都加上 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;三、基础连接已经关闭: 发送时发生错误        这个问题查阅了网上几个比较典型的博客试了下,结果都没有办法解决我的问题,一下记录下这几个博客的解决方案,希望可以帮助到遇到这样问题的小伙伴。1、一般来说添加了上面的ServicePointManager.SecurityProtocol属性就可以解决这个基础连接关闭的问题。2、C# HttpRequest基础连接已经关闭: 接收时发生意外错误(原文地址)://增加下面两个属性即可 hp.KeepAlive = false; hp.ProtocolVersion = HttpVersion.Version10;四、开启阿里云服务器外网(我的解决方案)  查看一下你的服务器是否开通了外网,假如没有开通服务器外网在进行尝试。阿里云服务器配置外网访问参考。因为这个奇葩问题花费了一天宝贵的时间,考虑问题还是得多方面考虑。

C#/.NET/.NET Core优秀项目框架推荐

前言:  为.NET开源者提供的一个推荐自己优秀框架的地址,大家可以把自己的一些优秀的框架,或者项目链接地址存到在这里,提供给广大.NET开发者们学习(注意:排名不分先后,都是十分优秀的开源框架和项目💖)。Github项目仓库收集地址:https://github.com/YSGStudyHards/DotNetGuide/issues/5填写格式如下:项目or框架名称+访问链接地址+项目描述:📦NPOI-ExportWordAndExcel-ImportExcelData一个简单,易懂的通用ASP.NET Core NPOI导出复杂Word、复杂美观Excel和Excel数据导入详细示例开源项目(开箱即用,无需其他繁琐配置)。🏡C#/.NET Core/.NET项目宝库(收集了大量优秀的C#、.NET、.NET Core项目)该库主要是为我们.NET开发者提供一个寻找优秀C#/.NET Core/.NET项目的入口,通过了解和对比更多的项目来选择最适合我们自己学习、工作开发的一套项目。优秀的项目是不应该被埋没的,欢迎大家一起加入这个组织共同完善、发展.NET社区!【注意:这些都是非常优秀的作者所写的项目,排名不分先后,欢迎前往原址Star】Blog.Core项目地址:https://github.com/anjoy8/Blog.CoreBlog.Core一个开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x + RBAC】权限框架。官方文档地址:apk.neters.club/.docAspNetCore项目地址:https://github.com/dotnet/aspnetcoreASP.NETCore是一个跨平台的.NET框架,用于在Windows、Mac或Linux上构建基于云的现代web应用程序。WeiXinMPSDK项目地址:https://github.com/JeffreySu/WeiXinMPSDK微信公众平台SDK Senparc.Weixin for C#,支持.NET Framework及.NET Core。已支持微信公众号、小程序、小游戏、企业号、企业微信、开放平台、微信支付、JSSDK、微信周边等全平台。 WeChat SDK for C#.ABP Framework项目地址:https://github.com/abpframework/abpABP是一个开源应用程序框架,专注于基于ASP.NET Core的Web应用程序开发,但也支持开发其他类型的应用程序.官方文档地址:documentationUtil项目地址:https://github.com/dotnetcore/UtilUtil是一个.net core平台下的应用框架,旨在提升小型团队的开发输出能力,由常用公共操作类(工具类)、分层架构基类、Ui组件,第三方组件封装,第三方业务接口封装,配套代码生成模板,权限等组成。siteserver/cms项目地址:https://github.com/siteserver/cms是基于 .NET Core,能够以最低的成本、最少的人力投入在最短的时间内架设一个功能齐全、性能优异、规模庞大并易于维护的网站平台。OSharp项目地址:https://github.com/dotnetcore/OSharpOSharp是一个基于.NetCore的快速开发框架,框架对 AspNetCore 的配置、依赖注入、日志、缓存、实体框架、Mvc(WebApi)、身份认证、功能权限、数据权限等模块进行更高一级的自动化封装,并规范了一套业务实现的代码结构与操作流程,使 .Net Core 框架更易于应用到实际项目开发中。Vue.NetCore项目地址:https://github.com/cq-panda/Vue.NetCore.NetCore+Vue2/Vue3+Element plus+uniapp前后端分离,全自动生成代码;支持移动端(uniapp)ios/android/h5/微信小程序。OpenAuth.Net项目地址:https://gitee.com/dotnetchina/OpenAuth.Net.Net快速应用开发框架、最好用的权限工作流系统。基于经典领域驱动设计的权限管理及快速开发框架,源于Martin Fowler企业级应用开发思想及最新技术组合(IdentityServer、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE、Element-ui等)。已成功在docker/jenkins中实施。核心模块包括:组织机构、角色用户、权限授权、表单设计、工作流等。它的架构精良易于扩展,是中小企业的首选。ant-design-blazor项目地址:https://github.com/ant-design-blazor/ant-design-blazor一组基于Ant Design和Blazor WebAssembly的企业级UI组件。NetModular项目地址:https://github.com/iamoldli/NetModularNetModular 是基于.Net Core 和 Vue.js 的业务模块化以及前后端分离的快速开发框架。payment项目地址:https://github.com/essensoft/paylink一套基于 .NET Core 开发的支付SDK集,它极大简化了API调用及通知的处理流程。Furion项目地址:https://gitee.com/dotnetchina/Furion让 .NET 开发更简单,更通用,更流行。YuebonNetCore项目地址:https://gitee.com/yuebon/YuebonNetCore?_from=gitee_searchYuebonCore基于.Net5.0的权限管理及快速开发框架,前后端分离,核心模块包括:组织机构、角色用户、权限授权、多系统、多应用管理、定时任务、业务单据编码规则、代码生成器等,整合应用最新技术包括Asp.NetCore MVC、EF、Dapper、AutoFac、WebAPI、Swagger、Vue等。它的架构易于扩展,是中小企业的首选。 YuebonCore其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展,让Web开发更快速、简单,解决70%重复工作。轻松开发,专注您的业务,从YuebonCore FW开始!fulusso项目地址:https://github.com/fuluteam/fulusso基于react+asp.net core开发的单点登录系统Awesome DotNet Packages项目地址:https://github.com/mjebrahimi/Awesome-Nuget-Packages很棒的.NET程序包的集合。SuperSocket项目地址:https://github.com/kerryjiang/SuperSocketSuperSocket 是一个轻量级、跨平台和可扩展的套接字服务器应用程序框架。DotNetty项目地址:https://github.com/Azure/DotNettyDotNetty 项目——netty 的一个端口,事件驱动的异步网络应用框架。nopCommerce项目地址:https://github.com/nopSolutions/nopCommerce一个功能完善,且流行的.NET领域电商开源项目nopCommerce是最好的开源电子商务平台。nopCommerce 是免费的,它是最流行的 ASP.NET Core 购物车。CAP项目地址:https://github.com/dotnetcore/CAPCAP 是一个基于 .NET Standard 的 C# 库,它是一种处理分布式事务的解决方案,同样具有 EventBus 的功能,它具有轻量级、易使用、高性能等特点。金庸群侠传3D重制版项目地址:https://github.com/jynew/jynew金庸群侠传3D重制版是一个非盈利游戏项目,重制经典游戏《金庸群侠传》(在线玩DOS原版)并支持后续一系列MOD和二次开发。项目目标:使用Unity引擎重制并致敬经典游戏《金庸群侠传》DOS版;后续支持重制《金群》的一系列MOD或二次开发;提供开放的能力给社区,有兴趣贡献力量的朋友可以让这个作品更加完善;提供一个完备的单机游戏结构供有兴趣学习开发游戏的朋友进行参考;IdentityServer4.Admin项目地址:https://github.com/skoruba/IdentityServer4.AdminIdentityServer4 和 Asp.Net Core Identity的管理Surging项目地址:https://github.com/fanliang11/surgingsurging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper、Consul作为surging服务的注册中心,集成了哈希,随机,轮询,压力最小优先作为负载均衡的算法,RPC可以选择采用netty或thrift框架,采用异步非阻塞传输。Ocelot项目地址:https://github.com/ThreeMammals/OcelotOcelot 是一个 .NET API 网关。该项目面向使用 .NET 运行微服务/面向服务架构的人,他们需要一个统一的入口点进入他们的系统。但是,它适用于任何使用 HTTP 的内容并在 ASP.NET Core 支持的任何平台上运行。SqlSugar项目地址:https://github.com/donet5/SqlSugarSqlSugar是一款 老牌 .NET 开源ORM框架,由果糖大数据科技团队维护和更新 ,1. .NET中唯一支持全自动分表组件,SAAS分库,大数据处理的ORM2. .NET 百万级写入、更新 性能最强框架3. 使用最简单的ORM 【文档,视频教程】4. 媲美原生的极限的性能5.Github star数仅次于EF 和 Dapper,每月nuget下载量超过1万更多优点: 简单易用、功能齐全、高性能、轻量级、服务齐全、官网教程文档、有专业技术支持一天18小时服务支持数据库:MySql、SqlServer、Sqlite、Oracle 、 postgresql、达梦、人大金仓、神通数据库FreeSql项目地址:https://github.com/dotnetcore/FreeSqlFreeSql 是一款功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。🛠 支持 CodeFirst 模式,即便使用 Access 数据库也支持数据迁移;💻 支持 DbFirst 模式,支持从数据库导入实体类,或使用实体类生成工具生成实体类;⛳ 支持 深入的类型映射,比如 PgSql 的数组类型等;✒ 支持 丰富的表达式函数,以及灵活的自定义解析;🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载;📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/Access 等数据库;csredis项目地址:https://github.com/2881099/csredis适用于 Redis 和 Redis Sentinel (2.8) 和集群的 .NET Core 或 .NET Framework 4.0+ 客户端。包括同步和异步客户端。FreeRedis项目地址:https://github.com/2881099/FreeRedisFreeRedis 是 .NET40+ Redis 客户端。支持集群、哨兵、主从、发布-订阅、lua、管道、事务、流、客户端缓存和池化。Orleans项目地址:https://github.com/dotnet/orleansOrleans建立在.NET开发人员生产力的基础上,并将其带入了分布式应用程序的世界,例如云服务。 Orleans可从单个本地服务器扩展到云中全局分布的高可用性应用程序。Orleans采用了对象,接口,async/await和try/catch等熟悉的概念,并将其扩展到多服务器环境。 这样,它可以帮助具有单服务器应用程序经验的开发人员过渡到构建弹性,可扩展的云服务和其他分布式应用程序。 因此,Orleans通常被称为“分布式.NET”。它是由Microsoft Research 创建的,并介绍了Virtual Actor Model作为一种新方法来构建面向云时代的新一代分布式系统。 Orleans的核心贡献是它的编程模型,它在不限制功能,以及对开发人员施加繁重约束的情况下,降低了高并发分布式系统固有的复杂性。FreeIM项目地址:https://github.com/2881099/FreeIM.NETCore websocket 实现简易、高性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。FreeIM 使用 websocket 协议实现简易、高性能(单机支持5万+连接)、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。 ImCore 已正式改名为 FreeIM。【网络版斗地主示例】FightLandlord项目地址:https://github.com/2881099/FightLandlord.NETCore斗地主服务器 + HTML5前端。FastGithub项目地址:https://github.com/dotnetcore/FastGithubgithub加速神器,解决github打不开、用户头像无法加载、releases无法上传下载、git-clone、git-pull、git-push失败等问题。AgileConfig项目地址:https://github.com/dotnetcore/AgileConfig基于.NET Core开发的轻量级分布式配置中心。YiShaAdmin项目地址:https://github.com/liukuo362573/YiShaAdminYiShaAdmin 基于.NET Core Web开发,借鉴了很多开源项目的优点,让你开发Web管理系统和移动端Api更简单,所以我也把她开源了。 她可以用于所有的Web应用程序,例如网站管理后台、CMS、CRM、ERP、OA这类的系统和移动端Api。MediatR项目地址:https://github.com/jbogard/MediatRMediatR是一款进程内的消息订阅、发布框架,提供了Send方法用于发布到单个处理程序、Publish方法发布到多个处理程序,使用起来非常方便。Autofac项目地址:https://github.com/autofac/AutofacAutofac 是.NET框架中最常用的依赖注入框架之一。相比.Net Core标准的依赖注入库, 它提供了更多高级特性, 比如动态代理和属性注入等。Mapster项目地址:https://github.com/MapsterMapper/Mapster一款高性能对象映射框架。AutoMapper项目地址:https://github.com/AutoMapper/AutoMapper一款功能强大的对象映射框架(在 .NET 领域的开发者中有非常高的知名度和使用率)。AspNetCoreRateLimit项目地址:https://github.com/stefanprodan/AspNetCoreRateLimitASP.NET Core 限速中间件。Polly项目地址:https://github.com/App-vNext/PollyPolly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以流畅和线程安全的方式表达重试、断路器、超时、隔板隔离和回退等策略。从 6.0.1 版开始,Polly 面向 .NET Standard 1.1 和 2.0+。bc-csharp项目地址:https://github.com/bcgit/bc-csharp一个提供了很多哈希算法和加密算法的C#第三方库。

C#/.NET/.NET Core优秀项目框架推荐

前言:  为.NET开源者提供的一个推荐自己优秀框架的地址,大家可以把自己的一些优秀的框架,或者项目链接地址存到在这里,提供给广大.NET开发者们学习(注意:排名不分先后,都是十分优秀的开源框架和项目💖)。Github项目仓库收集地址:https://github.com/YSGStudyHards/DotNetGuide/issues/5填写格式如下:项目or框架名称+访问链接地址+项目描述:📦NPOI-ExportWordAndExcel-ImportExcelData一个简单,易懂的通用ASP.NET Core NPOI导出复杂Word、复杂美观Excel和Excel数据导入详细示例开源项目(开箱即用,无需其他繁琐配置)。🏡C#/.NET Core/.NET项目宝库(收集了大量优秀的C#、.NET、.NET Core项目)该库主要是为我们.NET开发者提供一个寻找优秀C#/.NET Core/.NET项目的入口,通过了解和对比更多的项目来选择最适合我们自己学习、工作开发的一套项目。优秀的项目是不应该被埋没的,欢迎大家一起加入这个组织共同完善、发展.NET社区!【注意:这些都是非常优秀的作者所写的项目,排名不分先后,欢迎前往原址Star】Blog.Core项目地址:https://github.com/anjoy8/Blog.CoreBlog.Core一个开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x + RBAC】权限框架。官方文档地址:apk.neters.club/.docAspNetCore项目地址:https://github.com/dotnet/aspnetcoreASP.NETCore是一个跨平台的.NET框架,用于在Windows、Mac或Linux上构建基于云的现代web应用程序。WeiXinMPSDK项目地址:https://github.com/JeffreySu/WeiXinMPSDK微信公众平台SDK Senparc.Weixin for C#,支持.NET Framework及.NET Core。已支持微信公众号、小程序、小游戏、企业号、企业微信、开放平台、微信支付、JSSDK、微信周边等全平台。 WeChat SDK for C#.ABP Framework项目地址:https://github.com/abpframework/abpABP是一个开源应用程序框架,专注于基于ASP.NET Core的Web应用程序开发,但也支持开发其他类型的应用程序.官方文档地址:documentationUtil项目地址:https://github.com/dotnetcore/UtilUtil是一个.net core平台下的应用框架,旨在提升小型团队的开发输出能力,由常用公共操作类(工具类)、分层架构基类、Ui组件,第三方组件封装,第三方业务接口封装,配套代码生成模板,权限等组成。siteserver/cms项目地址:https://github.com/siteserver/cms是基于 .NET Core,能够以最低的成本、最少的人力投入在最短的时间内架设一个功能齐全、性能优异、规模庞大并易于维护的网站平台。OSharp项目地址:https://github.com/dotnetcore/OSharpOSharp是一个基于.NetCore的快速开发框架,框架对 AspNetCore 的配置、依赖注入、日志、缓存、实体框架、Mvc(WebApi)、身份认证、功能权限、数据权限等模块进行更高一级的自动化封装,并规范了一套业务实现的代码结构与操作流程,使 .Net Core 框架更易于应用到实际项目开发中。Vue.NetCore项目地址:https://github.com/cq-panda/Vue.NetCore.NetCore+Vue2/Vue3+Element plus+uniapp前后端分离,全自动生成代码;支持移动端(uniapp)ios/android/h5/微信小程序。OpenAuth.Net项目地址:https://gitee.com/dotnetchina/OpenAuth.Net.Net快速应用开发框架、最好用的权限工作流系统。基于经典领域驱动设计的权限管理及快速开发框架,源于Martin Fowler企业级应用开发思想及最新技术组合(IdentityServer、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE、Element-ui等)。已成功在docker/jenkins中实施。核心模块包括:组织机构、角色用户、权限授权、表单设计、工作流等。它的架构精良易于扩展,是中小企业的首选。ant-design-blazor项目地址:https://github.com/ant-design-blazor/ant-design-blazor一组基于Ant Design和Blazor WebAssembly的企业级UI组件。NetModular项目地址:https://github.com/iamoldli/NetModularNetModular 是基于.Net Core 和 Vue.js 的业务模块化以及前后端分离的快速开发框架。payment项目地址:https://github.com/essensoft/paylink一套基于 .NET Core 开发的支付SDK集,它极大简化了API调用及通知的处理流程。Furion项目地址:https://gitee.com/dotnetchina/Furion让 .NET 开发更简单,更通用,更流行。YuebonNetCore项目地址:https://gitee.com/yuebon/YuebonNetCore?_from=gitee_searchYuebonCore基于.Net5.0的权限管理及快速开发框架,前后端分离,核心模块包括:组织机构、角色用户、权限授权、多系统、多应用管理、定时任务、业务单据编码规则、代码生成器等,整合应用最新技术包括Asp.NetCore MVC、EF、Dapper、AutoFac、WebAPI、Swagger、Vue等。它的架构易于扩展,是中小企业的首选。 YuebonCore其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展,让Web开发更快速、简单,解决70%重复工作。轻松开发,专注您的业务,从YuebonCore FW开始!fulusso项目地址:https://github.com/fuluteam/fulusso基于react+asp.net core开发的单点登录系统Awesome DotNet Packages项目地址:https://github.com/mjebrahimi/Awesome-Nuget-Packages很棒的.NET程序包的集合。SuperSocket项目地址:https://github.com/kerryjiang/SuperSocketSuperSocket 是一个轻量级、跨平台和可扩展的套接字服务器应用程序框架。DotNetty项目地址:https://github.com/Azure/DotNettyDotNetty 项目——netty 的一个端口,事件驱动的异步网络应用框架。nopCommerce项目地址:https://github.com/nopSolutions/nopCommerce一个功能完善,且流行的.NET领域电商开源项目nopCommerce是最好的开源电子商务平台。nopCommerce 是免费的,它是最流行的 ASP.NET Core 购物车。CAP项目地址:https://github.com/dotnetcore/CAPCAP 是一个基于 .NET Standard 的 C# 库,它是一种处理分布式事务的解决方案,同样具有 EventBus 的功能,它具有轻量级、易使用、高性能等特点。金庸群侠传3D重制版项目地址:https://github.com/jynew/jynew金庸群侠传3D重制版是一个非盈利游戏项目,重制经典游戏《金庸群侠传》(在线玩DOS原版)并支持后续一系列MOD和二次开发。项目目标:使用Unity引擎重制并致敬经典游戏《金庸群侠传》DOS版;后续支持重制《金群》的一系列MOD或二次开发;提供开放的能力给社区,有兴趣贡献力量的朋友可以让这个作品更加完善;提供一个完备的单机游戏结构供有兴趣学习开发游戏的朋友进行参考;IdentityServer4.Admin项目地址:https://github.com/skoruba/IdentityServer4.AdminIdentityServer4 和 Asp.Net Core Identity的管理Surging项目地址:https://github.com/fanliang11/surgingsurging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper、Consul作为surging服务的注册中心,集成了哈希,随机,轮询,压力最小优先作为负载均衡的算法,RPC可以选择采用netty或thrift框架,采用异步非阻塞传输。Ocelot项目地址:https://github.com/ThreeMammals/OcelotOcelot 是一个 .NET API 网关。该项目面向使用 .NET 运行微服务/面向服务架构的人,他们需要一个统一的入口点进入他们的系统。但是,它适用于任何使用 HTTP 的内容并在 ASP.NET Core 支持的任何平台上运行。SqlSugar项目地址:https://github.com/donet5/SqlSugarSqlSugar是一款 老牌 .NET 开源ORM框架,由果糖大数据科技团队维护和更新 ,1. .NET中唯一支持全自动分表组件,SAAS分库,大数据处理的ORM2. .NET 百万级写入、更新 性能最强框架3. 使用最简单的ORM 【文档,视频教程】4. 媲美原生的极限的性能5.Github star数仅次于EF 和 Dapper,每月nuget下载量超过1万更多优点: 简单易用、功能齐全、高性能、轻量级、服务齐全、官网教程文档、有专业技术支持一天18小时服务支持数据库:MySql、SqlServer、Sqlite、Oracle 、 postgresql、达梦、人大金仓、神通数据库FreeSql项目地址:https://github.com/dotnetcore/FreeSqlFreeSql 是一款功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。🛠 支持 CodeFirst 模式,即便使用 Access 数据库也支持数据迁移;💻 支持 DbFirst 模式,支持从数据库导入实体类,或使用实体类生成工具生成实体类;⛳ 支持 深入的类型映射,比如 PgSql 的数组类型等;✒ 支持 丰富的表达式函数,以及灵活的自定义解析;🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载;📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/Access 等数据库;csredis项目地址:https://github.com/2881099/csredis适用于 Redis 和 Redis Sentinel (2.8) 和集群的 .NET Core 或 .NET Framework 4.0+ 客户端。包括同步和异步客户端。FreeRedis项目地址:https://github.com/2881099/FreeRedisFreeRedis 是 .NET40+ Redis 客户端。支持集群、哨兵、主从、发布-订阅、lua、管道、事务、流、客户端缓存和池化。Orleans项目地址:https://github.com/dotnet/orleansOrleans建立在.NET开发人员生产力的基础上,并将其带入了分布式应用程序的世界,例如云服务。 Orleans可从单个本地服务器扩展到云中全局分布的高可用性应用程序。Orleans采用了对象,接口,async/await和try/catch等熟悉的概念,并将其扩展到多服务器环境。 这样,它可以帮助具有单服务器应用程序经验的开发人员过渡到构建弹性,可扩展的云服务和其他分布式应用程序。 因此,Orleans通常被称为“分布式.NET”。它是由Microsoft Research 创建的,并介绍了Virtual Actor Model作为一种新方法来构建面向云时代的新一代分布式系统。 Orleans的核心贡献是它的编程模型,它在不限制功能,以及对开发人员施加繁重约束的情况下,降低了高并发分布式系统固有的复杂性。FreeIM项目地址:https://github.com/2881099/FreeIM.NETCore websocket 实现简易、高性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。FreeIM 使用 websocket 协议实现简易、高性能(单机支持5万+连接)、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。 ImCore 已正式改名为 FreeIM。【网络版斗地主示例】FightLandlord项目地址:https://github.com/2881099/FightLandlord.NETCore斗地主服务器 + HTML5前端。FastGithub项目地址:https://github.com/dotnetcore/FastGithubgithub加速神器,解决github打不开、用户头像无法加载、releases无法上传下载、git-clone、git-pull、git-push失败等问题。AgileConfig项目地址:https://github.com/dotnetcore/AgileConfig基于.NET Core开发的轻量级分布式配置中心。YiShaAdmin项目地址:https://github.com/liukuo362573/YiShaAdminYiShaAdmin 基于.NET Core Web开发,借鉴了很多开源项目的优点,让你开发Web管理系统和移动端Api更简单,所以我也把她开源了。 她可以用于所有的Web应用程序,例如网站管理后台、CMS、CRM、ERP、OA这类的系统和移动端Api。MediatR项目地址:https://github.com/jbogard/MediatRMediatR是一款进程内的消息订阅、发布框架,提供了Send方法用于发布到单个处理程序、Publish方法发布到多个处理程序,使用起来非常方便。Autofac项目地址:https://github.com/autofac/AutofacAutofac 是.NET框架中最常用的依赖注入框架之一。相比.Net Core标准的依赖注入库, 它提供了更多高级特性, 比如动态代理和属性注入等。Mapster项目地址:https://github.com/MapsterMapper/Mapster一款高性能对象映射框架。AutoMapper项目地址:https://github.com/AutoMapper/AutoMapper一款功能强大的对象映射框架(在 .NET 领域的开发者中有非常高的知名度和使用率)。AspNetCoreRateLimit项目地址:https://github.com/stefanprodan/AspNetCoreRateLimitASP.NET Core 限速中间件。Polly项目地址:https://github.com/App-vNext/PollyPolly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以流畅和线程安全的方式表达重试、断路器、超时、隔板隔离和回退等策略。从 6.0.1 版开始,Polly 面向 .NET Standard 1.1 和 2.0+。bc-csharp项目地址:https://github.com/bcgit/bc-csharp一个提供了很多哈希算法和加密算法的C#第三方库。

Kubernetes(K8S)是什么?

概述  Kubernetes,又称为 k8s(首字母为 k、首字母与尾字母之间有 8 个字符、尾字母为 s,所以简称 k8s)或者简称为 "kube" ,是一种可自动实施 Linux 容器操作的开源平台。它可以帮助用户省去应用容器化过程的许多手动部署和扩展操作。也就是说,您可以将运行 Linux 容器的多组主机聚集在一起,由 Kubernetes 帮助您轻松高效地管理这些集群。而且,这些集群可跨公共云、私有云或混合云部署主机。因此,对于要求快速扩展的云原生应用而言(例如借助 Apache Kafka 进行的实时数据流处理),Kubernetes 是理想的托管平台。  Kubernetes 最初由 Google 的工程师开发和设计。Google 是最早研发 Linux 容器技术的企业之一(组建了cgroups),曾公开分享介绍 Google 如何将一切都运行于容器之中(这是 Google 云服务背后的技术)。Google 每周会启用超过 20 亿个容器——全都由内部平台 Borg 支撑。Borg 是 Kubernetes 的前身,多年来开发 Borg 的经验教训成了影响 Kubernetes 中许多技术的主要因素。为什么需要 Kubernetes?  真正的生产型应用会涉及多个容器。这些容器必须跨多个服务器主机进行部署。容器安全性需要多层部署,因此可能会比较复杂。但 Kubernetes 有助于解决这一问题。Kubernetes 可以提供所需的编排和管理功能,以便您针对这些工作负载大规模部署容器。借助 Kubernetes 编排功能,您可以构建跨多个容器的应用服务、跨集群调度、扩展这些容器,并长期持续管理这些容器的健康状况。有了 Kubernetes,您便可切实采取一些措施来提高 IT 安全性。  Kubernetes 还需要与联网、存储、安全性、遥测和其他服务整合,以提供全面的容器基础架构。  当然,这取决于您如何在您的环境中使用容器。Linux 容器中的基本应用将它们视作高效、快速的虚拟机。一旦把它部署到生产环境或扩展为多个应用,您显然需要许多托管在相同位置的容器来协同提供各种服务。随着这些容器的累积,您运行环境中容器的数量会急剧增加,复杂度也随之增长。  Kubernetes 通过将容器分类组成"容器集" (pod) ,解决了容器增殖带来的许多常见问题容器集为分组容器增加了一个抽象层,可帮助您调用工作负载,并为这些容器提供所需的联网和存储等服务。Kubernetes 的其它部分可帮助您在这些容器集之间达成负载平衡,同时确保运行正确数量的容器,充分支持您的工作负载。  如果能正确实施 Kubernetes,再辅以其它开源项目(例如 Atomic 注册表、Open vSwitch、heapster、OAuth 以及 SELinux),您就能够轻松编排容器基础架构的各个部分。Kubernetes 有哪些应用?  在您生产环境中(尤其是当您要面向云优化应用开发时)使用 Kubernetes 的主要优势在于,它提供了一个便捷有效的平台,让您可以在物理机和虚拟机集群上调度和运行容器。更广泛一点说,它可以帮助您在生产环境中,完全实施并依托基于容器的基础架构运营。由于 Kubernetes 的实质在于实现操作任务自动化,所以您可以将其它应用平台或管理系统分配给您的许多相同任务交给容器来执行。利用 Kubernetes,您能够达成以下目标:跨多台主机进行容器编排。更加充分地利用硬件,最大程度获取运行企业应用所需的资源。有效管控应用部署和更新,并实现自动化操作。挂载和增加存储,用于运行有状态的应用。快速、按需扩展容器化应用及其资源。对服务进行声明式管理,保证所部署的应用始终按照部署的方式运行。利用自动布局、自动重启、自动复制以及自动扩展功能,对应用实施状况检查和自我修复。但是,Kubernetes 需要依赖其它项目来全面提供这些经过编排的服务。因此,借助其它开源项目可以帮助您将 Kubernetes 的全部功用发挥出来。这些功能包括:注册表,通过 Atomic 注册表或 Docker 注册表等项目实现。联网,通过 OpenvSwitch 和智能边缘路由等项目实现。遥测,通过 heapster、kibana、hawkular 和 elastic 等项目实现。安全性,通过 LDAP、SELinux、RBAC 和 OAUTH 等项目以及多租户层来实现。自动化,参照 Ansible 手册进行安装和集群生命周期管理。服务,可通过自带预建版常用应用模式的丰富内容目录来提供。Kubernetes 相关术语Kubernetes官方文档相关术语表👉:https://kubernetes.io/zh-cn/docs/reference/和其它技术一样,Kubernetes 也会采用一些专用的词汇,这可能会对初学者理解和掌握这项技术造成一定的障碍。为了帮助您了解 Kubernetes,我们在下面来解释一些常用术语。主机(Master): 用于控制 Kubernetes 节点的计算机。所有任务分配都来自于此。节点(Node):负责执行请求和所分配任务的计算机。由 Kubernetes 主机负责对节点进行控制。容器集(Pod):被部署在单个节点上的,且包含一个或多个容器的容器组。同一容器集中的所有容器共享同一个 IP 地址、IPC、主机名称及其它资源。容器集会将网络和存储从底层容器中抽象出来。这样,您就能更加轻松地在集群中移动容器。复制控制器(Replication controller):用于控制应在集群某处运行的完全相同的容器集副本数量。服务(Service):将工作内容与容器集分离。Kubernetes 服务代理会自动将服务请求分发到正确的容器集——无论这个容器集会移到集群中的哪个位置,甚至可以被替换掉。Kubelet:运行在节点上的服务,可读取容器清单(container manifest),确保指定的容器启动并运行。kubectl: Kubernetes 的命令行配置工具。如何在基础架构中采用Kubernetes Kubernetes 基于操作系统运行(例如红帽企业Linux),并与在节点上运行的容器集交互。由 Kubernetes 主机接收管理员(或 DevOps 团队)发出的命令,然后将这些指令转发给从属的节点。这种移交操作与多种服务同时作用,自动确定哪个节点最适合执行该任务。然后,它将在该节点分配资源,并指派容器集来完成任务请求。因此,就基础架构而言,管理容器的方式基本没变。但您对容器的掌控力得到提升,无需对独立的容器或节点实施微观管理,就能更好地管理容器。当然,某些工作是必须的,但大部分都是关于分配 Kubernetes 主机、定义节点以及定义容器集。Docker运行状态  Docker(点击查看Docker原理)技术仍然执行它原本的工作。当 kubernetes 将容器集调度到一个节点上时,该节点上的 kubelet 会发送指令让 docker 启动指定的容器。kubelet 随后会不断从 docker 收集这些容器的状态,并将这些信息汇集至主机。Docker 将容器拉至该节点,并按照常规启动和停止这些容器。不同在于,自动化系统要求 docker 在所有节点上对所有容器执行这些操作,而非要求管理员手动操作。

Docker安装MySQL并使用Navicat连接

MySQL简单介绍:  MySQL 是一个开放源码的关系数据库管理系统,开发者为瑞典 MySQL AB 公司。目前 MySQL 被广泛地应用在 Internet 上的大中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了 MySQL 作为网站数据库。查看可用的MySQL版本:访问DokcerHub中的MySQL镜像库地址:https://hub.docker.com/_/mysql/tags可以通过 Sort by 查看其他版本的MySQL,查看最新版本MySQL镜像(mysql:latest):https://hub.docker.com/_/mysql/tags?page=1&name=latest 此外,我们还可以用docker search mysql命令来查看可用版本:部拉取最新版本的MySQL镜像:docker pull mysql:latest注意:tag是可选的,tag表示标签,多为软件的版本,默认是latest版本(最新版)部验证MySQL镜像是否成功拉取到本地:使用以下命令来查看mysql镜像是否成功拉取到本地:docker images创建并运行一个MySQL容器:docker run --name=mysql-test -itd -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root123456 -d mysql参数说明:--name:指定了容器的名称,方便之后进入容器的命令行。-itd:其中,i是交互式操作,t是一个终端,d指的是在后台运行。-p:指在本地生成一个随机端口,用来映射mysql的3306端口。-e:设置环境变量。MYSQL_ROOT_PASSWORD=root123456:指定了MySQL的root密码-d mysql:指运行mysql镜像,设置容器在在后台一直运行。验证MySQL容器是否创建并运行成功:docker ps1、进入MySQL容器:docker exec -it mysql-test /bin/bash2、进入MySQL:mysql -uroot -p Enter password:root123456MySQL开启远程访问权限:1、切换数据库注意:默认应该就是这个,不切换也行,保险起见还是切换一下use mysql;2、给root用户分配远程访问权限GRANT ALL PRIVILEGES ON *.* TO root@'%' WITH GRANT OPTION;参数说明:GRANT:赋权命令ALL PRIVILEGES:当前用户的所有权限ON:介词*.*:当前用户对所有数据库和表的相应操作权限TO:介词‘root’@’%’:权限赋给root用户,所有ip都能连接WITH GRANT OPTION:允许级联赋权3、强制刷新权限FLUSH PRIVILEGES;服务器配置3306的开放端口:Navicat 连接 MySQL8 报错:2059 - Authentication plugin ‘caching_sha2_password’ cannot be loaded:xxxx;错误问题原因:  这是因为MySQL8之前密码加密规则为mysql_native_password,而 MySQL8 之后的加密规则为caching_sha2_password,也就是说,如果要用Navicat连接MySQL,其实只需要将密码规则改回 mysql_native_password 即可;解决方法:1.进入MySQL数据库docker exec -it mysql-test /bin/bash mysql -uroot -p Enter password:root1234562.选择数据库use mysql;3.更改密码加密方式IDENTIFIED BY ‘root123456’:连接时输入密码,密码为root123456ALTER USER 'root'@'%' IDENTIFIED BY 'root123456' PASSWORD EXPIRE NEVER;4.更新用户密码ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root123456';5.刷新权限FLUSH PRIVILEGES;Navicat连接MySQL测试:

Docker安装Redis并使用Another Redis Desktop Manager连接

Redis简单介绍Redis全称是Remote DIctionary Service,即远程字典服务。Redis 是一个使用C语言编写的、开源的(遵守 BSD 协议)、高性能的、支持网络、可基于内存亦可持久化的日志型、Key-Value的NoSQL数据库。查看可用的 Redis 版本访问DokcerHub中的Redis镜像库地址:https://hub.docker.com/_/redis?tab=tags可以通过 Sort by 查看其他版本的 Redis,默认是最新版本(redis:latest):https://hub.docker.com/_/redis/tags?page=1此外,我们还可以用 docker search redis 命令来查看可用版本:docker search redis输出如下:拉取最新版的Redis镜像这里我们拉取官方的最新版本的镜像:docker pull redis:latest查看本地安装的镜像使用以下命令来查看redis镜像是否成功拉取到本地:docker images设置Docker中的Redis容器运行外网连接首先Docker运行的每个容器都是隔离的,Redis默认不允许外部连接,因此想要部署在Docker容器内的应用连接上Redis,需要修改Redis默认配置,这里我们以配置文件运行redis即可。1、下载redis.conf文件首先创建挂载目录:sudo mkdir redisredis.conf是Redis的核心配置文件,默认docker运行的redis是不存在配置文件的,这里可以先从官网下载:wget http://download.redis.io/redis-stable/redis.conf2、设置redis.conf文件权限sudo chown -R $USER redis.conf-R或-recursive:递归处理,将指定目录下的所有文件及子目录一并处理chown [-R] [用户名称:组名称] [文件或目录]3、修改默认配置信息vi redis.confi 开始编辑编辑完成后esc+:wq保存修改bind 127.0.0.1 -::1  #这行要注释掉,解除本地连接限制protected-mode no  #默认yes,如果设置为yes,则只允许在本机的回环连接,其他机器无法连接。daemonize no  #默认no 为不守护进程模式,docker部署不需要改为yes,docker run -d本身就是后台启动,不然会冲突requirepass 123456  #设置密码appendonly yes  #持久化创建并运行一个Redis容器和设置链接密码Redis镜像拉取成功以后,我们可以使用以下命令来运行创建一个名为redis-test的redis容器:docker run --name redis-test -p 6379:6379 -v /docker-data/redis/redis.conf:/etc/redis/redis.conf -v /docker-data/redis:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes --requirepass 123456参数说明: --name redis-test:容器名称。-p 6379:6379:映射容器服务的 6379 端口到宿主机的 6379 端口。外部可以直接通过宿主机ip:6379 访问到 Redis 的服务。-v /docker-data/redis/redis.conf:/etc/redis/redis.conf : 将主机中配置文件挂载到容器中-v /docker-data/redis:/data : 将主机中data挂载到容器的/redis-d redis redis-server /etc/redis/redis.conf:表示后台启动redis,以配置文件启动redis,加载容器内的conf文件。redis-server /etc/redis/redis.conf : 容器中以配置文件方式启动redisredis-server --appendonly yes : 在容器执行redis-server启动命令,并打开redis持久化配置redis-server --requirepass 123456 :redis连接密码设置  验证Redis是否安装成功最后我们可以通过 docker ps 命令查看容器的运行信息:docker ps接着我们通过 redis-cli 连接测试使用 redis 服务。docker exec -it redis-test /bin/bash redis-cli # 密码登录 auth 123456Another Redis Desktop Manager介绍:  Redis DeskTop Manager自从进入了0.9.9版本就开始付费使用或者贡献代码获得免费使用期限。这时候,Another Redis DeskTop Manager作为一款基于nodejs开发的免费的Redis可视化管理工具,可以运行在Windows、Linux、Mac平台,而且是开源免费应用,就很推荐使用了。gitee源码地址:https://gitee.com/qishibo/AnotherRedisDesktopManagerwindow .exe安装包下载地址:https://gitee.com/qishibo/AnotherRedisDesktopManager/releasesRedis Client On Error: Error: connect ETIMEDOUT xxx.xxx.xxx:6379 Config right?由于上面我已经对redis.conf配置文件进行了允许外网连接配置的修改,报这个错误我猜测是因为服务器没有配置6379的开放端口,所以需要到服务器后端管理中添加6379端口配置。Another Redis Desktop Manager测试连接:

Ubuntu添加非root用户到Docker用户组

前言  首先平常公司的Linux生产环境为了防止误操作导致灾难性问题,一般都不会给我们开发开放root管理员的账号权限。所以平常在Ubuntu的普通用户登录的时候,要操作Dcoker一般都需要带上sudo来提升命令执行权限。为了解决这一问题,我们只需要将Docker假如到sudo用户组,即可默认sudo权限运行。permission denied问题lighthouse@VM-16-10-ubuntu:~$ docker ps Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied lighthouse@VM-16-10-ubuntu:~$ docker images Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/json": dial unix /var/run/docker.sock: connect: permission denied lighthouse@VM-16-10-ubuntu:~$ 验证是否有Docker用户组正常情况下,安装完Docker以后会自动创建一个用户组,执行以下命令验证即可:grep docker /etc/group添加Docker用户组sudo groupadd docker将当前登录用户添加到Docker用户组$USER是一个Linux 的环境变量,表示的是当前用户的用户名。sudo gpasswd -a $USER docker更新Docker用户组newgrp dockery 验证执行Dcoker命令不加sudo是否能正常运行

Visual Studio 2022 git error Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa

前言  前两天因为升级了Git导致git提交拉取的时候都提示下面这个异常,然后经过一番折腾以后终于把这个问题解决了。但是今天我升级了下Visual Studio 2022将其升级到了17.1.3版本然后又出现了这个问题,奇怪的是我使用VS 2019没有问题(VS2019没有升级),然后使用Git Bash也是可以正常拉取提交。唯独使用VS 2022就提示下面的异常(真的是问题天天有,四月特别多):Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa Git failed with a fatal error. Git failed with a fatal error. Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.vs 2022版本问题分析因为Visual Studio IDE有自己的Git扩展,既然我们设置了Git在C盘中的.SSH目录中的config配置无效,那会不会在VS 2022里面也会有一个类型于这样的配置呢?于是我搜索了一下果然让我发现了端倪。vs2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\etc\ssh如下是我对比VS2019和VS2022的配置:解决方案一,切换成HTTPS的方式1、修改本地代码关联的远程地址git remote set-url origin https://gitee.com/ysgdaydayup/pingrixuexilianxi.git2、重新拉取成功 git pulll解决方案二,在ssh_config配置文件中添加对应主机地址配置我们其实直接Copy一下VS2022新增现有配置,然后修改一下主机地址就可以了(注意添加好配置以后一定要重启一下VS 2022才会生效)。1、该配置指的是对所有主机生效Host * HostkeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsa2、指定对应主机生效(xx.xxx.xxxx:22)Host xx.xxx.xxxx:22 HostkeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsa

Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa(解决的两种方式)

异常问题:  下班之前升级了一下Git的版本,结果第二天过来拉取远程最新代码的时候就提示了下面的异常问题:Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa Git failed with a fatal error. Git failed with a fatal error. Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.问题分析:  通过翻译上面的报错信息大概说的是没有匹配到类型为ssh-rsa的主机秘钥。或者是可能你的代码仓库权限没有了。于是我上代码托管平台看了下我的项目权限是否被修改了,结果发现没有变更(这个可能性别排除了)。然后既然是ssh-rsa秘钥的问题,我就是试着把本机的ssh-key重生生成了一次再去托管平台添加,然后依旧还是包这个错。解决方案一,切换成HTTPS的方式1、修改本地代码关联的远程地址git remote set-url origin https://gitee.com/ysgdaydayup/pingrixuexilianxi.git2、重新拉取成功 git pulll解决方案二、在.ssh文件中创建config文件并添加配置 添加如下匹配:第一行说明对所有主机生效,当然你也可以指定对应主机地址!Host * HostkeyAlgorithms +ssh-rsa PubkeyAcceptedKeyTypes +ssh-rsa

C#复杂XML反序列化为实体对象两种方式 (上)

前言  今天主要讲的是如何把通过接口获取到的Xml数据转换成(反序列化)我们想要的实体对象,当然Xml反序列化和Json反序列化的方式基本上都是大同小异。都是我们事先定义好对应的对应的Xml实体模型,不过Xml是通过XmlSerializer类的相关特性来对实体对象和 XML文档之间进行序列化和反序列化操作的。序列化和反序列化其实都还好,我们可以调用封装好的XmlHelper帮助类即可实现,最关键的是我们该如何去定义这些实体模型(Model)。当你遇到对方接口一下子返回一大串的Xml数据并且里面存在很多不同的Xml节点,你该怎么办一个一个去解析这些节点到模型上去吗?本文我主要讲两种方式,第一种方法是通过手写的方式去定义Xml的实体对象模型类,第二种方法是通过Visual Studio自带的生成Xml实体对象模型类。需要操作的Xml数据注意:以下是我稍微简化的Xml数据,实际数据可能比这里要复杂个大几倍。<?xml version="1.0" encoding="utf-8" ?> <envelope> <header> <version port="1111" host="www.baidu.com">successfuly</version> <timestamp>20211216081218</timestamp> </header> <response type="cities" product="hotel"> <cities> <city> <code value="zg" /> <city_tax value="true" /> <names> <name language="fr" value="ABANO TERME - PADOUE" /> <name language="en" value="ABANO TERME - PADUE" /> <name language="nl" value="ABANO TERME - PADUE" /> </names> </city> <city> <code value="hk" /> <city_tax value="false" /> <names> <name language="fr" value="ABBADIA SAN SALVATORE - SIENNE" /> <name language="en" value="ABBADIA SAN SALVATORE - SIENA" /> <name language="nl" value="ABBADIA SAN SALVATORE - SIENA" /> </names> </city> </cities> </response> </envelope>一、通过是手写的方式去定义Xml的实体对象模型类当然假如你有耐心、时间充足并且眼睛好的话可以使用这种手写的方式去定义,很多情况写到最好都会把自己给写糊涂了(可能是我年纪大了的原因)。namespace Practices.Models /// <summary> /// Envelope /// </summary> [XmlType(TypeName = "envelope")] public class CityDataModel /// <summary> /// header /// </summary> [XmlElement("header")] public Header header { get; set; } /// <summary> /// response /// </summary> [XmlElement("response")] public Response response { get; set; } /// <summary> /// Header /// </summary> [XmlType(TypeName = "header")] public class Header /// <summary> /// version /// </summary> [XmlElement("version")] public Version version { get; set; } /// <summary> /// timestamp /// </summary> [XmlElement("timestamp")] public string timestamp { get; set; } /// <summary> /// Version /// </summary> public class Version /// <summary> /// port /// </summary> [XmlAttribute("port")] public string port { get; set; } /// <summary> /// host /// </summary> [XmlAttribute("host")] public string host { get; set; } /// <summary> /// value:XmlTextAttribute指示该属性作为XML文本处理 /// </summary> [XmlTextAttribute()] public string value { get; set; } /// <summary> /// Response /// </summary> [XmlType(TypeName = "response")] public class Response /// <summary> /// type /// </summary> [XmlAttribute] public string type { get; set; } /// <summary> /// product /// </summary> [XmlAttribute] public string product { get; set; } /// <summary> /// cities /// </summary> [XmlArray("cities")] public List<City> cities { get; set; } /// <summary> /// class: City /// </summary> [XmlType(TypeName = "city")] public class City /// <summary> /// code /// </summary> [XmlElement("code")] public Code code { get; set; } /// <summary> /// city_tax /// </summary> [XmlElement("city_tax")] public City_tax city_tax { get; set; } /// <summary> /// names /// </summary> [XmlArray("names")] public List<Name> names { get; set; } /// <summary> /// class: Code /// </summary> [XmlType(TypeName = "code")] public class Code /// <summary> /// </summary> [XmlAttribute("value")] public string value { get; set; } /// <summary> /// class: City_tax /// </summary> [XmlType(TypeName = "city_tax")] public class City_tax /// <summary> /// </summary> [XmlAttribute("value")] public string value { get; set; } /// <summary> /// class: Name /// </summary> [XmlType(TypeName = "name")] public class Name /// <summary> /// </summary> [XmlAttribute("language")] public string language { get; set; } /// <summary> /// </summary> [XmlAttribute("value")] public string value { get; set; } }二、通过Visual Studio自带的生成Xml实体对象模型类Vs被称为宇宙最强IDE也不是没有理由的,它集成了很多自动创建功能,如自动生成Json类、Xml类等,虽然说使用Vs自动生成的Xml模型可读性有点差并且有些冗余,但是快捷省事,只需要略微改动一下即可使用。1、首先Ctrl+C复制你需要生成的Xml文档内容2、找到编辑=》选择性粘贴=》将Xml粘贴为类3、以下是使用VS自动生成的Xml类namespace Practices.Models // 注意: 生成的代码可能至少需要 .NET Framework 4.5 或 .NET Core/Standard 2.0。 /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] //TODO:注意这里因为我把类名改成了我自定义的,所以在TypeName这里需要声明Xml文档的节点名 [System.Xml.Serialization.XmlTypeAttribute(typeName: "envelope")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] public partial class NewCityDataModel private envelopeHeader headerField; private envelopeResponse responseField; /// <remarks/> public envelopeHeader header return this.headerField; this.headerField = value; /// <remarks/> public envelopeResponse response return this.responseField; this.responseField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeHeader private envelopeHeaderVersion versionField; private ulong timestampField; /// <remarks/> public envelopeHeaderVersion version return this.versionField; this.versionField = value; /// <remarks/> public ulong timestamp return this.timestampField; this.timestampField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeHeaderVersion private ushort portField; private string hostField; private string valueField; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public ushort port return this.portField; this.portField = value; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string host return this.hostField; this.hostField = value; /// <remarks/> [System.Xml.Serialization.XmlTextAttribute()] public string Value return this.valueField; this.valueField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponse private envelopeResponseCity[] citiesField; private string typeField; private string productField; /// <remarks/> [System.Xml.Serialization.XmlArrayItemAttribute("city", IsNullable = false)] public envelopeResponseCity[] cities return this.citiesField; this.citiesField = value; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string type return this.typeField; this.typeField = value; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string product return this.productField; this.productField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCity private envelopeResponseCityCode codeField; private envelopeResponseCityCity_tax city_taxField; private envelopeResponseCityName[] namesField; /// <remarks/> public envelopeResponseCityCode code return this.codeField; this.codeField = value; /// <remarks/> public envelopeResponseCityCity_tax city_tax return this.city_taxField; this.city_taxField = value; /// <remarks/> [System.Xml.Serialization.XmlArrayItemAttribute("name", IsNullable = false)] public envelopeResponseCityName[] names return this.namesField; this.namesField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityCode private string valueField; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string value return this.valueField; this.valueField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityCity_tax private bool valueField; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public bool value return this.valueField; this.valueField = value; /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class envelopeResponseCityName private string languageField; private string valueField; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string language return this.languageField; this.languageField = value; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string value return this.valueField; this.valueField = value; }验证两个Xml类是否能够反序列化成功 /// <summary> /// 读取Xml文件内容反序列化为指定的对象 /// </summary> /// <param name="filePath">Xml文件的位置(绝对路径)</param> /// <returns></returns> public static T DeserializeFromXml<T>(string filePath) if (!File.Exists(filePath)) throw new ArgumentNullException(filePath + " not Exists"); using (StreamReader reader = new StreamReader(filePath)) XmlSerializer xs = new XmlSerializer(typeof(T)); T ret = (T)xs.Deserialize(reader); return ret; catch (Exception ex) return default(T);

.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结(XmlSerializer,XmlTypeAttribute,XmlElementAttribute,XmlAttributeAttribute,XmlArrayAttribute...)

序列化和反序列化是指什么?序列化(seriallization): 将对象转化为便于传输的数据格式, 常见的序列化格式:二进制格式,字节数组,json字符串,xml字符串。反序列化(deseriallization):将序列化的数据恢复为对象的过程。XmlSerializer类  该类用一种高度松散耦合的方式提供串行化服务。你的类不需要继承特别的基类,而且它们也不需要实现特别的接口。相反,你只需在你的类或者这些类的公共域以及读/写属性里加上自定义的特性。XmlSerializer通过反射机制读取这些特性并用它们将你的类和类成员映射到xml元素和属性(在对象和 XML 文档之间进行序列化和反序列化操作)。.NET-XML序列化和反序列化简单示例代码using System.IO; using System.Xml.Serialization; namespace Practices.Common public class SimpleSerializer /// <summary> /// Model实体对象序列化为XML字符串 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="t">Model实体对象</param> /// <returns></returns> public static string SerializeXMLL<T>(T t) using (StringWriter sw = new StringWriter()) XmlSerializer xmlSerializer = new XmlSerializer(t.GetType()); xmlSerializer.Serialize(sw, t); return sw.ToString(); /// <summary> /// XML反序列化为对象 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="xml">xml字符串</param> /// <returns></returns> public static T Deserialize<T>(string xml) XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); StringReader stringReader = new StringReader(xml); return (T)xmlSerializer.Deserialize(stringReader); }XmlTypeAttribute类   该类主要控制当属性目标由XML序列化时生成的XML节点。应用示例/// <summary> /// Envelope /// </summary> [XmlType(TypeName = "envelope")] public class CityRes public Header header { get; set; } public Response response { get; set; } }XmlElementAttribute类   该类用于指示公共字段或属性在XML序列化或反序列化包含它们的对象时表示XML元素。应用示例/// <summary> /// Envelope /// </summary> public class CityRes /// <summary> /// header /// </summary> [XmlElement("header")] public Header header { get; set; } /// <summary> /// response /// </summary> [XmlElement("response")] public Response response { get; set; } }XmlAttributeAttribute类  该类指定XML序列化必须将类成员序列化为XML属性。应用示例/// <summary> /// Version /// </summary> public class Version /// <summary> /// port /// </summary> [XmlAttribute("port")] public string port { get; set; } /// <summary> /// host /// </summary> [XmlAttribute("host")] public string host { get; set; } /// <summary> /// text /// </summary> [XmlAttribute("text")] public string text { get; set; } }XmlArrayAttribute类  该类主要用于XML元素数组的应用(相当于就是集合的声明)。应用示例[XmlArray] public Item []Items get{return items;} set{items = value;} }XmlTextAttribute类  当Xml文档序列化或反序列化时使用该特性修饰的成员会作为XML文本处理。应用示例[System.Xml.Serialization.XmlTextAttribute()] public string[] Text return this.textField; this.textField = value; }XmlIgnoreAttribute类   指示该特性修饰的对象在Xml序列化时不会序列化该特性指定的元素。应用示例public class TeamGroup [XmlIgnore] public string Comment; public string GroupName; }用来控制XML序列化的属性汇总通过将下表中的特性应用于类和类成员,可以控制 XmlSerializer 序列化或反序列化该类的实例的方式。 若要了解这些属性如何控制 XML 序列化,请参阅使用属性控制 XML 序列化。特性适用对象指定XmlAnyAttributeAttribute公共字段、属性、参数或返回 XmlAttribute 对象数组的返回值。反序列化时,将会使用 XmlAttribute 对象填充数组,而这些对象代表对于架构未知的所有 XML 特性。XmlAnyElementAttribute公共字段、属性、参数或返回 XmlElement 对象数组的返回值。反序列化时,将会使用 XmlElement 对象填充数组,而这些对象代表对于架构未知的所有 XML 元素。XmlArrayAttribute公共字段、属性、参数或返回复杂对象的数组的返回值。数组成员将作为 XML 数组的成员生成。XmlArrayItemAttribute公共字段、属性、参数或返回复杂对象的数组的返回值。可以插入数组的派生类型。 通常与 XmlArrayAttribute 一起应用。XmlAttributeAttribute公共字段、属性、参数或返回值。成员将作为 XML 属性进行序列化。XmlChoiceIdentifierAttribute公共字段、属性、参数或返回值。可以使用枚举进一步消除成员的歧义。XmlElementAttribute公共字段、属性、参数或返回值。字段或属性将作为 XML 元素进行序列化。XmlEnumAttribute作为枚举标识符的公共字段。枚举成员的元素名称。XmlIgnoreAttribute公共属性和公共字段。序列化包含类时,应该忽略属性或字段。XmlIncludeAttribute公共派生类声明,以及 Web 服务描述语言 (WSDL) 文档的公共方法的返回值。生成要在序列化时识别的架构时,应该将该类包括在内。XmlRootAttribute公共类声明。控制视为 XML 根元素的属性目标的 XML 序列化。 使用该属性可进一步指定命名空间和元素名称。XmlTextAttribute公共属性和公共字段。属性或字段应该作为 XML 文本进行序列化。XmlTypeAttribute公共类声明。XML 类型的名称和命名空间。

30分钟使用Docsify+Github Pages搭建个人博客

前言  现如今网上有许多完善的博客平台,如博客园、掘金、思否、知乎等。有人会说为什么现在网上有这么多成熟的博客平台,你还要浪费时间搭建一个自己的博客平台呢?首先我相信每一个程序员都会想要拥有一个属于自己的博客系统,其次使用Docsify能够快速构建一个自己的博客文档系统,最后我们可以通过Github Pages免费托管我们的博客系统文档(连域名和服务器都省了)这样的一次难得的实战机会我们又怎么能够错过呢。废话不多说,接下来步入正题。Docsify使用配置指南Docsify使用指南(打造最快捷、最轻量级的个人&团队文档)👉轻量&完善的Docsify模板  该模板为一个简洁,并且完善的Docsify模板基本上可以满足百分之八十多的团队需求,你可以按照文章中的Docsify环境配置教程把运行Docsify所需要的环境配置起来,通过命令即可查看效果(配置环境顺利的话只要十来分钟)。模板源码地址:Docsify-Guide👉模板预览地址:https://ysgstudyhards.github.io/Docsify-Guide/#/👉选择对应的存储库单击设置(Settings)点击左侧的Pages选择对应分支的发布源文件夹部保存发布即可访问Github Pages访问地址:https://ysgstudyhards.github.io/Docsify-Guide/

Typora+Docsify快速入门

Typora是什么? Typora中文版是一款好用极简的跨平台Markdown编辑器,软件使用这款软件能够帮助用户轻松将文本转换到HTML,软件从底层向上设计,软件支持markdown的标准语法,同时这款软件还支持动态预览功能,一键预览,让一切都变得如此干净、纯粹。虽然Typora 正式发布1.0 版本,进入了付费时代(假如需要体验新功能的话可以付费只要一次性支付人民币 89 元,可以在 3 台设备里使用。),不过我觉得beta版之前的免费版也是完全可以满足大家的需求的。Typora中文网https://www.typora.net/👉Typora下载地址https://typora.io/#download👉Typora相关主题https://www.typora.net/themes/👉部Markdown是什么?Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,Markdown文件的后缀名便是“.md”。Markdown是一种轻量级标记语言,排版语法简洁,让人们更多地关注内容本身而非排版。它使用易读易写的纯文本格式编写文档,可与HTML混编,可导出 HTML、PDF 以及本身的 .md 格式的文件。因简洁、高效、易读、易写,Markdown被大量使用,如Github、Wikipedia等网站,如各大博客平台:WordPress、Drupal、简书、掘金等。Markdown 基本语法在使用Typora之前首先你的先熟悉一下Markdown的基本语法,这样你用起Typora才能更加顺手、写起文章来更加快。Markdown 官方教程👉Docsify使用指南Docsify使用指南(打造最强、最轻量级的个人&团队文档)👉Typora快捷键的使用使用快捷键能够提高我们的开发,编辑效率,因此对于工具的快捷键灵活操作而言是十分重要的。新建: CTRL + N保存: CTRL + S另存为: CTRL + SHIFT + S段落:CTRL+0打开大纲视图:ctrl + shift + 1一级标题: CTRL + 1 这个是1级标题,最大的字号二级标题: CTRL + 2三级标题: CTRL + 3四级标题 : CTRL + 4五级标题 : CTRL + 5六级标题 : CTRL +6插入表格: CTRL + T插入引用: CTRL + SHIFT + Q有序列表: CTRL + SHIFT + [无序列表: CTRL + SHIFT + ]代码块: CTRL + SHIFT + K字体加粗: CTRL + B超链接: CTRL + K插入图片: CTRL + SHIFT + l显示/隐藏侧边栏: CTRL + SHIFT + L打开/关闭源代码模式: CTRL + /全文查找: CTRL + F全文替换: CTRL + H开发者工具: SHIFT + F12跳转到文首 CTRL + Home跳转到文末 CTRL + End设置打开Typora依旧打开上次编辑的文件和目录Typora-自动保存为了避免电脑意外关闭而导致辛苦编写的内容未保存丢失我们可以设置自动保存,避免电脑或者Typora意外关闭的情况。Typora配置图片保证在Docsify中能够正常访问一般情况下为了保证项目中的图片在不同的平台中都能够正常的访问到,我们通常都是使用相对路径去存储,因此在Typora中我们需要设置图片保存的路径为当前项目的指定文件夹下。在Typora中可以直接通过Ctrl+V将图片复制保存到指定的项目文件夹位置中,使用相对路径可访问!设置如下首先当前我们文件夹所处位置是在ProjectDocs文件夹目录里面,所以我们在ProjectDocs中新建images文件夹来存储文件图片。 文件=》偏好设置=》图像设置图片保存的相对路径将图片粘贴到Typora中查看效果

Docsify使用指南(打造最快捷、最轻量级的个人&团队文档)

前言  网上关于动态文档生成工具有很多如:Docsify、 VuePress、Docute 、Hexo这些都是一些非常优秀的文档生成工具,本章主要介绍如何快速使用Docsify搭建一个快捷、轻量级的个人&团队文档。什么是Docsify?  一个神奇的文档网站生成器。docsify 可以快速帮你生成文档网站。不同于 GitBook、Hexo 的地方是它不会生成静态的 .html 文件,所有转换工作都是在运行时。如果你想要开始使用它,只需要创建一个 index.html 就可以开始编写文档。Docsify的特性无需构建,写完文档直接发布容易使用并且轻量 (压缩后 ~21kB)智能的全文搜索提供多套主题丰富的 API支持 Emoji兼容 IE11支持服务端渲染 SSR (示例)轻量&完善的Docsify模板  该模板为一个简洁,并且完善的Docsify模板基本上可以满足百分之八十多的团队需求,你可以按照文章中的Docsify环境配置教程把运行Docsify所需要的环境配置起来,通过命令即可查看效果(配置环境顺利的话只要十来分钟)。模板源码地址:Docsify-Guide👉模板预览地址:https://ysgstudyhards.github.io/Docsify-Guide/#/👉Node.js 安装配置nodejs下载地址Node.js最新最详细安装教程win+r:cmd进入命令提示符窗口,分别输入以下命令查看node和npm的版本能够正常显示版本号,则安装成功:node -v:显示安装的nodejs版本npm -v:显示安装的npm版本docsify-cli工具安装推荐全局安装 docsify-cli 工具,可以方便地创建及在本地预览生成的文档。npm i docsify-cli -g项目初始化如果想在项目的 ./docs(文件名可以按自己的想法来) 目录里写文档,直接通过 init 初始化项目。docsify init ./Docsify-Guide初始化成功后,可以看到 ./docs 目录下创建的几个文件index.html 入口文件README.md 会做为主页内容渲染.nojekyll 用于阻止 GitHub Pages 忽略掉下划线开头的文件直接编辑 docs/README.md 就能更新文档内容,当然也可以添加更多页面。本地运行docsify创建的项目通过运行 docsify serve 项目名称 启动一个本地服务器,可以方便地实时预览效果。默认访问地址 http://localhost:3000 。docsify serve Docsify-Guide基础配置文件介绍其实我们维护一份轻量级的个人&团队文档我们只需要配置以下这几个基本文件就可以了。文件作用文件基础配置项(入口文件)index.html封面配置文件_coverpage.md侧边栏配置文件_sidebar.md导航栏配置文件_navbar.md主页内容渲染文件README.md浏览器图标favicon.ico基础配置项(index.html)下面是一份基础的配置项模板如下(可直接Copy使用)。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Docsify-Guide</title> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta name="description" content="Description"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <!-- 设置浏览器图标 --> <link rel="icon" href="/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <!-- 默认主题 --> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css"> </head> <body> <!-- 定义加载时候的动作 --> <div id="app">加载中...</div> <script> window.$docsify = { // 项目名称 name: 'Docsify-Guide', // 仓库地址,点击右上角的Github章鱼猫头像会跳转到此地址 repo: 'https://github.com/YSGStudyHards', // 侧边栏支持,默认加载的是项目根目录下的_sidebar.md文件 loadSidebar: true, // 导航栏支持,默认加载的是项目根目录下的_navbar.md文件 loadNavbar: true, // 封面支持,默认加载的是项目根目录下的_coverpage.md文件 coverpage: true, // 最大支持渲染的标题层级 maxLevel: 5, // 自定义侧边栏后默认不会再生成目录,设置生成目录的最大层级(建议配置为2-4) subMaxLevel: 4, // 小屏设备下合并导航栏到侧边栏 mergeNavbar: true, </script> <script> // 搜索配置(url:https://docsify.js.org/#/zh-cn/plugins?id=%e5%85%a8%e6%96%87%e6%90%9c%e7%b4%a2-search) window.$docsify = { search: { maxAge: 86400000,// 过期时间,单位毫秒,默认一天 paths: auto,// 注意:仅适用于 paths: 'auto' 模式 placeholder: '搜索', // 支持本地化 placeholder: { '/zh-cn/': '搜索', '/': 'Type to search' noData: '找不到结果', depth: 4, hideOtherSidebarContent: false, namespace: 'Docsify-Guide', </script> <!-- docsify的js依赖 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script> <!-- emoji表情支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script> <!-- 图片放大缩小支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script> <!-- 搜索功能支持 --> <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script> <!--在所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码--> <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script> </body> </html> 封面配置文件(_coverpage.md)Docsify官网封面配置教程index.html<!-- index.html --> <script> window.$docsify = { coverpage: true </script> <script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>_coverpage.md<!-- _coverpage.md --> # Docsify使用指南 > 💪Docsify使用指南,使用Typora+Docsify打造最强、最轻量级的个人&团队文档。 简单、轻便 (压缩后 ~21kB) - 无需生成 html 文件 - 众多主题 [开始使用 Let Go](/README.md)侧边栏配置文件(_sidebar.md)Docsify官网配置侧边栏教程index.html<!-- index.html --> <script> window.$docsify = { loadSidebar: true </script> <script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>在index.html基础配置文件中设置了二级目录_sidebar.md<!-- _sidebar.md --> * Typora+Docsify使用指南 * [Docsify使用指南](/ProjectDocs/Docsify使用指南.md) <!--注意这里是相对路径--> * [Typora+Docsify快速入门](/ProjectDocs/Typora+Docsify快速入门.md) * Docsify部署 * [Docsify部署教程](/ProjectDocs/Docsify部署教程.md)导航栏配置文件(_navbar.md)Docsify官网配置导航栏教程index.html<!-- index.html --> <script> window.$docsify = { loadNavbar: true </script> <script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>_navbar.md<!-- _navbar.md --> * 链接到我 * [博客园地址](https://www.cnblogs.com/Can-daydayup/) * [Github地址](https://github.com/YSGStudyHards) * [知乎地址](https://www.zhihu.com/people/ysgdaydayup) * [掘金地址](https://juejin.cn/user/2770425031690333/posts) * [Gitee地址](https://gitee.com/ysgdaydayup)

C#进程调用FFmpeg操作音视频

项目背景  因为公司需要对音视频做一些操作,比如说对系统用户的发音和背景视频进行合成,以及对多个音视频之间进行合成,还有就是在指定的源背景音频中按照对应的规则在视频的多少秒钟内插入一段客户发音等一些复杂的音视频操作。本篇文章主要讲解的是使用C#进程(Process)调用FFmpeg.exe进行视频合并,音频合并,音频与视频合并成视频这几个简单的音视频操作,还有些复杂的音视频操作后续有时间慢慢补上。FFmpeg介绍来源百度百科👉  FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。  FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac等多平台。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,而且当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。 FFmpeg编码库可以使用GPU加速。FFmpeg相关教程开始之初你首先要了解FFmpeg是什么,有哪些常用的命令和实用的功能。FFmpeg官网文档FFmpeg最全教程FFmpeg 视频处理入门教程FFMPEG命令入门到提高,一篇文章就够了博客示例源码https://github.com/YSGStudyHards/FFmpegAudioAndVideoMerge👉下载FFmpeg.exe安装包首先把下载下来的FFmpeg.exe放在你指定的目录文件夹中,方便C#进程调用。ffmpeg.exe 安装包: https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip👉 (74MB)C#进程调用FFmpeg操作音视频namespace FFmpegAudioAndVideoMerge class Program static void Main(string[] args) var physicalPath = "E:\\FFmpegAudioAndVideoMerge\\FFmpegAudioAndVideoMerge\\files\\"; //视频合并 VideoCombine(physicalPath + "video1.mp4", physicalPath + "video2.mp4", physicalPath + "merageVideoyy.mp4"); //音频合并 var audioMergeList = new List<string>(); audioMergeList.Add(physicalPath + "music1.mp3"); audioMergeList.Add(physicalPath + "music2.mp3"); audioMergeList.Add(physicalPath + "music3.mp3"); AudioMerge(physicalPath, audioMergeList); //音频与视频合并成视频 AudioAndVideoMerge(physicalPath); #region 视频合并 /// <summary> /// 视频合并 /// </summary> /// <param name="video1">合并视频1</param> /// <param name="video2">合并视频2</param> /// <param name="saveFilePath">保存文件名</param> /// <returns></returns> public static void VideoCombine(string video1, string video2, string saveFilePath) string strTmp1 = video1 + ".ts"; string strTmp2 = video2 + ".ts"; string strCmd1 = " -i " + video1 + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + strTmp1 + " -y "; string strCmd2 = " -i " + video2 + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + strTmp2 + " -y "; string videoMerge = " -i \"concat:" + strTmp1 + "|" + strTmp2 + "\" -c copy -bsf:a aac_adtstoasc -movflags +faststart " + saveFilePath + " -y "; //1、转换文件类型,由于不是所有类型的视频文件都支持直接合并,需要先转换格式 CommandManager(strCmd1); CommandManager(strCmd2); //2、视频合并 CommandManager(videoMerge); #endregion #region 音频合并 /// <summary> /// 音频合并 /// </summary> public static void AudioMerge(string physicalPath, List<string> mergeFile) //将多个音频混合成一个音频文件输出 http://www.ffmpeg.org/ffmpeg-all.html#amix //ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT //合并两个音频 //ffmpeg -i input1.mp3 -i input2.mp3 -filter_complex amerge -ac 2 - c:a libmp3lame -q:a 4 output.mp3 //获取视频中的音频 //ffmpeg -i input.mp4 -vn -y -acodec copy output.m4a //去掉视频中的音频 //ffmpeg -i input.mp4 -an output.mp4 // https://www.cnblogs.com/simadi/p/10649345.html // ffmpeg -i "concat:123.mp3|124.mp3" -acodec copy output.mp3 // 解释:-i代表输入参数 // contact: 123.mp3 | 124.mp3代表着需要连接到一起的音频文件 -acodec copy output.mp3 重新编码并复制到新文件中 string mergeCommandStr = $"-i \"concat:{string.Join("|", mergeFile.ToArray())}\" -acodec copy {physicalPath}AudioMerge.mp3 -y"; CommandManager(mergeCommandStr); #endregion #region 音频与视频合并成视频 /// <summary> /// 音频与视频合并成视频 /// </summary> /// <param name="physicalPath">物理路径</param> public static void AudioAndVideoMerge(string physicalPath) //1、视频文件中没有音频。 //ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental output.mp4 //string mergeCommandStr = $"-i {physicalPath}video2.mp4 -i {physicalPath}music1.mp3 -c:v copy -c:a aac -strict experimental {physicalPath}output.mp4 -y"; //video.mp4,audio.wav分别是要合并的视频和音频,output.mp4是合并后输出的音视频文件。 //2、下面的命令是用audio音频替换video中的音频 ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a: 0 output.mp4 string mergeCommandStr = $"-i {physicalPath}video3.mp4 -i {physicalPath}AudioMerge.mp3 -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a:0 {physicalPath}AudioAndVideoMerge.mp4 -y"; //3、c++音频视频合并(视频文件中没有音频的情况下) //"ffmpeg -i /tmp/mergeMp3/392118469203595327/392118469203595327.aac -i /tmp/mergeMp3/392118469203595327/bg.mp4 -c copy -bsf:a aac_adtstoasc /tmp/mergeMp3/392118469203595327/392118469203595327.mp4 -y" //string mergeCommandStr3 = $"-i {physicalPath}video5.mp4 -i {physicalPath}AudioMerge.mp3 -c copy -bsf:a aac_adtstoasc {physicalPath}AudioAndVideoMerge1.mp4 -y"; CommandManager(mergeCommandStr); #endregion /// <summary> /// 执行 /// C# Process进程调用 https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=net-5.0 /// </summary> /// <param name="commandStr">执行命令</param> public static void CommandManager(string commandStr) using (Process process = new Process()) process.StartInfo.FileName = "D:\\FFmpeg\\bin\\ffmpeg.exe";//要执行的程序名称(属性,获取或设置要启动的应用程序或文档。FileName 属性不需要表示可执行文件。 它可以是其扩展名已经与系统上安装的应用程序关联的任何文件类型。) process.StartInfo.Arguments = " " + commandStr;//启动该进程时传递的命令行参数 process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = false;//可能接受来自调用程序的输入信息 process.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息 process.StartInfo.RedirectStandardError = false;//重定向标准错误输出 process.StartInfo.CreateNoWindow = false;//不显示程序窗口 process.Start();//启动程序 process.WaitForExit();//等待程序执行完退出进程(避免进程占用文件或者是合成文件还未生成)* catch (Exception e) Console.WriteLine(e.Message);

GitHub git push超过100MB大文件失败(write error: Broken pipe)完美解决

问题  在使用git push推送大文件(超过了100MB)到GitHub远程仓库时提示异常,异常信息如下:fatal: sha1 file '<stdout>' write error: Broken pipefatal: the remote end hung up unexpectedly通过查阅了一些资料,我发现是因为GitHub对提交的文件大小做了限制,GitHub会阻止超过100 MB的推送(单文件),检查了一下我提交的文件中有一个超过200MB的文件。GitHub官方说明👉解决方案一1、将本地 http.postBuffer 数值调整到GitHub服务对应的单次上传大小配置注意:我这里设置的是500MB(大家可以根据自己的需要设置)。http.postBuffer默认单位为B(字节),所以500MB=1024*1024*500。# 方法一:全局配置 git config --global http.postBuffer 524288000 # 方法二:当前仓库配置 git config http.postBuffer 5242880002、查看 http.postBuffer数值是否设置成功# 查看当前的Git配置git config --list3、最后在重新使用git push推送代码到GitHub远程仓库中git push4、最后如果发现还是无法提交可以使用git命令撤回commit提交,找到超过100MB的文件进行删除#查询提交日志,获取提交head git log #撤销commit到指定的版本,本地修改的文件不会变动 git reset --soft 77e3f9eb02b96d7d2ea5def048fb4f1d07f19868找到你提交的文件中超过100MB的文件进行删除,然后重新添加,提交即可。 解决方案二安装 Git 大文件存储(Git LFS)什么是LFS?  Git LFS(Git Large File Storage),即Git大文件存储技术,相当于Git的一种插件式增强工具,简单讲,它是在Git仓库使用这些文件的 指针代替 实际文件,而把实际文件存储在远程端LFS服务器,同时在本地仓库中实时追踪这些文件的变动。1、下载Git Large File Storage(Git LFS)Git LFS Windows Installer2、在您的计算机上,找到下载的文件双击安装  双击名为git-lfs-windows-1.XXexe 的文件,其中 1.XX 替换为您下载的 Git LFS 版本。当你打开这个文件时,Windows 会运行一个安装向导来安装 Git LFS。3、打开Git Bash,验证安装是否成功$ git lfs install > Git LFS initialized.4、将您当前的工作目录更改为您希望与 Git LFS 一起使用的现有存储库5、要将存储库中的文件类型与 Git LFS 关联,请输入git lfs track后跟要自动上传到 Git LFS 的文件扩展名的名称例如,要关联.psd文件,请输入以下命令:$ git lfs track "*.psd" > Adding path *.psd您想与 Git LFS 关联的每种文件类型都需要添加git lfs track. 此命令修改存储库的.gitattributes文件并将大文件与 Git LFS 关联。提示:我们强烈建议您将本地.gitattributes文件提交到您的存储库中。依赖与 Git LFS 关联的全局.gitattributes文件可能会在为其他 Git 项目做出贡献时导致冲突。 6、将文件添加到与您关联的扩展名匹配的存储库$ git add path/to/file.psd7、提交文件并将其推送到 GitHub$ git commit -m "add file.psd" $ git push您应该会看到相关文件上传的进度信息:> Sending file.psd > 44.74 MB / 81.04 MB 55.21 % 14s > 64.74 MB / 81.04 MB 79.21 % 3s

Windows10 Docker安装详细教程

前言:  在上一章节已经成功的在Linux CentOS 8.4远程服务器中安装了Docker,下面让我们一起来试试如何在Windows10中安装Docker并运行起来。有人说你既然在Linxu环境中安装了Docker了,为什么还要到Windows环境中去折腾一个Dokcer环境呢?这不是在浪费时间内。那么那就大错特错了,在Windows环境中安装一个Dokcer是为了便于我们在自己的Windows开发环境中快速打搭建你所需要的开发运行的软件环境而准备的比如说有时候你本地需要在Windows10开发环境中快速搭建一个Ms SQLServer的运行环境,但是大家在Windows环境安装过的都知道Ms SQLServer安装快则半个到一个小时,忙的话就是两三个小时不等。但是你使用Docker的话,下载镜像到运行容器在到配置可能就是十多分钟的功夫吧。好了废话不对说,下面我们开始来配置Window10下的Docker环境吧。Docker Desktop是什么?  Docker Desktop是适用于Windows的Docker桌面,是Docker设计用于在Windows 10上运行。它是一个本地 Windows 应用程序,为构建、交付和运行dockerized应用程序提供易于使用的开发环境。Docker Desktop for Windows 使用 Windows 原生 Hyper-V 虚拟化和网络,是在 Windows 上开发 Docker 应用程序的最快、最可靠的方式。Windows 版 Docker 桌面支持运行 Linux 和 Windows Docker 容器。Dokcer Desktop下载:官方下载地址:Docker Desktop Installer.exe 下载地址国内镜像:Windows安装包下载地址 Windows 的 Docker 桌面说明:https://hub.docker.com/editions/community/docker-ce-desktop-windows启用Hyper-V以在 Windows 10上创建虚拟机:详情参考微软官方教程👉注意:可以通过多种方式启用 Hyper-V,包括使用 Windows 10 控制面板、PowerShell(Hyper-V 作为可选功能内置于 Windows -- 无需下载 Hyper-V)。1、使用 PowerShell 启用 Hyper-V以管理员身份打开 PowerShell 控制台,运行以下命令:Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All2、通过控制面板“设置”启用 Hyper-V 角色右键单击 Windows 按钮并选择“应用和功能”。选择相关设置下右侧的“程序和功能”。选择“打开或关闭 Windows 功能”。选择“Hyper-V”,然后单击“确定”。注意:安装完成后,系统会提示你重新启动计算机。 安装Docker Desktop:双击下载成功的Docker Desktop Installer.exe应用。 安装成功,关机重启!!  重启成功: 配置阿里云镜像加速地址: 阿里云容器镜像服务 ACR👉进入管理控制台获取镜像加速器地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors👉在Docker Desktop设置中配置阿里云镜像源:在系统右下角托盘图标内右键菜单选择 Settings,打开配置窗口后左侧导航菜单选择 Docker Desktop。编辑窗口内的JSON串,填写下方加速器地址:{ "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"] }Windows PowerShell查看Docker版本docker version验证Docker桌面版 可以正常使用:打开命令行窗口运行以下命令:docker run hello-world 看到以下输出则表示安装成功,且能正常工作: 查看Docker Desktop中是否存在hello-world镜像是否拉取成功:hello-world镜像地址:https://hub.docker.com/_/hello-world👉通过启用WSL2安装Docker:注意:通过启用Hyper-v虚拟化的方式在windows中安装Dokcer以外,我们还可以通过安装配置WSL2环境来安装。  WSL2 是 Windows Subsystem for Linux 二代的简称,WSL2允许用户在Windows上运行受支持的Linux发行版。当前的Docker桌面版可以使用WSL2作为其Linux后台运行。因此我们需要首先在Windows操作系统上激活WSL2功能才能使用Docker做面板。

CentOS 8.4安装Docker

前言:  Docker 是一个用于开发、传送和运行应用程序的开放平台。Docker 使您能够将应用程序与基础设施分开,以便您可以快速交付软件。使用 Docker,您可以像管理应用程序一样管理基础设施。通过利用 Docker 的快速交付、测试和部署代码的方法,您可以显着减少编写代码和在生产中运行代码之间的延迟。为了让开发、部署、测试和分发变得更高效和轻松,让我们把Docker安装起来体验一下它的魅力所在吧!系统要求:Docker 支持 64 位版本 CentOS 7/8,并且要求内核版本不低于 3.10。需要启用centos-extras repository。在 CentOS 7 中这个仓库是默认启用的,如果之前有将其禁用,则需要重新启用CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存储层驱动)无法使用,并且部分功能可能不太稳定。安装环境:  本文主要是在Liunx操作系统CentOS8.4中安装Docker,我们安装之前可以先查看自己的系统版本,使用命令:lsb_release -a 进行查看(如下图所示)。注意:切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker.、卸载旧版本:旧版本的Docker在CentOS中的包名为docker或者docker-engine。如果你之前的Linux CentOS系统中安装了Docker的旧版本,你需要先卸载旧版Docker及其相关依赖,执行以下命令sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine因为我的系统系刚安装的,所以执行上面的命令提示的是没有找到需要移除的包!如果yum报告没有安装这些软件包,那也没关系。注意:/var/lib/docker/目录下的内容,包括镜像、容器、卷组、网络等文件将被保留。Docker CE 的新包名为docker-ce。🚀回到顶部yum到底是干什么的?简单描述:yum称为包管理器,主要用来解决:下载、依赖关系、安装、卸载四种问题。详细说明:https://blog.csdn.net/weixin_43202123/article/details/119948927🚀回到顶部使用yum安装:执行以下命令安装依赖包和必要的一些系统工具:sudo yum install -y yum-utils device-mapper-persistent-data lvm2配置yum稳定镜像源:因为国内网络原因,推荐使用阿里云提供的Docker CE 镜像源站!sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo官方镜像源地址:# 官方源 # sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo安装 Docker更新 yum 软件源缓存,并安装 docker-ce(一路yes即可)。sudo yum install docker-ce docker-ce-cli containerd.io如下是成功安装的依赖:  查看安装成功的docker版本:docker -vCentOS8 额外设置由于 CentOS8 防火墙使用了 nftables,但 Docker 尚未支持 nftables。首先我们查看防火墙的状态,假如防火墙状态是开启的我们执行下面的操作:systemctl status firewalld我们可以使用如下设置使用 iptables:更改 /etc/firewalld/firewalld.conf# FirewallBackend=nftables FirewallBackend=iptables或者执行以下命令:firewall-cmd --permanent --zone=trusted --add-interface=docker0 firewall-cmd --reload开启Docker服务: 执行sudo service docker start 命令开启Docker服务提示异常:Redirecting to /bin/systemctl start docker.service 看异常就是需要执行systemctl的相关命令,因为Linux的不同发行版开启Docker服务的命令也有所不同sudo systemctl enable docker sudo systemctl start docker最后查看docker运行状态systemctl status docker启动 Docker 守护进程:官方教程:https://docs.docker.com/config/daemon/systemd/手动启动安装 Docker 后,您需要启动 Docker 守护程序。大多数 Linux 发行版用于systemctl启动服务。sudo systemctl start docker在系统启动时自动启动如果您希望 Docker 在启动时启动,请参阅 配置 Docker 以在启动时启动👉。Docker基础命令:启动docker:systemctl start docker停止docker:systemctl stop docker重启docker:systemctl restart docker查看docker状态:systemctl status docker开机启动:systemctl enable docker当前系统docker信息:docker info列举出所有的容器:docker ps -a停止容器:docker start 容器ID或容器名直接关闭容器:docker kill 容器ID或容器名重启容器:docker restart 容器ID或者容器名删除容器:docker rm 容器ID或者容器名查看镜像:docker image ls更多命令搜索(推荐):Docker命令在线速查手册测试 Docker 是否安装正确首先我们输入docker run hello-world是否会出现下图所示的提示,如果出现报错,这环境配置可能出现了问题。注意:这行命令会让Docker从官方仓库中拉去hello-world的镜像到本地(是本地不存在该镜像的情况),并且将其自动实例化容器。Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:37a0b92b08d4919615c3ee023f7ddb068d12b8387475d64c622ac30f45c29c51 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/查看hello-World镜像和容器:

全面的Docker快速入门教程

前言:  都2021年了,你还在为了安装一个开发或者部署环境、软件而花费半天的时间吗?你还在解决开发环境能够正常访问,而发布测试环境无法正常访问的问题吗?你还在为持续集成和持续交付(CI / CD)工作流程苦恼吗?那还在犹豫是什么,Docker能够完美的解决你遇到这所有的问题。Docker是什么?  Docker 是一个开源的应用容器引擎,基于 Golang 语言开发,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 服务器。容器是一个沙箱机制,相互之间不会有影响(类似于我们手机上运行的 app),并且容器开销是很低的。  Docker 是一个供开发人员和系统管理员构建、运行和与容器共享应用程序的平台。使用容器部署应用程序称为容器化。容器并不是新事物,但它们用于轻松部署应用程序却是新鲜的。注意:Docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。Docker的优势有哪些?灵活性:即使是最复杂的应用程序也可以容器化。轻量级:容器利用并共享主机内核,使它们在系统资源方面比虚拟机更有效率。可移植:您可以在本地构建,部署到云上,并在任何地方运行。松耦合:容器是高度自给自足和封装的,允许您在不影响其他容器的情况下替换或升级其中一个。可扩展:您可以跨数据中心增加和自动分发容器副本。安全性:容器对进程应用主动约束和隔离,而不需要用户进行任何配置。Docker的作用?  Docker 是一个用于开发、传送和运行应用程序的开放平台。Docker 使您能够将应用程序与基础设施分开,以便您可以快速交付软件。使用 Docker,您可以像管理应用程序一样管理基础设施。通过利用 Docker 的快速交付、测试和部署代码的方法,您可以显着减少编写代码和在生产中运行代码之间的延迟。Docker(opens new window)是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的维护效率,降低了云计算应用开发的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!无论是应用开发者、运维人员、还是其他信息技术从业人员,都有必要认识和掌握 Docker,节约有限的生命。Docker主要用来解决什么问题?Docker的出现主要就是为了解决:在我的机器上运行时是正常的,但为什么到你的机器上就运行不正常了。  比如你写一个Web应用,并且本地调试没有任何问题。这时候你想发给你的朋友试试看或者发布部署到远程的云服务器上查看效果,那么首先你需要配置和你本地相同的软件环境,如数据库,Web服务器(IIS,Tomcat,Nginx),必要的插件,库等等。而这你还不能保证的你的软件一定能够运行起来,因为别人可能用完全不同的操作系统,即便是使用Linux每种发行版也会有微小的区别。为了模拟完全相同的本地开发环境。我们首先想到的就是虚拟机,但是虚拟机需要模拟硬件,运行整个操作系统不但体积臃肿内存占用高,程序的性能也会受到影响。如下图是比较常用的虚拟机:Docker的脱颖而出:  这时候Dokcer就派上了用场,Docker在概念上与虚拟机非常类似。但是Docker更轻量,它不会去模拟底层的硬件 ,只会为每一个应用提供完全隔离的运行环境。你可以在容器中配置不同的应用环境,并且不用的环境之间互相不影响,这个“环境”在Docker中也被称作为Container(容器)。Docker和虚拟机技术的区别?  Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker技术比虚拟机技术更为轻便、快捷。下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。 如果想详细了解,可以参考文章:docker与虚拟机的区别👉Docker容器和虚拟机的区别总结:特性docker容器虚拟机启动秒级分钟级硬盘使用一般为MB一般为GB性能接近原生(宿主机)弱于原生系统支持量单机支持上千个容器一般几十个 Docker中的三个重要概念Docker中的三个重要概念分别是:Image(镜像),Container(容器),Repository(仓储)。Image(镜像)一个特殊的文件系统你可以把它理解成一个虚拟机的快照(Snapshot),里面包含了你要部署的应用程序以及它所关联的所有库。  操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。 Container(容器)镜像运行时的实体这里的容器就像是一台台运行起来的虚拟机,里面运行了你的应用程序,每个容器是独立运行的他们相互之间不影响。通过一个镜像,我们可以创建许多个不同的Container容器。  镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和类的实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。 Repository(仓储)集中存放镜像文件的地方  镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务(就像Git仓库一样),Docker Registry就是这样的服务。  一个Docker Registry中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。所以说:镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。Docker 架构及工作原理  Docker使用客户端-服务器架构。Docker 客户端与 Docker 守护进程通信,后者负责构建、运行和分发Docker容器等繁重的工作。Docker 客户端和守护进程可以运行在同一个系统上,或者您可以将一个 Docker 客户端连接到一个远程 Docker 守护进程。Docker 客户端和守护进程通过 UNIX 套接字或网络接口使用 REST API 进行通信。Docker 架构及工作原理详情介绍👉Dockerfile(自动化脚本)主要是用来创建我们之间讲到的镜像,这个过程就好比我们在虚拟机中安装操作系统和软件一样,只不过是通过Dockerfile这个自动化脚本完成的。Dockerfile详解教程文章:Dockerfile制作自己的镜像文件👉Docker管理工具Portainer(推荐)  介绍:Portainer是一个开源的、轻量级的Docker环境管理UI(是Web应用的形式),可以用来管理Docker宿主机和docker swarm集群。Github 上项目地址:https://github.com/portainer/portainer官网地址:https://www.portainer.io支持的系统:Linux, Mac OS X, Windows。功能特性:管理仓库、网络、数据卷、密钥、镜像、容器管理你的配置,例如告警、监控支持容器的健康检查容器的启动、停止、恢复、删除检查容器、查看容器日志、可视化状态查看进入容器控制台可以添加扩展有一套 RBAC 基于角色的权限控制系统DockStation 介绍:DockStation是一个免费的、以开发人员为中心的用于管理基于 Docker的桌面应用程序。您可以仅使用 GUI 来监控、配置和管理服务和容器,而不是大量的 CLI 命令。官网地址:https://dockstation.io/Github地址:https://github.com/DockStation/dockstation支持的系统:Linux, Mac, Windows功能特性:可以非常方便的操作 Docker 和 DockerCompose。可以帮助我们管理容器、Service服务(本地远程都可以),并监控他们可以轻松跟踪 CPU、内存、网络、磁盘I/O、开放端口可以把常用的操作组织成一个项目,通过项目的方式来检查容器状态,以图形化的方式管理。Docker Desktop介绍:Docker Desktop 是一款易于安装的应用程序,使您能够构建和共享容器化应用程序和微服务。官网地址:https://www.docker.com/products/docker-desktop支持的系统:Mac, Windows功能特性:能够以多种语言和框架在任何云平台上容器化和共享任何应用程序轻松安装和设置完整的 Docker 开发环境包括最新版本的 Kubernetes自动更新,让您保持最新状态和安全在 Windows 上,能够在 Linux 和 Windows Server 环境之间切换以构建应用程序使用本机 Windows Hyper-V 虚拟化实现快速可靠的性能能够通过 Windows 机器上的 WSL 2 在 Linux 上本地工作代码和数据的卷安装,包括文件更改通知和轻松访问本地主机网络上运行的容器使用支持的 IDE 进行容器内开发和调试

微信h5跳转小程序wx-open-launch-weapp开放标签不显示(已解决)

前言:   前几天成功对接了跳转第三方小程序的功能,今天有个页面有需要对接。但是奇怪的是用的和上次一模一样的配置,但就是死活不显示wx-open-launch-weapp这个开放标签的按钮,看不到任何效果(这个问题真的是让人欲哭无泪,相同的代码不同的页面就不显示了),下面就说说我的排查解决过程。开启wx.config的debug模式:首先我们在wx.config的配置中开启debug。wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印 appId: 'ccccxxxx4354353453', // 必填,公众号的唯一标识 timestamp: 0123456, // 必填,生成签名的时间戳 nonceStr: 'nonceStr', // 必填,填任意非空字符串即可 signature: 'signature', // 必填,填任意非空字符串即可 jsApiList: ['showOptionMenu', 'chooseImage', 'previewImage'], // 必填,随意一个接口即可 openTagList: ['wx-open-launch-weapp'], // 填入打开小程序的开放标签名 })然后把修改的代码发布到服务其中,在手机上看出调试效果(注意只能够在真机上才看到效果,浏览器和微信开发工具中都看不到效果)输出结果为:"errMsg":"config:ok"这就奇怪了,这里提示配置成功也就说明了,签名什么的都是生成成功了的。排除签名生成错误和后端参数传递异常问题。使用微信开发工具查看wx.config是否获取到OpenTag查看之前的一个配置成功的页面微信开发工具控制台输出是:获取到了wx-open-launch-weapp的开发标签权限而我新加的这个页面是没有获取到开发标签的权限的,如下图所示:分析解决问题  到这里我们基本上可以看出来是没有获取到微信开放标签(OpenTag)的权限,而开放标签也是jweixin-1.6.0.js开始支持,于是我到浏览器页面查看了js的加载资源,果然发现了问题所在,原来在之前的母版页中有一个jweixin-1.3.0.js的SDK先加载了,所以导致了这个开发标签获取不到的问题,于是我将jweixin-1.3.0.js替换成jweixin-1.6.0.js就成功了!!invalid signature签名错误排查:假如你遇到签名错误的情况,建议你按照以下顺序进行排查。确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。确保一定缓存access_token和jsapi_ticket。确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

微信公众号开发之H5页面跳转到指定的小程序

前言:  最近公司有一个这样的需要,需要从我们在现有的公众号H5页面中加一个跳转到第三方小程序的按钮。之前只知道小程序之间是可以相互跳转的,今天查阅了下微信开发文档原来现在H5网页也支持小程序之间的跳转了,下面就简单描述一下对接的流程。微信公众号详细对接文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html#21公众号关联小程序:注意:在对接跳转之前我们需要在需要跳转的小程序关联到我们的公众号中。公众号可以关联同一主体的小程序10个,不同主体的3个。1、进入公众号后台,路径:广告与服务——小程序—小程序管理—添加2、关联小程序—管理员微信扫码确认3、搜索小程序名称或APPID绑定4、绑定成功等待小程序管理者同意🚀回到顶部查看小程序原始id:小程序原始id,即小程序对应的以gh_开头的id找到关联成功的小程序,鼠标放入其中找到详情查看小程序原始id🚀回到顶部绑定JS接口安全域名:登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。微信JS-SDK的使用步骤,配置信息生成详细说明(.NET版):https://www.cnblogs.com/Can-daydayup/p/11124092.html跳转标签、前提条件和属性说明:跳转小程序:wx-open-launch-weapp用于页面中提供一个可跳转指定小程序的按钮。使用此标签后,用户需在网页内点击标签按钮方可跳转小程序。H5通过开放标签打开小程序的场景值为1167。开放对象已认证的服务号,服务号绑定“JS接口安全域名”下的网页可使用此标签跳转任意合法合规的小程序。已认证的非个人主体的小程序,使用小程序云开发的静态网站托管绑定的域名下的网页,可以使用此标签跳转任意合法合规的小程序。错误提示若跳转时出现以下页面,表示网页绑定的服务号或小程序无权限,请检查是否符合上述开放对象条件。属性名称必填默认值备注username是 所需跳转的小程序原始id,即小程序对应的以gh_开头的idpath否 所需跳转的小程序内页面路径及参数(不填写的话默认跳转小程序首页)代码实现:注意:使用浏览器或者微信开发工具调试wx-open-launch-weapp开发标签都不会显示,只有在真机中才会有效果(前提还是config接口注入权限验证配置通过)。<html> <head> <title>H5打开小程序</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1"> </head> <body> <wx-open-launch-weapp id="launch-btn" username="gh_xxxxxxxx" path="pages/home/index?user=123&action=abc"> <script type="text/wxtag-template"> <style>.btn { padding: 12px }</style> <button class="btn">打开小程序</button> </script> </wx-open-launch-weapp> <!-- 公众号 JSSDK --> <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> <!--js代码--> <script type="text/javascript"> var btn = document.getElementById('launch-btn'); btn.addEventListener('launch', function (e) { console.log('success'); btn.addEventListener('error', function (e) { console.log('fail', e.detail); wx.ready(function () { var ua = navigator.userAgent.toLowerCase() var isWXWork = ua.match(/wxwork/i) == 'wxwork' var isWeixin = !isWXWork && ua.match(/micromessenger/i) == 'micromessenger' if (isWeixin) { wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印 appId: 'ccccxxxx4354353453', // 必填,公众号的唯一标识 timestamp: 0123456, // 必填,生成签名的时间戳 nonceStr: 'nonceStr', // 必填,填任意非空字符串即可 signature: 'signature', // 必填,填任意非空字符串即可 jsApiList: ['showOptionMenu', 'chooseImage', 'previewImage'], // 必填,随意一个接口即可 openTagList: ['wx-open-launch-weapp'], // 填入打开小程序的开放标签名 else { alert("请在微信中打开"); </script> </body> </html>实现效果:

WCF服务调用超时错误:套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的。本地套接字超时是“00:05:30”(已解决)

问题:  线上正式环境调用WCF服务正常,但是每次使用本地测试环境调用WCF服务时长就是出现:套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的。本地套接字超时是“00:05:30” 这个问题,查阅了网上很多资料各种说法的都有,有的说是什么请求站点不在同一个域下,有的说什么应为datatable中有一个属性没有赋值各种答非所问的问题。其实从错误信息中就可以看出来其实就是调用超时了。解决方案:在调用wcf的服务端的web.config中配置netTcpBinding这个配置,将receiveTimeout完成接收操作提供的时间间隔设置为:00:05:30即可解决(或者使用默认配置:00:10:00,不配置即可)。这是我在我的服务端配置的相关参数(仅供大家参考),大家可以根据自己的需求配置:<netTcpBinding> <!--binding:此元素包含标准绑定和自定义绑定的集合--> <binding portSharingEnabled="true" receiveTimeout="00:05:30" openTimeout="00:01:00" sendTimeout="00:01:00"> <!--定义绑定的安全设置,mode="None"禁用安全性--> <security mode="None"/> <!--定义可由采用此绑定配置的终结点进行处理的 SOAP 消息的复杂性约束--> <readerQuotas maxDepth="32" maxStringContentLength="65536000" maxArrayLength="65536000" maxBytesPerRead="4096" maxNameTableCharCount="16384"/> </binding> </netTcpBinding>netTcpBinding配置说明官方详细说明☞security 的 netTcpBinding☞特性和元素下列各节描述了特性、子元素和父元素。特性特性特性说明closeTimeout一个 TimeSpan 值,指定为完成关闭操作提供的时间间隔。 此值应大于或等于 Zero。 默认值为 00:01:00。hostNameComparisonMode指定用于分析 URI 的 HTTP 主机名比较模式。 此属性的类型为 HostNameComparisonMode,指示在对 URI 进行匹配时,是否使用主机名来访问服务。 默认值为 StrongWildcard,表示忽略匹配项中的主机名。listenBacklog一个正整数,指定侦听器上等待接受的最大通道数。 超出此限制的连接会被排队,直到连接数低于限制值。 connectionTimeout 属性限制客户端在引发连接异常之前将等待连接的时间。 默认值为 10。maxBufferPoolSize一个整数,指定此绑定的最大缓冲池大小。 默认值为 512 * 1024 字节。 Windows Communication Foundation (WCF) 的许多部件使用缓冲区。 每次使用缓冲区时,创建和销毁它们都将占用大量资源,而缓冲区的垃圾回收过程也是如此。 利用缓冲池,可以从缓冲池中获得缓冲区,使用缓冲区,然后在完成工作后将其返回给缓冲池。 这样就避免了创建和销毁缓冲区的系统开销。maxBufferSize一个正整数,指定内存中用于存储消息的缓冲区的最大大小(字节)。如果 transferMode 属性等于 Buffered,则此属性应等于 maxReceivedMessageSize 属性值。如果 transferMode 属性等于 Streamed,则此属性不能大于 maxReceivedMessageSize 属性值,应当至少为标头的大小。默认值为 65536。 有关详细信息,请参阅 MaxBufferSize。maxConnections一个整数,指定服务将创建/接受的最大出站和入站连接数。 传入和传出连接分别根据此属性指定的限制进行计数。超出此限制的入站连接需要排队,直到连接数低于限制值。超出此限制的出站连接需要排队,直到连接数低于限制值。默认值为 10。maxReceivedMessageSize一个正整数,指定采用此绑定配置的通道上可以接收的最大消息大小(字节),包括消息头。 如果消息超出此限制,则发送方将收到 SOAP 错误。 接收方将删除该消息,并在跟踪日志中创建事件项。 默认值为 65536。name一个包含绑定的配置名称的字符串。 因为此值用作绑定的标识,所以它应该是唯一的。 从 .NET Framework 4 开始,绑定和行为不需要具有名称。 有关默认配置和无值绑定和行为的详细信息,请参阅WCF 服务的简化配置和简化配置。openTimeout一个 TimeSpan 值,指定为完成打开操作提供的时间间隔。 此值应大于或等于 Zero。 默认值为 00:01:00。portSharingEnabled一个布尔值,指定是否为此连接启用 TCP 端口共享。 如果此值为 false,则每个绑定都使用自己的独占端口。 此设置只与服务相关,因为客户端不受影响。receiveTimeout一个 TimeSpan 值,指定为完成接收操作提供的时间间隔。 此值应大于或等于 Zero。 默认值为 00:10:00。sendTimeout一个 TimeSpan 值,指定为完成发送操作提供的时间间隔。 此值应大于或等于 Zero。 默认值为 00:01:00。transactionFlow一个布尔值,指定绑定是否支持流动 WS-Transactions。 默认为 false。transactionProtocol指定与此绑定一起使用的事务处理协议。 有效值为-OleTransactions-WSAtomicTransactionOctober2004默认值为 OleTransactions。 此属性的类型为 TransactionProtocol。transferMode一个 TransferMode 值,指定为请求或响应对消息进行缓冲处理还是流式处理。子元素子元素元素说明<security>定义绑定的安全设置。 此元素的类型为 NetTcpSecurityElement。<readerQuotas>定义可由采用此绑定配置的终结点进行处理的 SOAP 消息的复杂性约束。 此元素的类型为 XmlDictionaryReaderQuotasElement。<reliableSession>指定是否在通道终结点之间建立可靠会话。父元素父元素元素说明<bindings>此元素包含标准绑定和自定义绑定的集合。

.NET Web应用配置本地IIS(实现Visual Studio离线运行与调试

前言:  因为项目程序需要频繁的修改,然后每次修改以后都要重新编译才能查看到修改的效果。而且有时候前端也需要及时的对接我们的接口,导致每次修改一点东西都要发布一次,这样子对于开发者而言是十分的浪费时间,工作效率也十分的低下。所以我们把.NET应用配置本地IIS,实现程序能够直接托管IIS并且运行程序可以调试。 安装IIS托管服务器前提:Windows10 IIS Web服务器安装配置在IIS中添加本地项目的站点 打开Internet Information Services (IIS)管理器=>添加网站=>配置本地项目站点项目配置本地IIS运行:配置完成后,我们可以不需要运行Visual Studio中的项目可以直接浏览IIS中站点即可查看页面或者api效果,假如需要调试的话可以运行Visual Studio中的项目直接调试既可以。

Windows10 IIS Web服务器安装配置

前言:  对于.NET开发者而已,IIS Web托管服务器应该是十分的熟悉的。对于刚安装Windows10的系统的用户而已Internet Information Services(IIS)功能是默认关闭的需要我们自己手动去开启,本篇博客主要介绍的是如何开启IIS功能,并托管.NET Core项目。IIS介绍:  Internet Information Services (IIS) 是一种灵活、安全且可管理的 Web 服务器,用于托管 Web 应用(包括 ASP.NET Core)。IIS受支持的平台:支持下列操作系统:Windows 7 或更高版本Windows Server 2012 R2 或更高版本支持针对 32 位 (x86) 或 64 位 (x64) 部署发布的应用。 使用 32 位 (x86) .NET Core SDK 部署 32 位应用,除非应用符合以下情况:需要适用于 64 位应用的更大虚拟内存地址空间。需要更大 IIS 堆栈大小。具有 64 位本机依赖项IIS配置并安装:1、打开控制面板=>程序=>启动或关闭Windows功能 2、选择Internet Information Services安装IIS 注意:无需选中"设置"下的所有Internet Information Services, 按照自己的需要选择安装即可。 第一次安装可能时间会比较的久,耐心等待一会。3、验证IIS是否安装配置成功找到windows管理工具=>打开IIS运行IIS默认的Default Web Site查看是否正常在C:\inetpub\wwwroot下IIS默认绑定了一个80端口的静态页面站点,我们将该站点浏览起来查看页面效果是否正常。站点地址:http://localhost:80

uni-app跨平台框架介绍和快速入门

前言:  首先今天主要介绍的是一个多平台的前端框架uni-app,关于多平台的前端框架网上有很多成熟的解决方案比如说Taro,React Native,Flutter等这些都是一些非常优秀的前端跨平台的框架(大家想要了解更多可以上网查询各种框架的优缺点,温馨提示:没有最好的框架,选择适合自己或者自己团队的才是最好的框架)。为什么选择uni-app?  首先uni-app是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/快手/钉钉/淘宝)、快应用等多个平台。  现如今Vue已经成为了一个前端的主流框架之一的快速开发框架,从招人人才贮备以及项目的开发效率我们选择使用uni-app这个跨平台框架。并且uni-app现已经支持11个平台,也就是说我们使用uni-app写一个应用程序,可以编译生成11个平台的应用,对于不同产品或者客户所需来说这简直是完美。  并且uni-app在开发者数量、案例、跨端广度、扩展灵活性、性能体验、周边生态、学习成本、开发成本等8大关键指标上拥有更强的优势。   对于不善于前端或者公司缺少前端的个人或者公司而言,uni-app绝对是不二之选,因为uni-app周边的生态非常丰富在插件市场中基本上可以搜索到符合大多数人所需要的插件模板。如商城,博客,小程序等等。 新手如何快速开始?   假如你是一个前端没有任何经验的开发者,首先建议先大概了解一下vue的相关知识点(比如说vue的基本语法,什么是双向绑定,条件判断,怎么数据请求绑定等常用的方法),然后开发uni-app应用时把uni-app的相关api文档了解一下(当然也可以边做编程相关的语法,实战开发起来能让我们更快的熟悉)。uni-app的api文档:https://uniapp.dcloud.io/api/README  开发之前可以先看一下uni-app官方出门的视频教程: 《uni-app官方教程》  通过快速上手👉,亲身体验下uni-app,开始之前,开发者需先下载安装如下工具:可视化的方式比较简单,HBuilderX内置相关环境,开箱即用,无需配置nodejs。HBuilderX:官方IDE下载地址部快速开发你的第一个Android应用1、打开HBuilderX=>文件=>新建项目=>uni-app项目类型注意这里我使用的是uni-app演示用的框架组件,主要是为了展示生成的Android的应用效果。2、在浏览器运行查看我们新建项目MyFirstApp的web页面效果点击工具栏的运行 => 运行到浏览器 => 选择浏览器3、发布原生App(云打包)点击工具栏的发布=>原生App(云打包) 输入Dcloud的后台登录邮箱和密码(没有的话需要先注册)在manifest.json中获取应用标识(AppId)配置App打包所需要的相关信息等待编译打包(可能花费的时间有点长请耐心等待) 打包完成打开生成apk的目录查看并将其安装到Android手机上查看效果

Visual Studio 2022 Preview设置简体中文

前言:  作为尝鲜小分队队长,对于vs的升级版Visual Studio 2022 Preview肯定也开始用上了,不过之前一直以为还没有出中文的语言包所以一直用的是英文版的,搞得英文本来不好的我很是不习惯,后面才知道原来自己是忘记了下载简体中文包。下面我来简单介绍一下怎么重新下载中文包。一、找到Visual Studio Installer二、在Vs Installer中找到VS 2022 Preview点击修改 三、选择语言包中的中文(简体)点击修改四、打开VS设置语言包Tools=>Options=>Environment=>International Settings=>language 部 五、重启VS,查看效果

.NET企业微信回调配置(数据回调URL和指令回调URL验证)(一)

前言:  前段时间因为公司业务需求,需要将微信小程序与企业微信对接通,也就是把小程序绑定到对应的企业微信账号下,在该企业微信的用户可以将该小程序绑定到工作台中,然后可以在工作台中打开该小程序并授权。不过将微信小程序与企业微信对接通需要后台去做数据回调URL和指令回调URL验证,因为第一次接触这个然后企业微信文档写的也不是很详细,并且在全网没有找到一篇.NET相关企业微信回调配置验证有用的文章,所以这里把自己的配置详细过程分享出来,希望能够帮助更多的同学。企业微信回调配置相关文档回调配置:主要讲的是回调配置的一些验证流程和请求接口。https://work.weixin.qq.com/api/doc/90000/90135/90930C#解密类库:https://open.work.weixin.qq.com/wwopen/downloadfile/csharp.zip.NET6完整示例代码别忘了给我个Star哦!!!YyFlight.WeChat部企业微信回调配置验证完整流程注意:配置回调服务时,需要能同时支持HttpGet以及HttpPost两种能力,注意接口一定要是https的安全域名地址。HttpGet接口用于验证数据回调URL有效性HttpPost接口用于验证指令回调URL有效性所以我们可以只定义一个接口,通过企业微信请求过来的类型进行不同回调URL的有效性验证。处理企业号的信息接口:public class EnterpriseWechatCallbackController : Controller //企业微信后台开发者设置的token, corpID, EncodingAESKey private readonly string sToken = "追逐时光者";//企业微信后台,开发者设置的Token private readonly string sCorpID = "追逐时光者";//企业号corpid是企业号的专属编号(CorpID)[不同场景含义不同,详见文档说明(ToUserName:企业微信的CorpID,当为第三方应用回调事件时,CorpID的内容为suiteid)] private readonly string sEncodingAESKey = "追逐时光者";//企业微信后台,开发者设置的EncodingAESKey /// <summary> /// 处理企业号的信息 /// get:数据回调URL验证; /// post:指令回调URL验证; /// </summary> public ActionResult EtWechatCommunication() string httpMethod = Request.HttpMethod.ToUpper(); if (httpMethod == "POST") //获取请求中的xml数据 string postString = GetXMLParameters(Request); string responseContent = "响应失败,未获取到xml中的请求参数"; if (!string.IsNullOrEmpty(postString)) //指令响应回调 responseContent = CommandCallback(Request, postString); return Content(responseContent); return EtWachatCheckVerifyURL(); /// <summary> /// 数据回调URL验证 /// </summary> /// <returns></returns> public ActionResult EtWachatCheckVerifyURL() string signature = Request.QueryString["msg_signature"];//微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体 string timestamp = Request.QueryString["timestamp"];//时间戳 string nonce = Request.QueryString["nonce"];//随机数 string httpMethod = Request.HttpMethod.ToUpper(); if (httpMethod == "GET")//验证回调URL(注意:企业回调的url-该url不做任何的业务逻辑,仅仅微信查看是否可以调通) //在1秒内响应GET请求,响应内容为上一步得到的明文消息内容decryptEchoString(不能加引号,不能带bom头,不能带换行符) string echostr = Request.QueryString["echostr"];//加密的随机字符串,以msg_encrypt格式提供。需要解密并返回echostr明文,解密后有random、msg_len、msg、$CorpID四个字段,其中msg即为echostr明文 if (!IsNullOrWhiteSpace(signature) && !IsNullOrWhiteSpace(timestamp) && !IsNullOrWhiteSpace(nonce) && !IsNullOrWhiteSpace(echostr)) string decryptEchoString = null; if (CheckVerifyURL(sToken, signature, timestamp, nonce, sCorpID, sEncodingAESKey, echostr, ref decryptEchoString)) if (!string.IsNullOrEmpty(decryptEchoString)) //必须要返回解密之后的明文 return Content(decryptEchoString); return Content("fail"); catch (Exception ex) return Content("fail"); return Content("fail"); /// <summary> /// 验证URL有效性 /// </summary> /// <param name="token">企业微信后台,开发者设置的Token</param> /// <param name="signature">签名串,对应URL参数的msg_signature</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机数</param> /// <param name="corpId">ToUserName为企业号的CorpID</param> /// <param name="encodingAESKey">企业微信后台,开发者设置的EncodingAESKey</param> /// <param name="echostr">随机串,对应URL参数的echostr</param> /// <param name="retEchostr">解密之后的echostr,当return返回0时有效</param> /// <returns></returns> private bool CheckVerifyURL(string token, string signature, string timestamp, string nonce, string corpId, string encodingAESKey, string echostr, ref string retEchostr) WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId); int result = wxcpt.VerifyURL(signature, timestamp, nonce, echostr, ref retEchostr); if (result != 0) return false;//FAIL //result==0表示验证成功、retEchostr参数表示明文 //用户需要将retEchostr作为get请求的返回参数、返回给企业微信号 return true; /// <summary> /// 指令响应回调 /// </summary> /// <param name="Request"></param> /// <param name="postString">post请求的xml参数</param> /// <returns></returns> private string CommandCallback(HttpRequestBase Request, string postString) string signature = Request.QueryString["msg_signature"];//微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体 string timestamp = Request.QueryString["timestamp"];//时间戳 string nonce = Request.QueryString["nonce"];//随机数 var xmlDoc = XDocument.Parse(postString);//xml数据转化 //https://work.weixin.qq.com/api/doc/90001/90143/90613 //在发生授权、通讯录变更、ticket变化等事件时,企业微信服务器会向应用的“指令回调URL”推送相应的事件消息。 //消息结构体将使用创建应用时的EncodingAESKey进行加密(特别注意, 在第三方回调事件中使用加解密算法,receiveid的内容为suiteid),请参考接收消息解析数据包。 本章节的回调事件,服务商在收到推送后都必须直接返回字符串 “success”,若返回值不是 “success”,企业微信会把返回内容当作错误信息。 if (xmlDoc.Root.Element("Encrypt") != null) //将post请求的数据进行xml解析,并将<Encrypt> 标签的内容进行解密,解密出来的明文即是用户回复消息的明文 //接收并读取POST过来的XML文件流 string decryptionParame = null; // 解析之后的明文 // 注意注意:sCorpID // @param sReceiveId: 不同场景含义不同,详见文档说明([消息加密时为 CorpId]ToUserName:企业微信的CorpID,当为第三方应用回调事件时,CorpID的内容为suiteid) WXBizMsgCrypt crypt = new WXBizMsgCrypt(sToken, sEncodingAESKey, xmlDoc.Root.Element("ToUserName").Value); var result = crypt.DecryptMsg(signature, timestamp, nonce, postString, ref decryptionParame); if (result != 0) return "fial"; //响应应答处理 return new InstructionCallbackResponse().ReceiveResponse(decryptionParame, timestamp, signature,sToken, sEncodingAESKey, sCorpID); catch (Exception ex) //LoggerHelper._.Debug("异常:" + ex.Message); return "fail"; /// <summary> /// 验证是否为空 /// </summary> /// <param name="strParame">验证参数</param> /// <returns></returns> private bool IsNullOrWhiteSpace(string strParame) if (string.IsNullOrWhiteSpace(strParame)) return true; return false; /// <summary> /// 获取post请求中的xml参数 /// </summary> /// <returns></returns> private string GetXMLParameters(HttpRequestBase Request) string replyMsg; using (Stream stream = Request.InputStream) Byte[] postBytes = new Byte[stream.Length]; stream.Read(postBytes, 0, (Int32)stream.Length); replyMsg = Encoding.UTF8.GetString(postBytes); return replyMsg; }指令回调响应应答处理: /// <summary> /// 指令回调响应应答处理 /// </summary> public class InstructionCallbackResponse /// <summary> /// 响应应答处理 /// </summary> /// <param name="sMsg">解密参数</param> /// <param name="timestamp">时间戳</param> /// <param name="signature">签名</param> /// <param name="sToken">企业微信后台,开发者设置的Token</param> /// <param name="sEncodingAESKey">开发者设置的EncodingAESKey</param> /// <param name="sCorpID">业号corpid是企业号的专属编号(CorpID)</param> /// <returns></returns> public string ReceiveResponse(string sMsg, string timestamp, string signature, string sToken, string sEncodingAESKey, string sCorpID) string responseMessage = "success";//响应内容 var xmlDoc = XDocument.Parse(sMsg);//xml数据转化 //区分普通消息与第三方应用授权推送消息,MsgType有值说明是普通消息,反之则是第三方应用授权推送消息 if (xmlDoc.Root.Element("MsgType") != null) var msgType = (ResponseMsgType)Enum.Parse(typeof(ResponseMsgType), xmlDoc.Root.Element("MsgType").Value, true); switch (msgType) case ResponseMsgType.Text://文本消息 responseMessage = ResponseMessageText(xmlDoc, timestamp, signature,sToken,sEncodingAESKey,sCorpID); break; case ResponseMsgType.Image: responseMessage = ResponseMessageImage(); break; case ResponseMsgType.Voice: responseMessage = ResponseMessageVoice(); break; case ResponseMsgType.Video: responseMessage = ResponseMessageVideo(); break; case ResponseMsgType.News: responseMessage = ResponseMessageNews(); break; else if (xmlDoc.Root.Element("InfoType") != null) //第三方回调 var infoType = (ResponseInfoType)Enum.Parse(typeof(ResponseInfoType), xmlDoc.Root.Element("InfoType").Value, true); switch (infoType) case ResponseInfoType.suite_ticket: //LoggerHelper._.Warn("suite_ticket===>>>>>,进来了,获取到的SuiteTicket票据为" + xmlDoc.Root.Element("SuiteTicket").Value); break; //其他情况 // result==0表示解密成功,sMsg表示解密之后的明文xml串 //服务器未正确返回响应字符串 “success” return responseMessage; #region 相关事件实现 /// <summary> /// 消息文本回复 /// </summary> /// <returns></returns> public string ResponseMessageText(XDocument xmlDoc, string timestamp, string nonce,string sToken,string sEncodingAESKey,string sCorpID) string FromUserName = xmlDoc.Root.Element("FromUserName").Value; string ToUserName = xmlDoc.Root.Element("ToUserName").Value; string Content = xmlDoc.Root.Element("Content").Value; string xml = "<xml>"; xml += "<ToUserName><![CDATA[" + ToUserName + "]]></ToUserName>"; xml += "<FromUserName><![CDATA[" + FromUserName + "]]></FromUserName>"; xml += "<CreateTime>" + GetCurrentTimeUnix() + "</CreateTime>"; xml += "<MsgType><![CDATA[text]]></MsgType>"; xml += "<Content><![CDATA[" + Content + "]]></Content>"; xml += "</xml>"; //"" + Content + "0";//回复内容 FuncFlag设置为1的时候,自动星标刚才接收到的消息,适合活动统计使用 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID); string sEncryptMsg = "";// 加密后的可以直接回复用户的密文; wxcpt.EncryptMsg(xml, timestamp, nonce, ref sEncryptMsg); return sEncryptMsg; /// <summary> /// 图片消息 /// </summary> /// <returns></returns> public string ResponseMessageImage() return "success"; /// <summary> /// 语音消息 /// </summary> /// <returns></returns> public string ResponseMessageVoice() return "success"; /// <summary> /// 视频消息 /// </summary> /// <returns></returns> public string ResponseMessageVideo() return "success"; /// <summary> /// 图文消息 /// </summary> /// <returns></returns> public string ResponseMessageNews() return "success"; #endregion /// <summary> /// 获取当前时间戳 /// </summary> /// <returns></returns> public static string GetCurrentTimeUnix() TimeSpan cha = (DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1))); long t = (long)cha.TotalSeconds; return t.ToString();

Windows Go 开发环境下载、安装并配置

前言对于我们Windows用户而言,Go提供两种环境安装方式(源码安装除外):1、MSI安装(MSI文件是Windows Installer的数据包,它实际上是一个数据库,包含安装一种产品所需要的信息和在很多安装情形下安装(和卸载)程序所需的指令和数据。):程序在安装过程中会自动配置Go所需要的环境变量。2、ZIP安装:需要你手动设置一些环境变量。Go重要环境变量介绍Go开发环境依赖于一些操作系统环境变量,你最好在安装Go之前就设置好这些系统环境变量配置。如果你使用的是Windows的话,你完全不用进行手动设置,Go将被默认安装在目录c:/go(当然你也可以修改GOROOT的安装位置如:D:/Go)下。这里列举几个最为重要的环境变量:GOROOT 是Go在你的电脑上的安装位置,它的值一般都是 c:/go,当然,你也可以安装在别的地方。GOPROXY 是控制Go Module下载的来源,有助于确保构建的确定性和安全性(代理的配置可以在goproxy.io这个网站上找到说明)。GOARCH 表示目标机器的处理器架构,它的值可以是 386、amd64 或 arm。GOOS 表示目标机器的操作系统,它的值可以是 darwin、freebsd、linux 或 windows。GOBIN 表示编译器和链接器的安装位置,默认是 GOROOT/bin,如果你使用的是Go 1.0.3及以后的版本,一般情况下你可以将它的值设置为空,Go 将会使用前面提到的默认值。GOPATH Go开发包在安装完成后会为设置一个默认目录,并且在Go1.14及之后的版本中启用了Go Module模式之后,不一定非要将代码写到GOPATH目录下,所以也就不需要我们再自己配置GOPATH了,使用默认的即可。Go环境下载Go官网下载地址(需要FQ):https://golang.org/dl/Go官方镜像站(国内用户推荐):https://golang.google.cn/dl/Go语言中文网下载(国内用户推荐):https://studygolang.com/dl选择我们对应系统的安装包下载即可:Go1.16.5安装图解 Go安装目录清单打开刚才设置的安装地址:D:\Go(GOROOT)Go安装目录(GOROOT)的文件夹结构简单介绍如下所示:/api:每个版本api变更差异/bin:go源码包编译出的编译器(go)、文档工具(godoc)、格式化工具(gofmt)等/doc:英文版的Go文档/lib:包含项目所引用、依赖的一些库文件/misc:包含与支持 Go 编辑器有关的配置文件以及 cgo 的示例,杂项用途的文件,例如 Android 平台的编译、git 的提交钩子等/pkg:包含Windows 平台编译好的中间文件/src:包含源代码构建脚本和标准库的包的完整源代码/test:测试用例存放处验证是否安装配置成功:win+r: cmd:go version或者:go help查看系统中配置的Go环境变量命令:go env GOPROXY(重要Go默认下载依赖库代理修改)关于GOPROXY由于国内的网络环境问题,我们可以通过配置GOPROXY避免DNS污染导致的模块拉取缓慢或失败的问题,加速你的构建。查看本机环境默认GoPROXY配置,并修改为国内可访问注意:在Go1.14版本之后,都推荐使用go mod模式来管理依赖环境了,也不再强制我们把代码必须写在GOPATH下面的src目录了,你可以在你电脑的任意位置编写Go代码。(网上有些教程适用于1.11版本之前。)由Go环境变量图可知,本机的默认GoPROXY配置是:GOPROXY=https://proxy.golang.org,direct,由于国内访问不到https://proxy.golang.org,所以我们需要换一个PROXY,这里推荐使用https://goproxy.io或https://goproxy.cn。执行下面的命令修改GOPROXY:go env -w GOPROXY=https://goproxy.cn,directgo run命令编译并运行:首先创建helloWorld.go文件:package main //定义一个包,声明包名为main,表明当前是一个可执行程序(Go通过包来管理明明空间) import "fmt" //导入一个外部包fmt func main() { // main函数,是程序执行的入口函数 fmt.Println("Go Hello World!") //在终端打印出Go Hello World! }进入该文件所在位置打开命令行:使用go run命令行运行文件helloWorld.go:

Jenkins汉化配置

登录进入Jenkins首页输入:本地ip+端口号(localhost:8099) 进入插件管理页面(Manage Jenkins)安装相关插件搜索:到available栏目搜索:Locale plugin和Localization: Chinese (Simplified)这两个插件进安装(注意:安全完成后需要重新才会生效)。 配置语言Manage Jenkins=>System Configuration=>Configuration System 搜索:Locale ,设置Default Language为:zh_CN若修改为中文简体,Default Language设置为:zh_cn若修改为中文繁体,Default Language设置为:zh_tw若要修改回英文,Default Language设置为:en_us勾选:"Ignore browser preference and force this language to all users" 并保存。 注意:假如配置完成后没有效果,重启Jenkins在查看(http://localhost:ip/restart) 配置成功:

uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式

前言:  关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式。uni-app跨平台框架介绍和快速入门uni-app跨平台框架介绍和快速入门一、H5+方法调用android原生方法H5+ Android开发规范官方文档:https://www.html5plus.org/doc/zh_cn/android.htmlH5端调用Android activity 并获取activity返回过来的数据//获取当前Activity,使用H5的方式调用android原生方法,从而启动activity var main = plus.android.runtimeMainActivity(); //invoke: 调用对象(类对象/实例对象)的方法,调用Android原生方法 plus.android.invoke('com.pingAnBank.payment.PingAnPaymentHelper', 'StartCallPosPayment', paymentMoney,orderNumber, main, paymentType); //requestCode请求码,即调用startActivityForResult()传递过去的值(一般为int,标志不同的支付类型) //resultCode 结果码,结果码用于标识返回数据来自哪个新Activity //data Intent中所携带的数据 main.onActivityResult = function(requestCode, resultCode, data) { //解析android 的activity回传过来的数据 plus.android.importClass(data); var bundle = data.getExtras(); plus.android.importClass(bundle); //获取activity回传过来的参数值 var amount = bundle.getString("amount"); //支付金额 var traceNo = bundle.getString("traceNo"); //支付流水号 }调用Android方法说明:plus.android.invoke('com.pingAnBank.payment.PingAnPaymentHelper', 'StartCallPosPayment', paymentMoney,orderNumber, main, paymentType);com.pingAnBank.payment.PingAnPaymentHelper:Android中的内部类名StartCallPosPayment:Android中的内部类名中的方法名paymentMoney,orderNumber, paymentType:方法所需的参数main:当前页面的Activity二、uniapp原生插件调用Android原生方法Android原生插件开发教程:https://nativesupport.dcloud.net.cn/NativePlugin/course/android实现功能:通过点击uni-app页面中的按钮传递参数,调用android原生代码,然后Android原生代码处理数据,返回到uniapp页面展示。uni-app代码:<template> <view class="content"> <view @click="callAndroidWay">android原生方法调用</view> </view> </template> <script> // 导入自己定义的插件js var elitetyc = require('../plugin.js'); export default { data() { return { plugins: elitetyc onLoad() { methods: { callAndroidWay(){ this.plugins.StartCallPosPayment( "这段文字是uniapp传过来的", function(result) { uni.showToast({title:JSON.stringify(result),icon:'none',duration:5000}); function(result) { uni.showToast({title:result,icon:"none",duration:5000}); </script>plugin.js插件代码:! function(root, factory) { if (typeof exports == 'object' && typeof module != 'undefined') { module.exports = factory() } else if (typeof define == 'function' && define.amd) { define(factory) } else { document.addEventListener('plusready', function(){ // 这里是定义插件的名称 var moduleName = 'elitetyc'; root.plus[moduleName] = factory() },false); }(this, function() { //在此处定义自己的方法 (这里也是插件的名称,可以看到在后面的) var _BARCODE = 'elitetyc'; var plugintest = { // 这里定义了一个名叫StartCallPosPayment的方法,传递三个参数,后面两个是回调函数 StartCallPosPayment: function(num, successCallback, errorCallback) { var success = typeof successCallback !== 'function' ? null : function(args) { successCallback(args); fail = typeof errorCallback !== 'function' ? null : function(code) { errorCallback(code); // 回调ID,后面原生代码中会用到,就好像你调用我,我有结果了,我该知道我把数据返回给谁把?这个id就是这个作用 var callbackID = plus.bridge.callbackId(success, fail); // 在上面有讲到过,这里需要注意的是前两个参数,第一个参数是插件类别名,后面再原生代码中的dcloud_properties.xml文件中会用到第二个参数(HelloAndroidWay),是android原生代码中的方法名要一致 return plus.bridge.exec(_BARCODE, "HelloAndroidWay", [callbackID, num]); return plugintest; }); Android代码:  我们需要在Android项目中新建一个java文件,在对应的类中什么一个HelloAndroidWay的方法。/** * 定义一个名为HelloAndroidWay的方法 * @param pWebview * @param array public void HelloAndroidWay(IWebview pWebview, JSONArray array) { //获取回调ID String CallBackID = array.optString(0); // 获取参数并计算(这里模拟原生处理) String newstring = "你好,这个字符串来自android原生代码,您传过来的参数是:" + array.optString(1); // 构建回传参数 JSONArray newArray = new JSONArray(); newArray.put(newstring); // JSUtil.execCallback(IWebview pWebViewImpl,String pCallbackId,String pMessage,int pStatus,boolean pKeepCallback) // 参数: // pWebViewImpl - webview对象 // pCallbackId - 回调方法ID // pMessage - 回调信息 // pStatus - 回调code值 如:OK、ERROR // pKeepCallback - js层回调function是否要保存 // 第一个参数是当前函数的入参,直接传入, 第二个是根据入参获取的回调id,第三个是回调的数据,是一个json数组 JSUtil.execCallback(pWebview, CallBackID, newstring, JSUtil.OK, false); }三、WebView简单实现Android与H5互调WebView简介:  要实现Android与H5互调,WebView是一个很重要的控件,WebView可以很好地帮助我们展示html页面,所以有必要先了解一下WebView。关于使用WebView简单实现Android与H5互调的参考文章参考下面文章:https://blog.csdn.net/qq_24530405/article/details/52067474

Fiddler手机抓包配置指南

前言:  对于开发、测试而言,抓包工具绝对是我们日常测试找bug的必备神器。今天主要介绍的是如何配置Fiddler抓取移动端app请求。首先Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据。 Fiddler 要比其他的网络调试器要更加简单,因为它不仅仅暴露http通讯还提供了一个用户友好的格式。Fiddler下载地址:https://www.telerik.com/download/fiddlerTools-Options下配置:注意:fiddler配置完成以后必须要重启,否则手机连接无法下载证书。手机端配置网络:查看本机Ip:1、Fiddler右上角查看:2、window+R : cmd ipconfig:修改手机网络:手机下载fiddler连接证书:在浏览器中输入电脑IP+fiddler监听端口进行访问配置完成查看fiddler中监听结果:Fiddler进行域名或ip重定向及过滤指定域名:

.NET Core Web API使用HttpClient提交文件的二进制流(multipart/form-data内容类型)

需求背景:   在需要通过服务端请求传递文件二进制文件流数据到相关的服务端保存时,如对接第三方接口很多情况下都会提供一个上传文件的接口,但是当你直接通过前端Ajax的方式将文件流上传到对方提供的接口的时候往往都会存在跨域的情况,这时候我们就需要通过服务端提交文件流来解决这个跨域的情况。本篇的主角就是使用HttpClient进行Http请求,提交二进制文件流到文件服务器中。HttpClient简单介绍:HttpClient类实例充当发送 HTTP 请求的会话。 HttpClient实例是对该实例执行的所有请求应用的设置的集合。 此外,每个 HttpClient 实例都使用其自己的连接池,并从其他实例所执行的请求隔离其请求 HttpClient 。使用注意点:HttpClient对象比较特殊,虽然继承了IDisposable这个接口但是它可以被共享实例,并且使用完不能立即关闭连接、性能消耗严重。所以我们在使用的时候,需要主动调用Dispose方法来释放它。可以使用using如下所示:using(var client = new HttpClient()){    //do something with http client}网上说.NET Core版本的HttpClient存在比较多的问题(不过我自己一直在使用HttpClient做一些http请求),大家也可以HttpClientFactory,ASP.NET Core中使用HttpClientFactory官方教程:在 ASP.NET Core 中使用 IHttpClientFactory 发出 HTTP 请求前端使用Ajax-FormData对象上传文件:注意点:FormData:对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。contentType:需设置为false,在Ajax中contentType 设置为false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。processData:需设置为false,默认为true,表示以对象的形式上传的时候会默认把对象转化为字符串的形式上传。<div class="text-center"> <p><input type="file" id="imageFile" onchange="uploadImage(this)" /></p> </div> <div id="imageBox"> </div> <script type="text/javascript"> //图片上传 function uploadImage(fileObject) { var formData = new FormData(); var files = $(fileObject).prop('files'); //获取到文件列表【$("#imageFile").get(0)通过id获取文件列表】 formData.append("files", files[0]);//图片文件流 console.log('formData=>>>', formData, files); $.ajax({ async: true, url:"@Url.Action("UploadImage", "ImageFileManage")", type: 'post', data: formData, //https://segmentfault.com/a/1190000007207128?utm_source=tag-newest //在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件 contentType: false, //告诉jQuery不要去处理发送的数据 processData: false, success: function (res) { console.log(res); if (res.code == 0) { $("#imageBox").append("<img width='100' height='100' src=" + res.msg.completeFilePath+">"); </script>接收Ajax传递的文件流,并转化为转化字节类型: /// <summary> /// 图片文件管理 /// </summary> public class ImageFileManageController : Controller /// <summary> /// 接收Ajax传递的文件流 /// </summary> /// <param name="files">表单文件信息</param> /// <returns></returns> public IActionResult UploadImage(IFormFile files) //var files = Request.Form.Files[0];//获取请求发送过来的文件 if (files.Length <= 0) return Json(new { code = 1, msg = "请选择需要上传的文件~" }); var fileBytes = ReadFileBytes(files); var fileExtension = Path.GetExtension(files.FileName);//获取文件格式,拓展名 var result = HttpClientHelper._.HttpClientPost("https://localhost:44347/FileUpload/SingleFileUpload", fileBytes, fileExtension, files.FileName); var resultObj = JsonConvert.DeserializeObject<UploadReponse>(result); if (resultObj.IsSuccess) return Json(new { code = 0, msg = resultObj }); return Json(new { code = 1, msg = resultObj.ReturnMsg }); /// <summary> /// 文件流类型转化字节类型 /// </summary> /// <param name="fileData">表单文件信息</param> /// <returns></returns> private byte[] ReadFileBytes(IFormFile fileData) byte[] data; using (Stream inputStream = fileData.OpenReadStream())//读取上传文件的请求流 MemoryStream memoryStream = inputStream as MemoryStream; if (memoryStream == null) memoryStream = new MemoryStream(); inputStream.CopyTo(memoryStream); data = memoryStream.ToArray(); return data; /// <summary> /// 上传响应模型 /// </summary> public class UploadReponse /// <summary> /// 是否成功 /// </summary> public bool IsSuccess { get; set; } /// <summary> /// 结果 /// </summary> public string ReturnMsg { get; set; } /// <summary> /// 完整地址 /// </summary> public string CompleteFilePath { get; set; } }向目标地址提交图片文件参数数据(HttpClient-上传multipart/form-data内容类型):注意: /// <summary> /// Http网络请求帮助类 /// </summary> public class HttpClientHelper private static HttpClientHelper _httpClientHelper; public static HttpClientHelper _ get => _httpClientHelper ?? (_httpClientHelper = new HttpClientHelper()); set => _httpClientHelper = value; /// <summary> /// 向目标地址提交图片文件参数数据 /// </summary> /// <param name="requestUrl">请求地址</param> /// <param name="bmpBytes">图片字节流</param> /// <param name="imgType">上传图片类型</param> /// <param name="fileName">图片名称</param> /// <returns></returns> public string HttpClientPost(string requestUrl, byte[] bmpBytes, string imgType, string fileName) using (var httpClient = new HttpClient()) List<ByteArrayContent> byteArrayContents = new List<ByteArrayContent>(); var imgTypeContent = new ByteArrayContent(Encoding.UTF8.GetBytes(imgType)); imgTypeContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") Name = "imgType" byteArrayContents.Add(imgTypeContent); var fileContent = new ByteArrayContent(bmpBytes);//填充图片文件二进制字节 fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") Name = "file", FileName = fileName byteArrayContents.Add(fileContent); var content = new MultipartFormDataContent(); //将ByteArrayContent集合加入到MultipartFormDataContent中 foreach (var byteArrayContent in byteArrayContents) content.Add(byteArrayContent); var result = httpClient.PostAsync(requestUrl, content).Result;//post请求 return result.Content.ReadAsStringAsync().Result; catch (Exception ex) return ex.Message; }模拟第三方上传文件接口,保存图片到服务端并返回文件预览完整地址:关于.NET Core上传文件的后端服务接口可以参考我之前写过的文章:ASP.NET Core单文件和多文件上传并保存到服务端 /// <summary> /// 单文件上传(Ajax,Form表单都适用)模拟第三方服务端接口 /// </summary> /// <param name="file">表单文件信息</param> /// <returns></returns> public JsonResult SingleFileUpload(IFormFile file) if (file != null) var currentDate = DateTime.Now; var webRootPath = _hostingEnvironment.WebRootPath;//>>>相当于HttpContext.Current.Server.MapPath("") var filePath = $"/UploadFile/{currentDate:yyyyMMdd}/"; //创建每日存储文件夹 if (!Directory.Exists(webRootPath + filePath)) Directory.CreateDirectory(webRootPath + filePath); //文件后缀 var fileExtension = Path.GetExtension(file.FileName);//获取文件格式,拓展名 //判断文件大小 var fileSize = file.Length; if (fileSize > 1024 * 1024 * 10) //10M TODO:(1mb=1024X1024b) return Json(new { isSuccess = false, resultMsg = "上传的文件不能大于10M" }); //保存的文件名称(以名称和保存时间命名) var saveName = file.FileName.Substring(0, file.FileName.LastIndexOf('.')) + "_" + currentDate.ToString("HHmmss") + fileExtension; //文件保存 using (var fs = System.IO.File.Create(webRootPath + filePath + saveName)) file.CopyTo(fs); fs.Flush(); //完整的文件路径 var completeFilePath = Path.Combine(filePath, saveName); return Json(new { isSuccess = true, returnMsg = "上传成功", completeFilePath = completeFilePath }); return Json(new { isSuccess = false, resultMsg = "上传失败,未检测上传的文件信息~" }); catch (Exception ex) return Json(new { isSuccess = false, resultMsg = "文件保存失败,异常信息为:" + ex.Message });

【排查解决】System.Runtime.InteropServices.ExternalException (0x80004005): GDI+ 中发生一般性错误

前言:  今天项目发布上线,发布到正式环境验证功能的时候忽然方向之前做的一个图片合成的功能报错了提示:System.Runtime.InteropServices.ExternalException (0x80004005): GDI+ 中发生一般性错误。也就是说应用的System.Drawing中的Bitmap的这个类中的属性出了问题,这到底是什么问题呢?首先我本地开发,测试环境都可以正常的,为什么已发布到正式环境就有问题了呢,到底是环境问题还是配置权限的问题呢?代码如下:/// <summary> /// 合成图片 /// </summary> /// <param name="backgroundImage">背景图</param> /// <param name="qrCodeImg">二维码图片</param> /// <param name="savePhysicalPath">图片存放物理路径</param> /// <param name="xDeviation">绘制图像X轴偏差</param> /// <param name="yDeviation">绘制图像Y轴偏差</param> /// <param name="width">绘制图像宽</param> /// <param name="height">绘制图像高</param> /// <returns></returns> public string CompositePicture(Image backgroundImage, Image qrCodeImg, string savePhysicalPath, int xDeviation = 0, int yDeviation = 0, int width = 0, int height = 0) Bitmap bitmap = new Bitmap(backgroundImage.Width, backgroundImage.Height); Graphics graphics = Graphics.FromImage(bitmap);//绘图 graphics.Clear(Color.White); SolidBrush surush = new SolidBrush(Color.White); graphics.DrawImage(backgroundImage, 0, 0, backgroundImage.Width, backgroundImage.Height); graphics.DrawImage(qrCodeImg, xDeviation, yDeviation, width, height); GC.Collect();//垃圾清理 string compositePictureUrl = savePhysicalPath + Guid.NewGuid().ToString() + ".jpg"; //合成图片保存 bitmap.Save(compositePictureUrl, System.Drawing.Imaging.ImageFormat.Jpeg); return compositePictureUrl; }解决方案:1、首先我排除了一下线上服务器是否存在savePhysicalPath图片存放的物理路径(我发布合成的图片保存的物理物理为/Content/Image)查看确实存在,因为之前在程序中写过判断文件夹是否存在不存在创建文件夹的逻辑。if (!Directory.Exists(savePhysicalPath)) Directory.CreateDirectory(savePhysicalPath); }2、判断文件Image是否存在读写的权限(让服务器管理员查了下果然是没有权限的),把权限的读写权限开通后就一切正常了。

.NET生成小程序码,并合自定义背景图生成推广小程序二维码

前言:  对于小程序大家可能都非常熟悉了,随着小程序的不断普及越来越多的公司都开始推广使用起来了。今天接到一个需求就是生成小程序码,并且与运营给的推广图片合并在一起做成一张漂亮美观的推广二维码,扫码这种二维码就可以进入小程序。为了节省服务器内存资源,我想的就是成功调用通微信生成小程序码的接口后直接把微信返回过来的图片二进制内容(返回的图片 Buffer)转化为二进制byte[]文件流,然后再转成Image这样就不需要在保存到本地直接读取本地的背景图片通过GDI+(Graphics)绘制图片。废话不多说直接上码,各位同学假如有什么小程序的开发问题都欢迎评论区,或者qq私聊我有时间都可以一起学习探索。选择小程序码生成方式:首先微信小程序官方文档提供了三种生成小程序码的方法,如下所示(本文采用的是第三种,需要的码数量极多的业务场景):文档详情地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html1、createwxaqrcode获取小程序二维码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制。2、getwxacode获取小程序码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制。3、getwxacodeunlimit获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。获取小程序全局唯一后台接口调用凭据(access_token):  对接开发过微信相关的业务的同学应该都清楚,调用微信接口很多情况下都会需要使用到access_token接口调用凭证。一般来说access_token的有效时长为2小时,为了不频繁调用该接口我们可以通过缓存的方法把调用凭证存起来并设置合理的过期时间(redis,cookie,memorycache都是非常不错的选择)。请求地址:GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET请求参数:属性类型默认值必填说明grant_typestring 是填写 client_credentialappidstring 是小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)secretstring 是小程序唯一凭证密钥,即 AppSecret,获取方式同 appid返回值(JSON 数据包): 属性类型说明access_tokenstring获取到的凭证expires_innumber凭证有效时间,单位:秒。目前是7200秒之内的值。errcodenumber错误码errmsgstring错误信息请求代码:/// <summary> /// 获取小程序全局唯一后台接口调用凭据(access_token) /// </summary> /// <returns></returns> public string GetWechatAccessToken() var appId = "你的小程序AppID";//小程序唯一凭证,即 AppID var secret = "你的小程序AppSecret"; //小程序唯一凭证密钥,即 AppSecret string Url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, secret); string Result = HttpWebRequest(Url, "GET", "", Encoding.UTF8); var obj = JsonConvert.DeserializeObject<AccessToken>(Result); if (obj != null && obj.access_token != null) return obj.access_token; return ""; /// <summary> /// WebRequest网络请求 /// </summary> /// <param name="requestUrl">请求地址</param> /// <param name="method">请求方式(GET/POST)</param> /// <param name="data">请求参数(method="POST"需要携带)</param> /// <param name="encoding">字符编码</param> /// <param name="contentType">请求数据的内容类型</param> /// <returns></returns> public string HttpWebRequest(string requestUrl, string method, string data, Encoding encoding,string contentType="application/json;charset=UTF-8") WebRequest webRequest = WebRequest.Create(requestUrl); webRequest.Method = method; if (method == "POST") byte[] bytes = Encoding.Default.GetBytes(data); webRequest.ContentType = contentType; webRequest.ContentLength = bytes.Length; Stream requestStream = webRequest.GetRequestStream(); requestStream.Write(bytes, 0, bytes.Length); requestStream.Close(); WebResponse response = webRequest.GetResponse(); Stream responseStream = response.GetResponseStream(); if (responseStream == null) return ""; StreamReader streamReader = new StreamReader(responseStream, encoding); string result = streamReader.ReadToEnd(); responseStream.Close(); streamReader.Close(); return result; /// <summary> /// 响应模型 /// </summary> public class AccessToken /// <summary> /// 获取到的凭证 /// </summary> public string access_token { get; set; } /// <summary> /// 凭证有效时间,单位:秒。目前是7200秒之内的值 /// </summary> public int expires_in { get; set; } /// <summary> /// 错误码 /// </summary> public int errcode { get; set; } /// <summary> /// 错误信息 /// </summary> public string errmsg { get; set; } }小程序码获取:请求地址:POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN请求参数属性类型默认值必填说明access_tokenstring 是接口调用凭证scenestring 是最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)pagestring主页否必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面widthnumber430否二维码的宽度,单位 px,最小 280px,最大 1280pxauto_colorbooleanfalse否自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 falseline_colorObject{"r":0,"g":0,"b":0}否auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示is_hyalinebooleanfalse否是否需要透明底色,为 true 时,生成透明底色的小程序请求成功返回值:返回的图片 Buffer(如果调用成功,会直接返回图片二进制内容(图片文件流),如果请求失败,会返回 JSON 格式的数据。)请求异常返回值:属性类型说明errcodenumber错误码errmsgstring错误信息请求代码:注意:这个与前面获取授权凭证的网络请求不同的是因为要接收请求返回过来的图片二进制内容(buffer),然后需要把二进制文件流转化为byte[]二进制字节流,然后在转化Image。/// <summary> /// 获取小程序码图片 /// </summary> /// <param name="access_token">接口调用凭据</param> /// <param name="param">携带参数</param> private Image GetWetchatAppletQRCodeImage(string access_token, string param) string requestData = "{\"scene\":\"" + param + "\"}"; string requestUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl); request.Method = "POST"; request.ContentType = "application/json;charset=UTF-8"; byte[] payload = System.Text.Encoding.UTF8.GetBytes(requestData); request.ContentLength = payload.Length; Stream writer = request.GetRequestStream(); writer.Write(payload, 0, payload.Length); writer.Close(); HttpWebResponse response; response = (HttpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream();//获取返回的图片 Buffer(文件流) byte[] imageBuffer = StreamToBytes(stream); return ByteArrayConvertToImage(imageBuffer); /// <summary> /// 将文件数据流转为二进制byte[]字节流 /// </summary> /// <param name="stream">文件流</param> /// <returns></returns> private byte[] StreamToBytes(Stream stream) List<byte> bytes = new List<byte>(); int temp = stream.ReadByte(); while (temp != -1) bytes.Add((byte)temp); temp = stream.ReadByte(); return bytes.ToArray(); /// <summary> /// byte [] 转化为Iamge /// </summary> /// <param name="buffer"></param> /// <returns></returns> public static Image ByteArrayConvertToImage(byte[] buffer) using (MemoryStream ms = new MemoryStream(buffer)) // 直接调用Image库类中自带的方法使用MemoryStream实例对象获取Image return Image.FromStream(ms); }小程序码和背景图合并:/// <summary> /// 小程序推广二维码获取 /// </summary> /// <param name="userId">小程序码携带的用户参数</param> /// <returns></returns> public JsonResult GetCompositePictureUrl(int userId) //图片存放物理路径 var savePhysicalPath = HttpContext.Request.MapPath("~/qrcode/"); var imgBack = Image.FromFile(savePhysicalPath + "ewm.jpg");//合成背景图片 var wechatQrcodeImg = GetWetchatAppletQRCodeImage(GetWechatAccessToken(),userId.ToString());//获取小程序码图片 var compositePictureUrl = CompositePicture(imgBack, wechatQrcodeImg, savePhysicalPath, 232, 719, 290, 290); return Json(new { code = 0, compositePictureUrl = compositePictureUrl }); /// <summary> /// 合成图片 /// </summary> /// <param name="backgroundImage">背景图</param> /// <param name="qrCodeImg">二维码图片</param> /// <param name="savePhysicalPath">图片存放物理路径</param> /// <param name="xDeviation">绘制图像X轴偏差</param> /// <param name="yDeviation">绘制图像Y轴偏差</param> /// <param name="width">绘制图像宽</param> /// <param name="height">绘制图像高</param> /// <returns></returns> public string CompositePicture(Image backgroundImage, Image qrCodeImg, string savePhysicalPath, int xDeviation = 0, int yDeviation = 0, int width = 0, int height = 0) Bitmap bitmap = new Bitmap(backgroundImage.Width, backgroundImage.Height); Graphics graphics = Graphics.FromImage(bitmap);//绘图 graphics.Clear(Color.White); SolidBrush surush = new SolidBrush(Color.White); graphics.DrawImage(backgroundImage, 0, 0, backgroundImage.Width, backgroundImage.Height); graphics.DrawImage(qrCodeImg, xDeviation, yDeviation, width, height); GC.Collect();//垃圾清理 string compositePictureUrl = savePhysicalPath + Guid.NewGuid().ToString() + ".jpg"; //合成图片保存 bitmap.Save(compositePictureUrl, System.Drawing.Imaging.ImageFormat.Jpeg); return compositePictureUrl;

uni-app&H5&Android混合开发二 || 使用Android Studio打包应用APK

前言:  在上一章节我们已经讲了如何uni-app离线打包Android平台教程,这一章就该来讲讲如何使用Android Studio打包应用APK提供给Android手机安装使用了。uni-app跨平台框架介绍和快速入门uni-app跨平台框架介绍和快速入门第一步、首先打开已经编译好的Android项目:第二步、选择Build>Generate Signed APK or APK:注意:这里没有签名文件秘钥,则需要进行第三步创建签名秘钥。存在可以直接选择对应的签名文件输入密码验证即可。第三步、如果不存在秘钥,创建新的秘钥(New Key Store):注意:下面这张图片来源于该篇博客(因为这篇博客已经描述的很详细了,所以我就不浪费时间了):http://www.downxia.com/zixun/42752.html第四步、选择对应的app保存路径,并选择release发布版本发布:生成完成后在指定生成目录下即会有一个release文件夹在其下即可找到生成的apk(app-release.apk即时我所打包生成的app应用)。 第五步、项目app应用发布成功,打开apk所在本地目录:第六步、将打包生成的APK文件安装到Android手机上(大功告成)赶紧亲手体验一下打包Android应用的快感吧!!

uni-app&H5&Android混合开发一 || 最全面的uni-app离线打包Android平台教程

前言:  为什么会写这么一个教程,因为很久之前做过一个对接银行POS我们的系统是使用的H5开发的app应用。但是假如对结果银行相关业务的小伙伴应该都清楚,银行的业务相对于其他的对接方而言安全性比较高,而且一般都不会提供定制开发,所以只能我们自己来实现与他们的对接。因此我们把支付这一块做成了Android原生的对接,因为我们需要对接银行提供的Activity组件来来实现POS机扫码、刷卡等相关的支付功能。uni-app跨平台框架介绍和快速入门uni-app跨平台框架介绍和快速入门什么是原生开发?什么是混合开发?两者有什么区别?详情概述:https://zhuanlan.zhihu.com/p/32146560开发环境准备:Android Studio 下载地址:Android Studio官网 OR Android Studio中文社区(Android Studio 下载安装详细教程:https://blog.csdn.net/wangmx1993328/article/details/81905195)uni-app开发环境安装:HBuilderXApp离线SDK下载:最新android平台SDK下载下载uni-app 安卓打包所需要的 SDK:https://nativesupport.dcloud.net.cn/AppDocs/download/android 下载成功,如下图所示:使用Android Studio 打开Hbuilder-Hello (H5+项目模板),并编译:注意:下文中的Hbuilder-Hello等于HBuilder-HelloUniApp因为之前版本是叫做HBuilder-Hello,所以大家只要知道这两个SDK其实是一样的只是版本不一样而已。注意不要把项目放在带有中文的文件夹目录下面,否则无法编译通过提示一下错误:编译的时候会提示:项目路径包含非ASCII字符。这很可能会导致Windows上的生成失败。请将项目移到其他目录或者更改为英文文件名。 打开Hbuilder-Hello Android项目: 注意:导入成功以后进行项目编译,注意第一次项目编译可能会出现ERROR: Read timed out的情况,不过不要慌继续点击编译即可解决。解决项目编译通过后无法直接在虚拟设备中运行提示Error:moudle not specified:问题查找:1、点击Edit Configurations: 2、 在弹出层左侧选择,Android App>app 查看General模块下的Module中是否存在其他模块: Android Studio中运行项目时提示Error:moudle not specified,解决方案: 点击搜索按钮,输入【Sync Project With Gradle Files】,直接点击下面搜索到的内容,然后就会自动安装缺少的Gradle Files文件,安装完成之后项目即可运行! 使用Android Studio中的虚拟设备运行项目,查看运行效果:如何使用Android Studio中的虚拟设备运行项目,如下图所示: 虚拟设备运行成功后的项目界面:HBuilderX生成本地打包App资源:生成本地打包App资源:使用HBuilderX写好的项目,点击发行 > 原生app-本地打包 > 生成本地打包资源,打包完成后,HBuilderX控制台会输出打包信息和打包路径: 生成的资源文件如下图所示:Android知识点补充,assets资源目录和res目录介绍:assets目录下存放的原生资源文件(不会被编译):Android的体系架构设计中,assets目录下的数据内容(图片、文件等等)将不会被Android系统压缩、二次处理等,assets目录下的文件将保持原汁原味打包进Android的apk文件中,因此,利用Android assets这一点特性,根据项目开发的需要,在某种情况下,可以在assets目录下存放一些不希望被Android系统二次处理的原始文件,就像在PC开发时候直接针对硬盘上存放的文件内容进行读写一样读出原始数据。res目录下存放的可编译的资源文件: 这种资源文件系统会在R.java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可。HBuilder-Hello > app > src > main 文件图解:打开android studio 切换项目到project目录,依次打开 HBuilder-Hello > app > src > main > assets,能看到apps.HelloH5.www 和 data 两个文件夹: 将HBuilderX生成本地打包App资源复制到项目App>src>main>assets>apps目录下:将本地App资源文件Copy到App>src>main>assets>apps目录中,并把之前的apps.HelloH5.www 删除(也可以不删除)。apps目录下存在多个app项目如何指定对应项目运行:当我们没有删除apps目录文件夹下的apps.HelloH5.www项目时,在存在两个app项目的情况下如何指定对应的项目运行,下图所示:替换dcloud_control.xml中的appid:复制apps.HelloH5.www>maindest.json 中的id(__UNI__18BEDD3 我项目中的id),替换data>dcloud_control.xml 中的 appid:替换项目appid后重新编译项目,查看HBuilderX生成的本地App资源效果:替换appid后先点击Build先点击Clean Project(清理项目),然后在Make Project(重新编译项目):   虚拟设备运行成功后的项目界面:

【新手指南】Android Studio中应用App的相关配置

前言:  注意这是一个对于Android开发入门学习者而言的一个教程,因为自己平时很少使用Android进行原生应用的开发,对于使用Android Studio配置Android App应用的一些参数(如版本号,应用包名,应用图标,应用名称,起始页等)十分的陌生。这里主要记录下自己开发中的一些经验所得,方便下一次直接查看并且希望可以帮助到刚刚入门Android开发的小伙伴。app中的build.gradle中的相关配置:简介:Google推荐使用的Android Studio是采用Gradle来构建项目的。Gradle是一个非常先进的项目构建工具。Gradle是用了一种基于Groovy的领域特定语言(DSL,Domain Specific Language)来声明项目设置,摒弃了XML(如ANT和Maven)的各种繁琐配置。项目中一般会出现2个或者多个build.gradle文件,一个在根目录下,一个在app目录下。项目位置:build.gradle详解:https://blog.csdn.net/hebbely/article/details/79074460defaultConfig(基础配置)://默认配置 defaultConfig { applicationId "com.rayhahah.gradledemo" //最低版本 minSdkVersion 19 //目标版本 targetSdkVersion 25 //版本代码 versionCode 1 versionName "1.0" //自动化测试 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }Android中VersionCode和VersionName命名规则:VersionCode,整数值,发布第一版程序设为1,每次发布依次递增,对用户不可见,仅用于识别版本用途。VersionName,字符串值,对用户可见,如1.0.0。Android中应用Id(applicationId):应用Id(applicationId):每个Android应用都有一个唯一的应用ID.在Android设备和市场上,这个ID是你应用的唯一标识.若想在市场上更新应用,新应用的ID必须和原来apk的应用ID一致.所以一旦发布了应用,就不能再改变应用ID。注意:applicationId在安卓设备和商店中是作为应用的唯一标识,所以应用一旦发布应用程序,就不推荐再去修改applicationId,否则将会视为完全不同的应用。applicationId命名规则:applicationId看起来很像package name,但是它的命名规则是有一些限制的:它必须至少有两段,也就是一个或者多个点来间隔它们。每个小段都必须以字母开头。所有字符必须为字母数字或下划线[a-zA-Z0-9_]如:applicationId "hncx.blockstore.cn"修改应用applicationId,Version Code,Version Name:注意直接在项目结构中进行应用Id修改可以避免安装到android手机上避免项目闪退情况!!!  直接按F4,或者是点击File>Project Structure(项目结构),在新弹出的窗口中,依次点击左边的Modules找到app、上方的Default Config,然后在Application Id处修改成刚才修改的名称,修改完成后一定要记得点击【Apply应用】否则是不会生效的。如下图AndroidManifest.xml介绍: Android应用的入口文件,它描述了package中暴露的组件(activities, services等),他们各自的实现类,各种能被处理的数据和启动位置。 AndroidManifest.xml详解:https://blog.csdn.net/mluoya/article/details/87827335package 包名,应用进程的默认名称:Android Studio应用App 名称、图标,启动页修改:应用名称修改:在Android Studio中以“Android”模式浏览程序,在“app->res->values->strings.xml”中可以看到如下图所示。应用图标修改:app->res->drawable-xxhdpi->icon.png。应用启动页修改:app->res->drawable-xxhdpi->splash.png。

Android Studio在android Emulator中运行的项目黑屏

前言:  最近在做一个Android相关的小项目,因为之前这方面的项目做的比较的少。今天在使用虚拟机调试的时候经常出现一些莫名其妙的问题,经过自己多次的尝试和搜索终于解决了这些问题。问题:每次run(运行)项目在android Emulator一直显示黑屏问题,如下如所示:可能是没有检测到匹配的虚拟设备(unknown devices):解决方案:重新创建一个新的虚拟设备(Create virtural devices),下载,安装:点击Android Virtual Device Manager(虚拟设备管理)按钮>Create virtual devices最后选择刚安装的虚拟设备运行android项目:黑屏问题成功解决,项目界面正常展示:

.NET HttpWebRequest(请求被中止: 未能创建 SSL/TLS 安全通道)和(基础连接已经关闭: 发送时发生错误)问题查找解决

前言:  前段时间在对接第三方接口的时候发生了一个非常奇葩的问题,就是使用 .NET Framework 4.6 HttpWebRequest进行网络请求的相关问题。背景,关于调用第三方的接口都是使用使用自己封装的一个HttpWebRequestHepler帮助类,在本地开发时调用第三方接口都是正常的。然而当我部署到运维给我一个服务器(阿里云服务器)时刚开始提示是请求被中止: 未能创建 SSL/TLS 安全通道,之后经过一番修改以后就是提示基础连接已经关闭: 发送时发生错误。之后尝试了各种方法,还是没有办法解决基础连接已经关闭: 发送时发生错误这个问题。最后真的是无能为力,光这个问题找了一下午的解决方案,最后换到了我自己的阿里云服务器是可以正常调通第三方接口的。然后让运维看了下服务器结果是这个服务器都没有开通外网,所以导致了这个问题的出现。下面记录下问题排除的过程,希望能够帮助到遇到这种坑的小伙伴。一、自己封装的一个通用的HttpWebRequestHepler Http Web网络请求帮助类:/// <summary> /// Http Web网络请求帮助类 /// </summary> public class HttpWebRequestHepler private static HttpWebRequestHepler _httpWebRequestHepler; private string _resContent;//响应内容 private string _errInfo;//错误信息 private int _responseCode;//响应状态码 public static HttpWebRequestHepler _ get => _httpWebRequestHepler ?? (_httpWebRequestHepler = new HttpWebRequestHepler()); set => _httpWebRequestHepler = value; /// <summary> /// 数据请求 /// </summary> /// <param name="requestUrl">请求地址</param> /// <param name="postData">请求参数</param> /// <param name="accessToken">授权token</param> /// <param name="contentType">请求标头值类型</param> /// <param name="method">请求方式</param> /// <returns></returns> public string HttpWebResponseData(string requestUrl, string postData, string accessToken = "", string contentType = "application/json", string method = "POST") HttpWebResponse wr = null; var hp = (HttpWebRequest)WebRequest.Create(requestUrl); hp.Timeout = 60 * 1000 * 10;//以毫秒为单位,设置等待超时10分钟 hp.Method = method; hp.ContentType = contentType; if (!string.IsNullOrWhiteSpace(accessToken)) hp.Headers.Add("Authorization", "Bearer " + accessToken);//增加headers请求头信息 if (postData != "")//带参数请求 byte[] data = Encoding.UTF8.GetBytes(postData); hp.ContentLength = data.Length; Stream ws = hp.GetRequestStream(); // 发送数据 ws.Write(data, 0, data.Length); ws.Close(); wr = (HttpWebResponse)hp.GetResponse(); var sr = new StreamReader(wr.GetResponseStream() ?? throw new InvalidOperationException(), Encoding.UTF8); this._resContent = sr.ReadToEnd(); sr.Close(); wr.Close(); catch (Exception exp) this._errInfo += exp.Message; if (wr != null) this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; this._responseCode = Convert.ToInt32(wr.StatusCode); return this._resContent; }二、请求被中止: 未能创建 SSL/TLS 安全通道问题解决:  把项目部署到阿里云服务器中,请求第三方提示请求被中止: 未能创建 SSL/TLS 安全通道。首先字面上可以看出来这个https请求安全协议的问题。微软官方说明是,NET 4.6需要添加ServicePointManager.SecurityProtocol属性,指定schnanel安全包支持的安全协议。微软官方解释:此属性选择要用于新连接的安全套接字层 (SSL) 或传输层安全性 (TLS) 协议的版本;不会更改现有连接。从 .NET Framework 4.7 开始,此属性的默认值为 SecurityProtocolType.SystemDefault 。 这允许基于 SslStream ((如 FTP、HTTP 和 SMTP) )的 .NET Framework 网络 api 从操作系统或系统管理员执行的任何自定义配置继承默认安全协议。 有关默认情况下在每个版本的 Windows 操作系统上启用了哪些 SSL/TLS 协议的信息,请参阅 TLS/SSL (SCHANNEL SSP) 中的协议 。对于通过 .NET Framework 4.6.2 的 .NET Framework 版本,不会列出此属性的默认值。 安全环境不断变化,默认的协议和保护级别会随着时间的推移而更改,以避免已知的漏洞。 默认值因单独的计算机配置、已安装的软件和应用的修补程序而异。 解决方案://todo:指定请求包的安全协议,因为不知道你当前项目到底是哪个版本所以为了安全保障都加上 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;三、基础连接已经关闭: 发送时发生错误        这个问题查阅了网上几个比较典型的博客试了下,结果都没有办法解决我的问题,一下记录下这几个博客的解决方案,希望可以帮助到遇到这样问题的小伙伴。1、一般来说添加了上面的ServicePointManager.SecurityProtocol属性就可以解决这个基础连接关闭的问题。2、C# HttpRequest基础连接已经关闭: 接收时发生意外错误(原文地址)://增加下面两个属性即可 hp.KeepAlive = false; hp.ProtocolVersion = HttpVersion.Version10;四、开启阿里云服务器外网(我的解决方案)  查看一下你的服务器是否开通了外网,假如没有开通服务器外网在进行尝试。阿里云服务器配置外网访问参考。因为这个奇葩问题花费了一天宝贵的时间,考虑问题还是得多方面考虑。

【.NET开发福音】使用Visual Studio将JSON格式数据自动转化为对应的类

前言:  这段时间一直在做一个第三方平台的对接,对接第三方其实无非就是请求调用第三方的相关接口接收返回过来的相关参数。因此在这个过程中就会涉及大量的JSON响应参数或者请求参数转化为对应的实体类的情况,因为只有转化为对应的实体类我们才好进行相关的数据操作。那么问题来了,这样我们在遇到后很多JSON对象的情况下是不是要自己一个一个的去写对应类的属性那假如有二三十个那岂不是要疯了去,其实咱们强大的Visual Studio有一个强大的功能能够将JSON串自动转化为对应的类(真的是一个提高工作效率的好方法)。一、首先进行Json格式化校验http://www.bejson.com/  (推荐这个在线工具非常好用){ "metaData": { "defaultLang": "zh-CN", "name": "追逐时光者每日一秀", "categoryIds": ["214342106997653504", "214343889333583872"], "tagIds": ["215586040843403264", "212828639341903872"], "residentAGApp": "101144753", "sourceName": "追逐时光者出版社", "sellingMode": 2, "remarks": "你是最棒的", "availableFrom": "2019-01-01T08:00:00Z", "availableBefore": "2020-01-01T10:00:00Z", "autoStatusChange": [{ "status": 0, "changeTime": "string" "eduappUsed": true, "eduappPurchased": true, "devProductId": "1001", "distNotifyUrl": "https://www.cnblogs.com/Can-daydayup/", "validityUnit": 5, "validityNum": 1, "includeLessons": true, "typeId": 1001, "teachers": ["212828639341903872"], "mediaType": 3, "needDelivery": true "countryCodes": ["CN", "SG"] }二、复制JSON串,前往Visual Studio找到编辑=》选择性粘贴=》将JSON粘贴为类:注意:首先根据自己的需求创建一个对应实体空白类三、JSON成功转化的实体类:namespace Domain.Model public class Rootobject public Metadata metaData { get; set; } public string[] countryCodes { get; set; } public class Metadata public string defaultLang { get; set; } public string name { get; set; } public string[] categoryIds { get; set; } public string[] tagIds { get; set; } public string residentAGApp { get; set; } public string sourceName { get; set; } public int sellingMode { get; set; } public string remarks { get; set; } public DateTime availableFrom { get; set; } public DateTime availableBefore { get; set; } public Autostatuschange[] autoStatusChange { get; set; } public bool eduappUsed { get; set; } public bool eduappPurchased { get; set; } public string devProductId { get; set; } public string distNotifyUrl { get; set; } public int validityUnit { get; set; } public int validityNum { get; set; } public bool includeLessons { get; set; } public int typeId { get; set; } public string[] teachers { get; set; } public int mediaType { get; set; } public bool needDelivery { get; set; } public class Autostatuschange public int status { get; set; } public string changeTime { get; set; }

ASP.NET Core获取请求完整的Url

在ASP.NET项目中获取请求完整的Url:获取System.Web命名空间下的类名为HttpRequestBase的Url方法: /// <summary>在派生类中替代时,获取有关当前请求的 URL 的信息。</summary> /// <returns>包含有关当前请求的 URL 的信息的对象。</returns> /// <exception cref="T:System.NotImplementedException"> /// 始终。 /// </exception> public virtual Uri Url throw new NotImplementedException(); 在控制器中获取://获取完整的Url地址 string completeUrl = Request.Url.ToString();在ASP.NET Core项目中获取:        由于.NET Core相关接口重构,现在无法在项目中直接获取当前请求的完整的Url地址了,需要我们自己把Microsoft.AspNetCore.Http命名空间下类名为HttpRequest的相关方法拼接获取,如下所示。public IActionResult Privacy() //获取当前请求完整的Url地址 var GetCompleteUrlStr=GetCompleteUrl(); return View(); /// <summary> /// 获取当前请求完整的Url地址 /// </summary> /// <returns></returns> private string GetCompleteUrl() return new StringBuilder() .Append(HttpContext.Request.Scheme) .Append("://") .Append(HttpContext.Request.Host) .Append(HttpContext.Request.PathBase) .Append(HttpContext.Request.Path) .Append(HttpContext.Request.QueryString) .ToString(); OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown

OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown
Visual Studio 2022 git error Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa
Visual Studio 2022 git error Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa
Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa(解决的两种方式)
Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa(解决的两种方式)
.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结(XmlSerializer,XmlTypeAttribute,XmlElementAttribute,XmlAttributeAttribute,XmlArrayAttribute...)
.NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结(XmlSerializer,XmlTypeAttribute,XmlElementAttribute,XmlAttributeAttribute,XmlArrayAttribute...)