Servlet快速学习和Tomcat快速部署(web)

Servlet快速学习和Tomcat快速部署(web) 一.快速入门二、执行流程三、生命周期四、Servlet体系结构五、Servlet urlPattern配置六、XML配置方式编写Servlet七、Tomcat快速部属(idea) 🌹servlet 是java提供的一门动态的web资源开发技术🌹 Servlet是javaEE的规范(规范就是接口),将来需要我们定义Servlet类实现Servlet接口,并有web服务器运行Servlet。 一.快速入门 1.创建web项目,导入Servlet依赖坐标 <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> <!--这个provided 编译环境和测试项目有效,运行环境排除掉,因为tomcat包含这个包,不然就冲突了--> 2.创建:定义一个类,实现servlet接口,并重写接口中所有方法,并在service方法中输入一句话 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("servlet hello world~"); } 3.配置:在类上使用@WebServlet注解,配置该Servlet访问路径 @WebServlet("/demo1") //这里是当前servlet访问路径 public class ServletDemo1 implements Servlet { 4.访问:启动Tomcat,浏览器输入URL访问Servlet 显示页面是空白,因为我们并没有向页面输出信息,我们的输出内容在控制台里面,这样就说明servlet被成功访问。 二、执行流程 http://localhost:8080/web-demo/demo1 http://localhost:8080:访问tomcat服务器 /web-demo:访问对应的web项目 /demo1:访问对应得Servlet页面 1.Servlet对象和对应得方法都是tomcat web服务器创建和调用得 2.服务器怎么知道Servlet中一定有service方法? ​ 因为我们自定的servlet,必须实现Servlet接口并复其方法,而Servlet接口中有service方法。 三、生命周期 创建到销毁的过程称为生命周期 servlet生命周期由容器(web服务器)来管理,四个阶段: 加载实例化:默认情况,servlet第一次访问时被创建 @WebServlet(urlPattrens="/demo1",loadOnStartup=1) 0或者正数:服务器启动时创建servlet,数字越小优先级越高 初始化:实例化后容器调用servlet的init方法初始化这个对象(只调用一次),用来加载配置、创建链接等 请求处理:请求Servlet时(访问),容器都会调用Servlet的service方法(提供服务的)对请求处理(会执行很多次) 服务终止:当需要释放内存或者容器被关闭,容器调用servlet的destroy方法,之后该实例会被java垃圾收集器所回收 ServletConfig getSerletConfig()//获取ServeltConfig对象 String getServeltinfo() //获取Servlet信息 四、Servlet体系结构 我们开发的B/S框架的web项目都是针对HTTP协议,所以我们自定义Servlet,会继承HTTPServlet

Vue3实现滚动加载动画效果

目录 滚动加载动画依赖配置配置动画 滚动加载动画 实现效果:滚到到指定元素后,该元素才执行对应动画 依赖配置 实现该效果,需要借助两个库:wow.js以及animate.css 并且由于wow 依赖于 animate 动画库,所以 安装 animate.css 以及 wow.js npm install animate.css --save npm install wow.js --save 配置动画 首先写一个简单的页面 提供两个元素,第一个为占据全屏(是为了提供滚动空间)的 div,第二个为模拟需要执行动画的卡片 <template> <div class="container"> <!-- 占据全屏 --> <div class="before">index</div> <!-- 欲执行动画的div --> <div class="after">after</div> </div> </template> <script setup></script> <style scoped lang="less"> .container { width: 100%; .before { width: 100%; height: 100vh; background-color: antiquewhite; } .after { width: 40%; height: 40vh; background-color: aquamarine; } } </style> 修改第二个元素,填入你想要执行的动画 class,类名可以直接在 animate.

nodejs性能优化——多进程

1.引言 现在在准备毕设,打算还是使用nodejs作为后端,遇到了一些知识上的瓶颈,主要是想要写出一个高性能点的爬虫,由于每次请求的http数量上万,经常挂了,要么是他人的服务器终止了连接,要么是node经不起密集CPU,毕竟请求完成之后还需要对数据进行处理,特别是我毕设里面需要的数据涉及到cheerio依赖对于页面dom的操作,因此更加怀疑的是nodejs的算力不够导致的。因此,想要看看是否可以通过多线程和多进程来解决一下,恰好之前有一些知识落下了,刚好补一补。 2.ab测试 提及这个主要是为了验证node多线程和多进程到底是做什么的,能够提供那些优化参考。首先借鉴一写文章说一下概念,ab是apache bench命令的缩写,ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问。它既可以用来测试apache的负载压力,也可以测试nginx、tomcat等其它Web服务器的压力。ab命令对发出负载的计算机要求很低,它既不会占用很高CPU,也不会占用很多内存。但却会给目标服务器造成巨大的负载,其原理类似CC攻击。 2.1环境配置 mac内置Apache,但是windows是没有的,所以需要自己下一个Apache。刚好自己经常用小皮面板来下载数据库或者Apache或者是Nginx来配置本地开发环境,因此直接配个环境变量就行,比如我电脑里面的路径: D:\phpstudy_pro\Extensions\Apache2.4.39\bin 如果没有下载过小皮面板,推荐安装一个,毕竟用这个能够快速切换数据库版本,快速搭建本地环境,配一个Navicat能够轻松搞一个系统出来,比直接单独安装Apache和MySQL好的多。 3.1ab测试演示 我们先主要说一下ab测试的流程,翻译一些常用参数,以及指示性能的参数: //多进程测试 let cluster = require("cluster"); let http = require("http"); let CPUNum = require("os").cpus().length;//获取CPU的核数 if (cluster.isMaster) { for (let i = 0; i < CPUNum; i++) { cluster.fork(); } cluster.on("exit", (worker, code, signal) => { console.log("进程消亡:", worker, code, signal) }) } else { http.createServer((req, res) => { res.end('hello world\n'); }).listen(8000, () => { console.log("localhost:8000"); }); } 对于电脑的CPU核数也可以利用任务管理器查看: 好直接测试,cmd中输入(如果提示ab不是内部指令那就是Apache的环境变量没有配置好): ab -c 20 -n 100 http://127.

如何设计一个高并发系统

如何理解高并发系统 所谓设计高并发系统,就是设计一个系统,保证它整体可用的同时,能够处理很高的并发用户请求,能够承受很大的流量冲击。 我们要设计高并发的系统,那就需要处理好一些常见的系统瓶颈问题,如内存不足、磁盘空间不足,连接数不够,网络宽带不够等等,以应对突发的流量洪峰。 1. 分而治之,横向扩展 如果你只部署一个应用,只部署一台服务器,那抗住的流量请求是非常有限的。并且,单体的应用,有单点的风险,如果它挂了,那服务就不可用了。 因此,设计一个高并发系统,我们可以分而治之,横向扩展。也就是说,采用分布式部署的方式,部署多台服务器,把流量分流开,让每个服务器都承担一部分的并发和流量,提升整体系统的并发能力。 2. 微服务拆分(系统拆分) 要提高系统的吞吐,提高系统的处理并发请求的能力。除了采用分布式部署的方式外,还可以做微服务拆分,这样就可以达到分摊请求流量的目的,提高了并发能力。 所谓的微服务拆分,其实就是把一个单体的应用,按功能单一性,拆分为多个服务模块。比如一个电商系统,拆分为用户系统、订单系统、商品系统等等。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OXAhC2SP-1678757870124)(/Users/zsh/Desktop/2.png)] 3. 分库分表 当业务量暴增的话,MySQL单机磁盘容量会撑爆。并且,我们知道数据库连接数是有限的。在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!高并发场景下,会出现too many connections报错。 所以高并发的系统,需要考虑拆分为多个数据库,来抗住高并发的毒打。而假如你的单表数据量非常大,存储和查询的性能就会遇到瓶颈了,如果你做了很多优化之后还是无法提升效率的时候,就需要考虑做分表了。一般千万级别数据量,就需要分表,每个表的数据量少一点,提升SQL查询性能。 当面试官问要求你设计一个高并发系统的时候,一般都要说到分库分表这个点。 4. 池化技术 在高并发的场景下,数据库连接数可能成为瓶颈,因为连接数是有限的。 我们的请求调用数据库时,都会先获取数据库的连接,然后依靠这个连接来查询数据,搞完收工,最后关闭连接,释放资源。如果我们不用数据库连接池的话,每次执行SQL,都要创建连接和销毁连接,这就会导致每个查询请求都变得更慢了,相应的,系统处理用户请求的能力就降低了。 因此,需要使用池化技术,即数据库连接池、HTTP 连接池、Redis 连接池等等。使用数据库连接池,可以避免每次查询都新建连接,减少不必要的资源开销,通过复用连接池,提高系统处理高并发请求的能力。 同理,我们使用线程池,也能让任务并行处理,更高效地完成任务。 5. 主从分离 通常来说,一台单机的MySQL服务器,可以支持500左右的TPS和10000左右的QPS,即单机支撑的请求访问是有限的。因此你做了分布式部署,部署了多台机器,部署了主数据库、从数据库。 但是,如果双十一搞活动,流量肯定会猛增的。如果所有的查询请求,都走主库的话,主库肯定扛不住,因为查询请求量是非常非常大的。因此一般都要求做主从分离,然后实时性要求不高的读请求,都去读从库,写的请求或者实时性要求高的请求,才走主库。这样就很好保护了主库,也提高了系统的吞吐。 当然,如果回答了主从分离,面试官可能扩展开问你主从复制原理,问你主从延迟问题等等,这块大家需要**全方位掌握好。 6. 使用缓存 无论是操作系统,浏览器,还是一些复杂的中间件,你都可以看到缓存的影子。我们使用缓存,主要是提升系统接口的性能,这样高并发场景,你的系统就可以支持更多的用户同时访问。 常用的缓存包括:Redis缓存,JVM本地缓存,memcached等等。就拿Redis来说,它单机就能轻轻松松应对几万的并发,你读场景的业务,可以用缓存来抗高并发。 缓存虽然用得爽,但是要注意缓存使用的一些问题: 缓存与数据库的一致性问题缓存雪崩缓存穿透缓存击穿 7. CDN,加速静态资源访问 商品图片,icon等等静态资源,可以对页面做静态化处理,减少访问服务端的请求。如果用户分布在全国各地,有的在上海,有的在深圳,地域相差很远,网速也各不相同。为了让用户最快访问到页面,可以使用CDN。CDN可以让用户就近获取所需内容。 什么是CDN? Content Delivery Network/Content Distribution Network,翻译过来就是内容分发网络,它表示将静态资源分发到位于多个地理位置机房的服务器,可以做到数据就近访问,加速了静态资源的访问速度,因此让系统更好处理正常别的动态请求。 8. 消息队列,削锋 我们搞一些双十一、双十二等运营活动时,需要避免流量暴涨,打垮应用系统的风险。因此一般会引入消息队列,来应对高并发的场景。 假设你的应用系统每秒最多可以处理2k个请求,每秒却有5k的请求过来,可以引入消息队列,应用系统每秒从消息队列拉2k请求处理得了。 有些伙伴担心这样可能会出现消息积压的问题: 首先,搞一些运营活动,不会每时每刻都那么多请求过来你的系统(除非有人恶意攻击),高峰期过去后,积压的请求可以慢慢处理;其次,如果消息队列长度超过最大数量,可以直接抛弃用户请求或跳转到错误页面; 9. ElasticSearch Elasticsearch,大家都使用得比较多了吧,一般搜索功能都会用到它。它是一个分布式、高扩展、高实时的搜索与数据分析引擎,简称为ES。 我们在聊高并发,为啥聊到ES呢?因为ES可以扩容方便,天然支撑高并发。当数据量大的时候,不用动不动就加机器扩容,分库等等,可以考虑用ES来支持简单的查询搜索、统计类的操作。 10. 降级熔断 熔断降级是保护系统的一种手段。当前互联网系统一般都是分布式部署的。而分布式系统中偶尔会出现某个基础服务不可用,最终导致整个系统不可用的情况, 这种现象被称为服务雪崩效应。 比如分布式调用链路A->B->C....,下图所示: 如果服务C出现问题,比如是因为慢SQL导致调用缓慢,那将导致B也会延迟,从而A也会延迟。堵住的A请求会消耗占用系统的线程、IO、CPU等资源。当请求A的服务越来越多,占用计算机的资源也越来越多,最终会导致系统瓶颈出现,造成其他的请求同样不可用,最后导致业务系统崩溃。 为了应对服务雪崩, 常见的做法是熔断和降级。最简单是加开关控制,当下游系统出问题时,开关打开降级,不再调用下游系统。还可以选用开源组件Hystrix来支持。 你要保证设计的系统能应对高并发场景,那肯定要考虑熔断降级逻辑进来。 11. 限流 限流也是我们应对高并发的一种方案。我们当然希望,在高并发大流量过来时,系统能全部请求都正常处理。但是有时候没办法,系统的CPU、网络带宽、内存、线程等资源都是有限的。因此,我们要考虑限流。

OSPF多区域实验

一、OSPF多区域 (一)实验介绍 1、学习目标 实现手动指定OSPF Router ID 实现OSPF多区域配置 阐明OSPF区域之间路由汇总的配置方法 阐明OSPF参考带宽的配置方法 阐明OSPF引入外部路由的配置方法 阐明OSPF引入的外部路由时进行路由汇总的方法 阐明向OSPF引入缺省路由的方法 阐明对OSPF中各类路由优先级的修改方法 2、实验组网介绍 免费视频链接:【实战课】华为HCIA-Datacom认证实验教学-学习视频教程-腾讯课堂 OSPF多区域 互联接口、IP地址如上图所示,所有设备均创建Loopback0,其IP地址为10.0.x.x/24,其中x为设备编号。 R1、R3的所有接口以及R2的GE0/0/4接口属于OSPF区域2,R2、R4的Loopback0接口及互联接口属于OSPF区域0,R4、R5的互联接口、R5的Loopback0、1、2接口属于OSPF区域1。 R2上创建Loopback1、2接口用于模拟外部网段。 3、实验背景 你是公司的网络管理员。现在公司的网络中有五台AR路由器,其中R2和R4在公司总部,R1、R3、R5在公司分部。由于网络规模较大,为了控制LSA的洪泛,你设计了多区域的OSPF。 为了明确设备的Router-ID,你配置设备使用固定的地址作为Router ID。 为了使路由器进行路由转发时效率更高,你在区域的边界配置了自动汇总。 R1路由器连接到Internet,你需要配置一条缺省路由,引入到OSPF区域,以便于OSPF区域的所有路由器都知道如何访问Internet。 同时OSPF路由信息中区分了内部路由和外部路由,你修改了OSPF路由信息的优先级信息,以避免潜在的风险。 OSPF中特定路由信息的度量值是将到达目的网络经过的所有链路的代价值进行累加得到的。而链路的代价值是路由器将接口带宽与参考带宽进行对比得到。参考带宽值为100Mbps,实际接口带宽可能为1000Mbps,而度量值都是整数,所以快速以太网接口和千兆以太网接口的OSPF代价值均为1。为了能够相互区分这些链路,你定义参考带宽值为10Gbps。 (二)实验任务 1、任务思路 设备IP地址配置。按照规划配置OSPF区域。检查OSPF配置结果,检查OSPF邻居关系状态,在ABR上查看OSPF LSDB。在ABR、ASBR上配置路由汇总,减少区域间、外部路由数量。修改OSPF的参考带宽值。在OSPF中引入缺省路由。修改OSPF域内、域间路由和域外路由的缺省路由优先级。 2、任务步骤 2 互联接口、环回口IP地址配置 #设备命名 略。 #关闭本实验中未使用的接口 略 #配置R1的GE0/0/3接口、环回口IP地址 [R1]interface GigabitEthernet0/0/3 [R1-GigabitEthernet0/0/3] ip address 10.0.123.1 24 [R1-GigabitEthernet0/0/3] quit [R1]interface LoopBack 0 [R1-LoopBack0] ip address 10.0.1.1 24 [R1-LoopBack0] quit #配置R2的GE0/0/4、GE0/0/2接口、环回口IP地址 [R2]interface GigabitEthernet0/0/4 [R2-GigabitEthernet0/0/4] ip address 10.0.123.2 24 [R2-GigabitEthernet0/0/4] quit [R2] interface GigabitEthernet0/0/2

5秒用Python轻松爬取全国"地铁"数据!

截止发文,全国一共有40个城市开通了地铁,累计站点数量为5968 而我,爬完这些数据,只用了5秒 此时,正在看文章的你,是不是心里会默默的来一句:麻雀啄了牛屁股—雀食牛逼 今天就来教大家用 Python 如何快速搞定,先给一个使用说明,源码和逻辑见后文 1、核心代码 首先是先获取所有开通地铁的城市 代码分成两部分,一部分是官方页面显示出的城市列表,一部分是未显示出来的城市列表 其中,主函数代码如下: """获取有地铁站点的城市名""" df_city_list = get_city_list() print('[ 提示 ]: 共检测到 {0} 个开通地铁的城市'.format(df_city_list.shape[0])) 其次是遍历每个城市,获取对应城市的所有地铁线路 并将最终的结果进行拼接,最终生成的就是所有城市的所有地铁站点信息 df_city_data = pd.DataFrame() for row_index, data_row in df_city_list.iterrows(): print('[ 提示 ]: 正在爬取第 {0}/{1} 个城市 {2} 的数据中...'.format(row_index + 1, df_city_list.shape[0], data_row['name_ch'])) """遍历每个城市获取地铁站点信息""" df_per_city = get_per_info(data_row) df_city_data = df_city_data.append(df_per_city, ignore_index=True) 程序运行图如下: 最终爬取的数据如下: 一共40个城市,5968条数据 2、爬虫思路 获取源码文件请直接在后台回复 地铁站点 今天的源码其实之前有写过,但是因为过去时间比较久了,没有和官方的更新同步,所以在运行过程中会出现bug 这次我也是将存在的bug修复了,并优化了部分逻辑,比以前的代码运行速度会更快。 今天的数据来自于高德,下面是高德地图对于全国地铁站点的一个可视化界面,做的相当不错。 页面长这样: 对了,如果有不擅长写代码的读者,但是又想拿到数据做分析和挖掘,可以在后台回复地铁数据集我会发给你。 首先,浏览器打开 F12,定位到上方的城市列表 对应的城市列表是直接显示在 div 标签里面的,不过城市是被分成了两部分,一部分在 city-list 里面,一部分在 more-city-list 里面。

信息安全基础-扫描技术笔记

一、IP地址扫描 主要用在网络攻击开始的阶段,用于获取目标计算机及其外围网格使用的IP网段,以及对应网段中处于开机状态的计算机。 主要利用ping,tracert等操作系统提供的简单命令,或者Nmap、SuperScan这种扫描工具。 注:ping是利用ICMP协议数据包判断目标主机是否开机,检测和本机之间的网络链路是否联通。 1.ping命令构建一个固定格式的ICMP请求数据包echo request,并设置一个要检测的目标IP地址。 2.目标IP地址的计算机收到ICMP探测包,将构建一个ICMP应答包echo reply返回给源主机 此时还可以根据发送包和应答包携带的时间信息计算出网络延迟 二、网络端口扫描 网络攻击者通过Nmap对网络端口进行扫描从而得到目标计算机开放的网络服务程序。 注:TCP协议通过套接字来建立起两台计算机之间的连接,套接字采用【IP地址:网络端口号】的形式定义。 注:TCP和UDP协议的端口号在0到65535范围之间,其中1024以下的端口保留给常用的网络服务。 (1)TCP全连接扫描 源主机每次进行扫描时,都尝试与目标主机建立正常的TCP三次握手的全连接。如果能建立起三次握手,则说明三次握手所连接的目的主机的网络端口是打开的。但是,因为源主机和目标主机的TCP连接状态处于ESTABLISHED的状态,所以扫描过程容易被检测出来。 (2)TCP SYN扫描 也被称为TCP的半扫描连接。利用三次握手的前两次握手。 1.源主机向目标主机发送第一次握手的SYN数据包 2.若端口开放,则目的主机回应第二次握手的SYN和ACK标志位为1的数据包。源主机收到数据包,则发送RST标志位为1的数据包,从而拒绝和目标主机建立全连接。 若端口未开放,则目的主机发送RST标志位为1的数据包 (3)TCP FIN扫描 1.发送FIN标志位为1的数据包 2.若端口开放,则丢弃此包不进行回应 若端口未开放,则返回一个RST标志位为1的数据包 注:适用于UNIX操作系统主机,而有的操作系统无论端口是否打开,都回复RST (4)UDP 的ICMP端口不可到达扫描 利用UDP协议向目的主机的UDP端口发送探测的数据包 1.若端口打开,则不会返回确认数据包 2.当源主机向未打开UDP端口的主机发送数据包时,目标主机会返回一个ICMP_PORT_UNREACHABLE错误 (5)ICMP扫描 利用ICMP协议的性能,向目标主机发送一个协议项存在错误的IP数据包,根据反馈的ICMP错误信息判断目标主机使用的网络服务及使用的网络端口。 三、漏洞扫描 在获取了目标主机的IP、端口等信息后,攻击者下一步要扫描检测目标主机和目标网络存在的安全漏洞,以获得对目标主机的控制权限。 (1)网络漏洞扫描 针对主机和网络设备,发送漏洞探测数据包进行漏洞扫描。 (2)主机漏洞扫描 通过漏洞特征匹配技术和补丁安装信息检测来进行操作系统和应用软件系统的漏洞检测 注:主机漏洞扫描工具不具备网络扫描功能。常用的网络漏洞扫描工具包括Nessus,X-Scan,SSS,绿盟极光漏洞扫描器。具有主机漏洞扫描功能的工具包括Nessus,360安全卫士。

Latex 按引用排序后的文献列表 个别文献顺序存在错乱

Google 必应搜了一圈没发现一样问题的。 1.问题描述 有的参考文献跑到前面去了,大致顺序还是对的 2.原因:latex自动对齐,选择长度合适的文献放到前面来对齐文档末尾了。 3.解决方案:给末尾加适量空行如下,从而使得latex不用强行凑对齐 \bibliography{ref_nolink} \bibliographystyle{ieeetr} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \

fabric网络搭建

通用命令 进入终端1 docker exec -it cli1 bash 进入终端2 docker exec -it cli2 bash 退出终端 exit 关闭网络并清除配置 docker-compose down -v 命令执行顺序 通道操作 创建通道 peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem cli1加入通道 peer channel join -b mychannel.block 将区块文件复制到cli2 exit docker cp cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/mychannel.block ./ docker cp ./mychannel.block cli2:/opt/gopath/src/github.com/hyperledger/fabric/peer cli2加入通道 peer channel join -b mychannel.block 设置锚节点 组织1 peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.

黑马瑞吉外卖-菜品管理-批量删除,批量启售停售,套餐管理-修改套餐和批量启售停售

编写瑞吉外卖项目未讲解到的功能代码 菜品管理模块:批量删除和批量启售停售功能需求实现。 套餐管理模块:修改套餐,批量启售停售功能需求实现。 菜品管理模块 删除和批量删除---请求接口信息: 代码 /** * 批量删除菜品 * @param ids 需要删除的id数组 * @return 返回数据联调对象R */ @DeleteMapping public R<String> deleteIds(Long[] ids){ //将数组转为集合 List<Long> longs = Arrays.asList(ids); //批量删除 dishService.removeByIds(longs); return R.success("删除成功!"); } 启售停售和批量启售停售---请求接口信息: 代码 /** * 批量起售和停售 * @param ids 传入需要操作的id数组 * @param status 需要变更到的状态 * @return 返回数据联调对象R */ @PostMapping("/status/{status}") public R<String> updateStatus(Long[] ids,@PathVariable int status){ //将数组转为集合 List<Long> idsList = Arrays.asList(ids); //创建更新的条件构造器 LambdaUpdateWrapper<Dish> queryWrapper = new LambdaUpdateWrapper<>(); //设置修改状态和条件 queryWrapper.set(Dish::getStatus,status).in(Dish::getId,idsList); //执行更新操作 dishService.

Spring Boot框架知识总结笔记(超详细,一次性到位)狂神说SpringBoot笔记

开始就进入微服务阶段 javase:OOP MySQL:持久化 html+css+js+jquery+框架:视图,框架不熟练,css不好 javaweb:独立开发MVC三层架构的网站:原始 ssm:框架:简化了我们的开发流程,配置也开始较为复杂; 之前项目打包都是war包,程序在Tomcat中运行 spring再简化:springBoot-jar包,内嵌Tomcat;微服务架构! 服务越来越多:springCloud 1、SpringBoot简介 1.1、回顾什么是Spring 什么是Spring Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者:Rod Johnson 。 Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。 Spring是如何简化Java开发的 为了降低Java开发的复杂性,Spring采用了以下4种关键策略: 基于POJO的轻量级和最小侵入性编程,所有东西都是bean; 通过IOC,依赖注入(DI)和面向接口实现松耦合; 基于切面(AOP)和惯例进行声明式编程; 通过切面和模版减少样式代码,RedisTemplate,xxxTemplate; 1.2、什么是SpringBoot ​ 学过javaweb的同学就知道,开发一个web应用,从最初开始接触Servlet结合Tomcat, 跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架Struts,再后来是SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;你们有经历过框架不断的演进,然后自己开发项目所有的技术也在不断的变化、改造吗?建议都可以去经历一遍; 所有的技术框架的发展似乎都遵循了一条主线规律:从一个复杂应用场景 衍生 一种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡“约定大于配置”,进而衍生出一些一站式的解决方案。 是的这就是Java企业级应用->J2EE->spring->springboot的过程。 随着 Spring 不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用 Spring 、更容易的集成各种常用的中间件、开源软件; Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。 ​ 简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。

针对于selenium的一些常规配置(防检测,无头,保留自己浏览器的登录信息等)

在使用selenium的时候有时候会受到网站的检测导致我们的程序被迫中止,因此我们需要给selenium添加一些浏览器特征来防止被网站检测到**(1-4为防检测配置)**. 在给selenium添加参数的时候,我们可以使用add_argument option = webdriver.ChromeOptions() # 首先实例化一个ChromeOptions selenium添加user-agent参数 option.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36') 去除 “Chrome正受到自动化测试软件的控制” option.add_experimental_option('excludeSwitches', ['enable-automation']) 添加浏览器特征 option.add_argument("--disable-blink-features=AutomationControlled") selenium无头模式(即不会弹出浏览器来运行) option.add_argument('--headless') 保留自己浏览器的cookie信息等,让selenium操作的浏览器跟自己所使用的一样,而不是新开一个,在操作一些需要登录的网站的时候,可以直接免登陆 option.add_argument(r'--user-data-dir=C:\Users\honor\AppData\Local\Google\Chrome\User Data') 在新版的selenium中,在代码执行完之后浏览器就会自动关闭,但我们在调试的时候可能不需要它自动关闭,因此可以通过以下代码来让浏览器不自动关闭 option.add_experimental_option("detach", True) 而–user-data-dir=后面的值可以在谷歌浏览器(chrome://version/)中看到,替换为自己的即可 在最后实例化driver对象的时候,将option添加到其中即可 driver = webdriver.Chrome(options=option) 感谢您的阅读!

【微信小程序】-- 自定义组件 - 纯数据字段 & 组件的生命周期(三十六)

💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 文章目录 前言一、纯数据字段1、什么是纯数据字段2、基本语法3、使用纯数据字段改造数据监听器案例 二、组件的生命周期1、组件全部的生命周期函数2、组件主要的生命周期函数3、定义生命周期方法 总结 前言 大家好,又见面了,我是夜阑的狗🐶,本文是专栏【微信小程序开发教程】专栏的第36篇文章; 今天开始学习微信小程序的第21天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。 专栏地址:【微信小程序开发教程】, 此专栏是我是夜阑的狗微信小程序开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。 如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。 一、纯数据字段 前面通过案例完整学习了自定义组件中数据监听器的用法,以及监听指定数据和所有数据的方法。接下来就来讲解一下另外一个自定义组件 - 纯数据字段 & 组件的生命周期。上个周末连着两天没写偷懒了,一天不学习,罪恶感嘎嘎上升呀。话不多说,让我们原文再续,书接上回吧。 1、什么是纯数据字段 纯数据字段顾名思义指的是那些不用于界面渲染的 data 字段。应用场景:例如有些情况下,某些 data 中的字段既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。带有这种特性的 data 字段适合被设置为纯数据字段。 比如前面学习过数据监听器案例中,像 r, g, b 这三个值是没有必要渲染到页面上的,所以这三个适合当纯数据字段。 设置为纯数据字段有助于提升页面更新的性能。 2、基本语法 在 Component 构造器的 options 节点中,指定 pureDataPattern 为一个 正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段,示例代码如下: Component({ options: { // 指定所以 _开头的数据字段为纯数据字段 pureDataPattern: /^_/ }, /** * 组件的初始数据 */ data: { _rgb: { r: 0, g: 0, b: 0 }, // 根据 rgb 对象的三个属性,动态计算 fullColor 的值 fullColor: '0, 0, 0' }, }) 注意:纯数据字段只能用于页面逻辑的处理,不能用于页面渲染。

安全测试之xss漏洞的检测与防御

整理了一些软件测试方面的资料、面试资料(接口自动化、web自动化、app自动化、性能安全、测试开发等),有需要的小伙伴可以文末加入我的学习交流qun,无套路自行领取~ 1.xss漏洞检测方法1:手动检测 手工检测重点要考虑数据输入的地方,且需要清楚输入的数据输出到什么地方。 在检测的开始,可以输入一些敏感字符,比如“<、>、()”等,提交后查看网页源代码的变化以发现输入被输出到什么地方,且可以发现相关敏感字符是否被过滤。 手工检测结果相对准确,但效率较低。 2.xss漏洞检测方法2:工具检测 常用工具有AVWS(Acunetix Web Vulnerability Scanner)、BurpSuite等。还有一些专门针对XSS漏洞的检测工具,如:XSSer、XSSF(跨站脚本攻击框架)、BeEF(The Browser Exploitation Framework)等。 推荐两款自动检测工具: beef-xss是一个web框架攻击平台,parrot和kali等渗透测试系统,都集成beef,而且beef有很多好使的payload。 比如XSS这个漏洞,beef可以通过一段编制好的javascript控制目标主机的浏览器,通过浏览器拿到各种信息并且扫描内网信息,非常强大。 XSStrike是目前比较流行的一款xss检查工具,它只针对反射型和DOM型,对参数进行模糊测试之后构建合适的payload,使用payload对参数进行穷举匹配,内置爬虫功能,检测并尝试绕过WAF,同时支持GET及POST方式,大多数payload都是由作者精心构造,误报率极低。 3.xss漏洞防御方法 使用黑名单进行 ●对HTML标签或特殊字符进行过滤 ●使用内容安全的CSP ●使用设计上就会自动编码的框架,如:OWASP ESAPI、React JS、JSOUP等,对于JAVA而言,可以使用ESAPI.encoder().encodeForHTML()对字符串进行HTML编码。 ●对于反射型和存储型XSS,可以在数据返回给客户端浏览器时,将敏感字符进行转义,如:将单引号进行编码替换(十进制编码'、十六进制编码'、HTML编码&apos、Unicode编码\u0027等)。 ●对于DOM型XSS,可以使用上下文敏感数据编码。如:在PHP中的htmlspecialchars()、htmlentities()函 数可以将一些预定义的字符转换为HTML实体,如:小于转化为<、大于转化为>、双引号转化为"、单引号转化为&apos、与转化 为&等。 ●启用浏览器的HttpOnly特性可以组织客户端脚本访问cookie。如:在PHP中可以通过下面的代码设置cookie并启用HttpOnly。 4.XSS防御的总体思路 XSS防御的总体思路是:对用户的输入(和URL参数)进行过滤,对输出进行html编码。也就是对用户提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。 对输入的内容进行过滤,可以分为黑名单过滤和白名单过滤。黑名单过滤虽然可以拦截大部分的XSS攻击,但是还是存在被绕过的风险。白名单过滤虽然可以基本杜绝XSS攻击,但是真实环境中一般是不能进行如此严格的白名单过滤的。 对输出进行html编码,就是通过函数,将用户的输入的数据进行html编码,使其不能作为脚本运行。 如下,是使用php中的htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体 #使用htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体 $name = htmlspecialchars( $_GET[ 'name' ] ); 所有的过滤、检测、限制等策略,建议在Web Server那一端去完成,而不是使用客户端的JavaScript或者VBScript去做简单的检查。因为真正的攻击者可以绕过你精心设计制作的客户端进行过滤、检测或限制手段。 最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走: 这些资料,对于从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。希望对大家有所帮助……如果你不想再体验一次自学时找不到资料,没人解答问题,坚持几天便放弃的感受的话,可以加入下方我们的测试交流群大家一起讨论交流学习

蓝桥杯单片机开发及应用-基础模块02-蜂鸣器和继电器

一、先前知识 74HC138译码器(在基础模块01中有介绍,此处再次介绍是为了加深我们对基础芯片的印象) 74HC138译码器是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL)系列。74HC138译码器可接受3位二进制加权地址输入(A, B和C),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。 74HC138特有3个使能输入端:两个低有效(G2A和G2B)和一个高有效(G1)。除非G2A和G2B置低且G1置高,否则74HC138将保持所有输出为高。 图一、74HC138译码器模块 图二、74HC138译码器输出经或非门 图三、74HC138译码器功能表 74HC573锁存器(在基础模块01中有介绍,此处再次介绍是为了加深我们对基础芯片的印象) 74HC573锁存器是八路三态输出的非反转透明锁存器。 当锁存器使能端LE为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。当锁存器使能变低时,符合建立时间和保持时间的数据会被锁存。 图四、74HC573锁存器模块 图五、74HC573锁存器功能表 蜂鸣器模块介绍 蜂鸣器分有源蜂鸣器和无源蜂鸣器,蓝桥杯板子上使用的蜂鸣器是有源蜂鸣器。有源蜂鸣器的工作原理是直流电源输入经过振荡系统的放大取样电路在谐振装置作用下产生声音信号。由下图可知,蜂鸣器的正极接了一个 VCC 高电平,当 N_BUZZ 引脚输入高电平的时候蜂鸣器就会发出响声;输入低电平的时候蜂鸣器关闭。 图六、蜂鸣器模块 继电器模块介绍 该继电器为电磁继电器,是利用输入电路内电流在电磁铁铁芯与衔铁之间产生的吸力作用而工作。当单片机输出低电平时,也就是对继电器模块的输入引脚 N_RELAY 给低电平时,二极管的正极就是低电平了,此时二极管截止,线路没有电流流过,继电器不反应;当输入 N_RELAY 引脚给高电平时,二极管导通,内部形成电流,电磁铁铁芯“ RELAY_SPDT ”产生吸力将K1吸下来,继电器吸合。 图七、继电器模块 蜂鸣器和继电器模块原理图 图八、蜂鸣器和继电器模块原理图 二、模块控制实现过程简述 要控制LED模块,就需要先往74HC138译码器中写入二进制数100(十进制数4),输出就是Y4为低电平,经过一个或非门输出的Y4C就为高电平,再输入74HC573锁存器。再控制LED灯的点亮。 要控制蜂鸣器和继电器模块,就需要先往74HC138译码器中写入二进制数101(十进制数5),输出就是Y5为低电平,经过一个或非门输出的Y5C就为高电平,再输入74HC573锁存器。再控制蜂鸣器和继电器。 三、所要实现的功能 首先让继电器吸合一定时间后关闭,再让蜂鸣器响一定时间后关闭,然后8个LED灯以一秒为间隔闪烁两次。再让继电器吸合一定时间后关闭,让蜂鸣器响一定时间后关闭,然后依次点亮LED灯,再依次熄灭LED灯。程序循环实现上述功能。 四、代码实现 ①系统初始化-先关闭蜂鸣器和继电器,否则下载程序之后可能会乱叫 // 关闭蜂鸣器和继电器 void Init_System(void) { // 138译码器输出Y5为低电平,则输出的Y5C为高电平,573锁存器正常工作 HC138_C = 1; HC138_B = 0; HC138_A = 1; // 低电平有效 P0 = 0xaf; // 1010 1111 关闭蜂鸣器和继电器 } ②蜂鸣器模块 // 打开蜂鸣器 void Beep_Open(void) { // 138译码器输出Y5为低电平,则输出的Y5C为高电平,573锁存器正常工作 HC138_C = 1; HC138_B = 0; HC138_A = 1; // 低电平有效 P0 = 0xef; // 1110 1111 打开蜂鸣器 } ③继电器模块 // 打开继电器 void Relay_Open(void) { // 138译码器输出Y5为低电平,则输出的Y5C为高电平,573锁存器正常工作 HC138_C = 1; HC138_B = 0; HC138_A = 1; // 低电平有效 P0 = 0xbf; // 1011 1111 打开继电器 } ④延时函数 void Delay_tms( unsigned int t ) { int i; while( t-- ) { for( i=115 ; i>0 ; i-- ) { } } } ⑤LED灯、蜂鸣器和继电器功能整合 // 工作 void At_Work(void) { int i; Relay_Open(); // 继电器吸合 Delay_tms(500); Init_System(); // 关 Beep_Open(); // 蜂鸣器响 Delay_tms(500); Init_System(); // 关 LED_Init(); // 闪两下 for( i=0 ; i<2 ; i++ ) { P0 = 0x00; // 全部灯亮 Delay_tms( 2000 ); P0 = 0xff; // 全部灯灭 Delay_tms( 2000 ); } Relay_Open(); // 继电器吸合 Delay_tms( 500 ); Init_System(); // 关 Beep_Open(); // 蜂鸣器响 Delay_tms( 500 ); Init_System(); // 关 LED_Init(); // LED按顺序亮灭 for( i=1 ; i<=8 ; i++ ) // 亮 { P0 = 0xff << i; Delay_tms( 250 ); } for( i=1 ; i<=8 ; i++ ) // 灭 { P0 = ~( 0xff << i ); Delay_tms( 250 ); } } ⑥整个函数展示 #include <STC15F2K60S2.

Golang中Channel的分析与使用

一、什么是channel 我们来看《Go语言编程》中的一段话 channel是Go语言在语言级别提供的goroutine间的通信方式,是一种进程内的通信方式。 通俗点儿解释就是channel可以在两个或者多个goroutine之间传递消息。在Go中,goroutine和channel是并发编程的两大基石,goroutine用来执行并发任务,channel用来在goroutine之间来传递消息。 Do not communicate by sharing memory; instead, share memory by communicating. 不要通过共享内存来通信,而要通过通信来实现共享内存。 推荐一本书《Concurrency in Go》,这本书对golang中的并发做了深入的讲解。 二、channel的实现 1、引入概念 首先我们来看两个例子来简单看下golang中channel是如何使用的: package main import ( "fmt" ) func goroutineA(a <-chan int) { for { select { case val := <-a: fmt.Println(val) } } } func main() { ch := make(chan int) go goroutineA(ch) ch <- 3 ch <- 5 } 很简单的一段程序,初始化了一个非缓冲的channel,然后并发一个协程去接收channel中的数据,然后往channel中连续发送两个值,首先大家先理解一组概念,什么是非缓冲型channel和缓冲型channel?对,其实很简单,make时如果channel空间不为0,就是缓冲型的channel。 ch := make(chan int)//非缓冲型 ch := make(chan int, 1024)//缓冲型 如果我们将go goroutineA(ch)这行代码往下移,会发生什么?对,会报错

微信小程序如何进行反编译详细教程

前言介绍 小程序反编译,其实还是简单的,要想拿到微信小程序源码,先要拿到小程序的包,用反编译脚本跑一下,微信小程序代码包里的所有文件、所有资源就出来了(除了project.config.json小程序配置文件)。拿到源码后,跑起来是能跑,但登录、授权等涉及到appid的功能是不能用的,因为被反编译小程序的服务端appid和你本地添加的不一样,这就是为啥拉下来的源码没有project.config.json文件的原因,项目中appid是配置在这个文件里,这里一定程度上保护原小程序。 准备工具 1、nodejs环境,这是反编译脚本的运行环境,下方有地址。 2、小程序包解密工具,PC版解包无需模拟器,附件中有这个。 3、反编译脚本下载,附件中有这个。 4、微信PC端,运行小程序,自己下载电脑端微信。 操作流程 第一步:nodejs安装 安装nodejs下载链接: https://nodejs.org/zh-cn/download/ 或者 http://nodejs.cn/download/安装的过程一路next就可以了,安装后将nodejs设置为环境变量。 检查是否安装:打开cmd,测试是否安装成功,在命令行输入node -v, 结果: 第二步:在微信PC端运行需要反编译的小程序,我这边运行:,每个页面都点点。 第三步:打开小程序包解密工具,选择加密小程序包,按时间对应的第一个就是你要的小程序包,可以对一下APPID是否一致。 第四步:打开反编译脚本所在的目录,我把刚刚解出来的包wx0a43b778b69841cd.wxapkg也放在这个目录下了。 先运行以下命令: npm install esprima npm install css-tree npm install cssbeautify npm install vm2 npm install uglify-es npm install js-beautify 安装好依赖之后,就是最后一步了,反编译 .wxapkg 文件,刚刚我已经把wx0a43b778b69841cd.wxapkg 文件放入了根目录。 如果觉得以上很复杂,请使用自动化反编译工具:史上最简单的全自动微信小程序反编译工具-大师原创 所以直接运行反编译命令: node wuWxapkg.js wx0a43b778b69841cd.wxapkg 如果.wxapkg 文件在其他路径,则需要填写对应路径。 例如在D盘则: node wuWxapkg.js D:wx0a43b778b69841cd.wxapkg 到这里就反编译成功了 测试一下是否正常,我这边直接复制一个project.config.json文件,导入开发者工具 我这边是有后端的,所以运行正常: 最后说下 其实反编译一般的小程序前端都是可以的反编译的,只是部分比较复杂。 建议找没有后端的小程序反编译,因为有后端反编译了也没啥用,除非自己写后台或者使用别人接口。 本教程仅限技术交流。 ‍‍‍‍‍‍‍‍‍‍‍‍工具下载 下载地址1:如何进行反编译微信小程序详细教程-陆大湿源码 下载地址2:https://download.csdn.net/download/wapqke/86338953 最新版: 特别说明 本文由陆大湿整理自网络,如有侵权请联系客服删除! 如需转载请注明出处:陆大湿 唯一官网:bbs.ludeqi.com 1、本站所有资源均来源于互联网,不保证100%完整、

kali linux 通过粘贴板攻击对方服务器

目录 一、粘贴板中毒攻击原理 二、Pastejacker 攻击工具简介 三、安装Pastejacker 四、Pastejacker结合MSF拿到目标shell权限 一、粘贴板中毒攻击原理 该工具的主要目的是自动化攻击,将此攻击中使用的所有已知技巧收集在一个地方和一项自动化工作,因为在搜索后发现没有工具可以正确地完成这项工作方式现在因为这种攻击取决于用户将粘贴什么,将 Metasploit 网络交付模块的想法实现到工具中,所以当用户粘贴到终端时,你会在他的设备上获得 meterpreter 会话。 换句话说,当我们在自己电脑上的一个网站上复制一条看似正常的命令时,但事实上那个网站在背后偷偷的篡改了我们粘贴的内容,我以为我复制了一条正常的命令,但事实上我复制到粘贴板上的命令,却是一串恶意代码,这就是恶意的网站搭建者,他欺骗我们最终用户访问他的恶意网站,然后通过我们在他网站上的键盘和鼠标操作,将恶意的内容注入到我们本地的剪贴板当中,这种攻击方式,我们就成为粘贴劫持攻击。 二、Pastejacker 攻击工具简介 模拟剪贴板劫持对目标进行攻击。 https://github.com/D4Vinci/PasteJacker 简而言之,粘贴劫持是恶意网站用来控制您计算机的剪贴板并在您不知情的情况下将其内容更改为有害内容的一种方法。 所以在这里所做的是自动化原始攻击并添加另外两个技巧来欺骗用户,使用 HTML 和 CSS将讨论它然后添加 meterpreter 会话 三、安装Pastejacker 安装 Pastejacker 工具 git clone https://github.com/D4Vinci/PasteJacker.git 注意Kali Linux 默认安装了 Python 2.x 和 Python 3.x 版本,可以按照以下步骤在 Kali 中切换到 Python 3: sudo update-alternatives --install /usr/bin/python python /usr/bin/python2* sudo update-alternatives --install /usr/bin/python python /usr/bin/python3* 这将把 /usr/bin/python 链接到 Python 2.7 和 Python 3 之间进行切换。您可以使用以下命令来切换到 Python 3: sudo update-alternatives --config python

【C/C++专栏】cJSON的API介绍和使用

目录 前言 一,cJSON 数据类型 二,cJSON 结构体 三,创建 Json 项 四,往 JSON 项中添加数据 五,从 JSON 父项中删除 JSON 子项 六,更新 JSON 项的指定位置数据 七,拷贝 JSON 项 八,比较两个 JSON 项是否相等 九,判断当前 JSON 项的类型 十,获取当前 JSON 项的 value 值 十一,删除 JSON 项(重点) 十二,解析 JSON 项 十三,获取 JSON 项的序列化值 十四,获取当前 cJSON 版本 十五,JSON 钩子模块(了解就行) 十六,案例答疑解惑 1,测试读写的 test.json 文件内容(文件路径 E:\test.json) 2,所需要的头文件 3,写 Json 文件接口实现 4,读 Json 文件接口实现 总结 前言 cJSON 是用C语言编写的一个超轻量,可移植,单文件的 JSON 解析器,它是个开源的项目,它只有 cJSON.h 和 cJSON.c 两个文件,使用时只需要在对应的 include 和 src 目录添加进去就可以使用了,cJSON 下载地址