本文由葡萄城技术团队于博客园原创并首发。葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
作为一名优秀的打工人,Excel是大家上班中必不可少的办公软件。随着互联网时代的到来,越来越多的公司开始使用各种B/S系统来处理表格数据文件。那么有没有一种可以直接在浏览器中使用的Excel插件去处理数据呢?答案是肯定的。本文小编将为大家介绍如何在Vue框架中集成在线表格插件(以下简称为“SpreadJS”)和在线表格编辑器(类Excel浏览器插件)实现在浏览器中使用Excel插件来处理数据。
在本教程中,我们将使用node.js,请确保已安装最新版本,除此之外还需要使用软件Visual Studio Code(以下简称“VSCode”)作为编程环境,请您以管理员身份运行它。
上一篇文章(《新人必看!手把手教你如何使用浏览器表格插件(上)》)小编为大家介绍了如何在Vue框架中集成表格插件(SpreadJS),本章小编将继续为大家介绍如何在Vue中集成在线表格编辑器。
在Vue中集成在线表格编辑器:
本节内容小编将为大家介绍Vue框架中如何集成在线表格编辑器和如何实现使用编辑器实现表格数据绑定。
Vue集成在线表格编辑器和SpreadJS的方法相似,首先引入需要集成到Vue中的资源,其次使用styleInfo标签和designerInitialized设置表格的大小(使用方法与Vue集成SpreadJS一样,具体可以参考第一篇文章)。
import {defineComponent} from "Vue" // SpreadJS核心资源 import GC from "@grapecity/spread-sheets" // 形状资源 import "@grapecity/spread-sheets-shapes" // 二维码资源 import "@grapecity/spread-sheets-barcode" // 图表资源 import "@grapecity/spread-sheets-charts" // 文件IO相关资源 import "@grapecity/spread-excelio" // 打印资源 打印资源要在pdf之前 import "@grapecity/spread-sheets-print" // 导出pdf相关资源 import "@grapecity/spread-sheets-pdf" // 透视表相关资源 import "@grapecity/spread-sheets-pivot-addon" // 集算表相关资源 import "@grapecity/spread-sheets-tablesheet" // 组件运行时样式信息 import "@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css" // 组件运行时语言资源 import "@grapecity/spread-sheets-resources-zh" // 设计器资源,设计器资源要在设计器核心资源之前 import "@grapecity/spread-sheets-designer-resources-cn" // 设计器核心资源 import * as GcDesigner from "@grapecity/spread-sheets-designer" // 设计器css import "@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css" // 设计器对Vue的支持资源 import Designer from "@grapecity/spread-sheets-designer-Vue" import {bindFile} from "../files/bindFile" import {bindSchema,generateData} from "../files/bindTree.js"
(Vue引入在线表格编辑器的资源)
实现数据绑定:
为了更形象、具体的描述数据绑定,小编将用一个简单的小案例为大家介绍在SpreadJS中数据绑定是如何实现的。
实现需求:通过SpreadJS实现一个简单的苹果销售量的数据表格。数据表格中的数据可以通过数据文件实现将数据回显到数据表格中。下面是具体实现的方法步骤:
(1)设计可视化表格:
使用spreaeJs表格设计器拉拽设计出一个表格如下图所示(和Excel创建表格的方法一样,不详细介绍)。
(初始化一个Excel表格)
除了SpreadJS可视化方法创建表格之外,小编再为大家再介绍一种使用数据文件实现表格的方法:
在提供的源码资源中包含了两个数据文件bindFile.js和bindTree.js,而bindFile.js文件则是上图表格的Json文件格式,使用spread.fromJSON(bindFile)方法可以读取bindFile.js文件中的内容并显示到页面上。
const loadBindData = (spread:GC.Spread.Sheets.Workbook) => { // 加载文件(第一步) spread.fromJSON(bindFile) }
(读取bindFile.js文件的代码)
(2)创建工作表:
设计完可视化表格之后就是创建数据表来存储数据,创建工作表也可以分为可视化创建工作表和数据文件实现工作表,由于可视化设计工作表操作比较简单,小编在这里不作详细介绍。下面主要介绍如何通过代码实现数据表:使用designer的setData方法读取bindTree.js文件中的bindSchema(数据表的Json格式)并加载到SpreadJS的页面中。
//第二步绑定数据绑定表信息(designer初始化完成之后,加载右侧Tree)
designer.setData("treeNodeFromJson",JSON.stringify(bindSchema)) designer.setData("oldTreeNodeFromJson",JSON.stringify(bindSchema)) designer.setData('updatedTreeNode',JSON.stringify(bindSchema))
(实现创建工作表的代码)
(3)实现数据绑定:
设计完工作表之后,下面将介绍如何通过代码和数据文件实现数据绑定:
首先去调用bindTree.js文件中的generateData方法生成随机数据,然后使用
GC.Spread.Sheets.Bindings.CellBindingSource方法去生成绑定的数据源,再将绑定的数据源放到初始化的活动页sheet中,最后去加载数据。具体实现代码如下:
const loadBindData = (spread:GC.Spread.Sheets.Workbook) => { // 加载文件(第一步) spread.fromJSON(bindFile) //第三步绑定数据 // mock数据 let data = generateData(20) // 生成绑定数据源 let source = new GC.Spread.Sheets.Bindings.CellBindingSource(data) // 获取当前活动sheet let sheet = spread.getActiveSheet() as GC.Spread.Sheets.Worksheet // 获取sheet中的目标表格,并将表格的数据设置为随数据量自动纵向扩展 let table = sheet.tables.findByName('report_card') table.expandBoundRows(true) // 加载数据 sheet.setDataSource(source) }
(实现数据绑定的代码)
将上面的步骤代码合在一起之后的整体代码如下所示:
//绑定数据信息(第二步)
const initDesigner = (designerEntity:GcDesigner.Spread.Sheets.Designer.Designer) => { designer = designerEntity customeConfig(designer) //第二步绑定数据绑定表信息(designer初始化完成之后,加载右侧Tree) designer.setData("treeNodeFromJson",JSON.stringify(bindSchema)) designer.setData("oldTreeNodeFromJson",JSON.stringify(bindSchema)) designer.setData('updatedTreeNode',JSON.stringify(bindSchema)) let spread = designer.getWorkbook() as GC.Spread.Sheets.Workbook loadBindData(spread) } const loadBindData = (spread:GC.Spread.Sheets.Workbook) => { // 加载文件(第一步) spread.fromJSON(bindFile) //第三步绑定数据 // mock数据 let data = generateData(20) // 生成绑定数据源 let source = new GC.Spread.Sheets.Bindings.CellBindingSource(data) // 获取当前活动sheet let sheet = spread.getActiveSheet() as GC.Spread.Sheets.Worksheet // 获取sheet中的目标表格,并将表格的数据设置为随数据量自动纵向扩展 let table = sheet.tables.findByName('report_card') table.expandBoundRows(true) // 加载数据 sheet.setDataSource(source) } return{ styleInfo,initDesigner }
(整体流程的代码)
(最终效果图)
做完这些之后便可以在浏览器中体验和使用在线编辑器了(高度类似Excel操作)。
备注:
整理的完整源码附文章下方day2文件夹中的vue3-spreadJS-ts文件,直接在终端中使用npm run dev指令运行即可。
这两篇文章为大家详细的介绍了SpreadJS在Vue框架中使用的方法和具体的作用,希望可以帮助大家在学习SpreadJS的道路上可以起到帮助。
本文是由葡萄城技术开发团队发布,转载请注明出处:葡萄城官网
大家好,又见面了,我是你们的朋友全栈君。movie.py虫子#-*-coding:utf-8-*- importscrapy frommoviePro1.itemsimportMoviepro1Item classMovieSpider(scrapy.Spider): name='movie' #allowed_domains=['www.xxx.com'] start_urls=['https://www.4567tv.tv/index.php/vod/show/class/喜剧/id/1.html'] #定义通用爬虫模板: url="https://www.4567tv.tv/index.php/vod/show/class/喜剧/id/1/page/%d.html" page=1 #用于解析电影名称: defparse(self,response): print("正在爬取第{}页的电影数据....".format(self.page)) li_list=response
ServiceMeshisyetanotheremergingfancytechwordinthefieldofmicroservicesrecently.Ifyouhaveatelecommunicationornetworkingbackground,youmayhavealreadynoticedthatServiceMeshandSDN(SoftwareDefinedNetwork)looksimilar.Bothofthemuseasoftwarelayertomanageandcontrolthenetworkinfrastructure,andtheyalsosharethesamearchitecture,whichconsistsofacontrolplaneandadataplane.SowhatistherelationshipbetweenServiceMeshandSDN—IsServiceMeshthenextgenerationofSDN?WhatcanServiceMeshlearnfromtheexperienceofSDN?I’dliketoshar
阅读助手1.题目解法一:双指针解法二:remove&apeend解法三:布尔排序一个有问题的解法1.题目给定一个数组nums, 编写一个函数将所有0移动到数组的末尾, 同时保持非零元素的相对顺序。示例:输入:[0,1,0,3,12] 输出:[1,3,12,0,0]复制说明:必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。复制来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/move-zeroes/ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。解法一:双指针#基本思路: 新建一个索引指针j,原索引指针i上的值不等于0时,把值放到j索引位置上classSolution: defmoveZeroes(self,nums:List[int])->None: """ Donotreturnanything,modifynumsin-placeinstead. """ j=0 foriinrange(len(nums)): ifnums[
MakeMKV,可以用蓝光光碟和DVD制作MKV,现在可以通过Ubuntu18.04及更高版本中的Snap软件包轻松安装。Snap是在大多数Linux桌面上运行的容器化软件包。感谢DanielLlewellyn,他制作了MakeMKVSnap软件包。因此,可以通过SnappyStore或在终端中运行单个命令轻松地安装它。在Ubuntu中安装MakeMKVsnap:1、)不知道为什么,但是在Ubuntu18.04的Ubuntu软件中找不到makemkv。但是,可以通过在终端中运行单个命令来安装它(通过Ctrl+Alt+T打开终端):snapinstallmakemkv2、)还需要一个命令来连接到硬件观察接口:sudosnapconnectmakemkv:hardware-observe(可选)由于任何原因,您可以通过在终端中运行命令来轻松删除MakeMKVsnap软件包:snapremovemakemkvMakeMKVPPA:对于那些喜欢通过本地Ubuntu.deb包安装它的人来说,还有一个PPA存储库,它包含了所有当前Ubuntu版本的软件。您可以简单地打开终端,运行3个命令,一个接一
当视频流不能在浏览器直接进行播放时,可以使用ffmpeg进行转码,如何利用ffmpeg拉RTSP流转推RTMP服务器,实现内网视频上互联网?脚本命令如下:ffmpeg.exe–irtsp地址-vcodeccopy-acodeccopy-fflvrtmp地址下面我们借助EasyDSS做个具体测试。EasyDSS是一个RTMP服务器,官网测试地址为:http://demo.easydss.com:10080/;默认的用户名和密码为admin/admin。在直播管理页面中,我们新建一个直播间,如下图:然后拿到推流地址如下:rtmp://demo.easydss.com:10035/hls/TestFFMPEG?sign=GGmav6wGg接下来我们实际测试上面的脚本命令功能:ffmpeg-irtsp://admin:****@183.234.***.90:3**/Streaming/Channels/201-vcodeccopy-acodeccopy-fflvrtmp://demo.easydss.com:10035/hls/TestFFMPEG?sign=GGmav6wGgVLC查看RTS
在使用Discourse进行服务的时候,很多人可能会希望安装一些广告服务。对Discourse的广告服务来说还是可以的,因为广告服务的位置不是非常影响阅读。这篇文章将会描述如何在Discourse中提供广告服务。安装插件Discourse的GoogleAdsense广告服务是使用插件进行安装的。安装插件的方法,请参考:InstallPluginsinDiscourse-admins-DiscourseMeta页面中的内容。有关启用广告服务的文章,请参考页面:OfficialAdvertising/AdPluginforDiscourse-plugin-DiscourseMeta中的内容。广告服务的源代码,请参考:GitHub-discourse/discourse-adplugin:OfficialDiscourseAdvertisingPlugin.Install&StartServingAdsonYourDiscourseForum代码仓库。安装代码根据提示,你首先需要添加插件代码,然后对Discourse进行重编译。编辑app.yml文件,如果你有多个仓库,你可以进行添加
作为程序猿的我有哪些插件,今天就给大家展示一下我作为后端程序猿使用到的Chrome浏览器插件,先说一下Chrome浏览器为什么那么强大,就是因为这个浏览器有着成百上千的浏览器插件,造就了Chrome浏览器的成功。1、Infinity谷歌应用商店直达安装地址这是一款标签页插件,我使用Chrome浏览器的时候就开始使用这个插件,注册后可以使用Pro版本,它具有多种搜索引擎设计及类似书签页的功能,非常的实用,可以看一下我之前写的介绍Infinity插件的文章:2、Tampermonkey谷歌应用商店直达安装地址Tampermonkey(油猴)是一款针对于浏览器运行脚本的插件,这个可以说是一款神器,一款必装的浏览器插件,因为在如今的互联网环境中,往往不能搜索或者看到自己想要的东西,安装了这个插件,可以去脚本市场greasyfork去下载自己想要的插件,非常实用。在这里给大家推荐两个常用的脚本:AC-baidu重定向优化百度搜狗谷歌搜索;破解VIP会员视频集合。3、Wappalyzer谷歌应用商店直达安装地址Wappalyzer是一个跨平台实用程序,可发现网站上使用的技术。它检测内容管理系统,电
什么是线程池把线程进行池化,调用的时候直接去池里面去取,而不是每次去重新创建,不用的时候放回线程池,而不是直接销毁,从而达到复用。为什么使用线程池①复用线程,降低创建以及销毁导致的资源消耗。②提高响应速度。③提高线程的可管理性,提升系统稳定性。ThreadPoolExecutorJDK提供的线程池 ThreadPoolExecutor的构造方法有七个参数intcorePoolSize核心线程数intmaximumPoolSize约定的线程最大数量longkeepAliveTime线程空闲的时候存活多久(但会保留核心线程数的线程数量)TimeUnitunit时间单位BlockingQueue<Runnable>workQueue线程超过核心线程数的部分放到阻塞队列中ThreadFactorythreadFactory线程工厂主要是给线程命名RejectedExecutionHandlerhandler拒绝策略缺省策略RejectedExecutionHandler是一个接口,JDK提供了四种实现,如果都不合适,可以自己实现这个接口去处理。DiscardOldestPolicy
协作翻译原文:Go:theGood,theBadandtheUgly链接:https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/译者:Tocy,琪花亿草,凉凉_,kevinlinkai,Tot_ziens,边城作者语:我对Go又爱又恨。Go有点像一个朋友,你喜欢和他在一起,因为他很有趣,但是当你想要进行更深入的对话时,你会觉得无聊或痛苦,而且你不想与他去一起度假。Go确实有一些不错的特性,也就是本文中提到的“好”的部分,但是当我们不将它用于API或者网络服务器(这是为它设计的),而是将它用于业务领域逻辑的时候,它看起来比较糟糕。即使是用于网络编程,它在设计和实现方面也有很多缺陷。最近我开始用Go做一个“兼职”项目,因此我用这篇文章总结一下我使用Go的体验。我希望这个博客已经让你了解到了一些关于Go的你曾经没意识到的问题,这样你就可以避免陷阱而不会被陷进去!背景我喜欢静态类型语言。我的第一个重要项目是用Pascal编写的。在90年代初我开始工作之时,我使用了Ada和C/C++,后来我迁移到了Java,最后又使用了Scala(在期间还
环境:RHEL5.4+Oracle10.2.0.4 目的:在本机将数据库升级到11.2.0.4之前总结的Oracle数据库异机升级:http://www.cnblogs.com/jyzhao/p/4813324.html 本文简单总结下在本机升级的大体步骤,和异机升级的不同点,及需要注意的地方。下面为主要步骤:新路径安装11.2.0.4软件临时生效11g软件环境变量脚本创建必须的目录10g库升级前检查备份10g数据库升级10g数据库到11g1.新路径安装11.2.0.4软件比如我这里10.2.0.4是/opt/app/oracle 11.2.0.4就选择安装到/opt/app/oracle11 即$ORACLE_BASE就不一样。2.临时生效11g软件环境变量脚本viora11.envexportORACLE_BASE=/opt/app/oracle11 exportORACLE_HOME=/opt/app/oracle11/product/11.2.0/dbhome_1 exportORACLE_SID=vas exportPATH=$ORACLE_HOME/bin:$PATH复制需
<inputstyle="float:right;margin-right:50px;margin-bottom:10px;margin-top:0px;"data-toggle="modal"data-target="#updatePassword"class="btnbtn-primary"type="button"value="修改密码"/> <!--模态框(Modal)--> <divclass="modalfade"id="updatePassword"tabindex="-1"role="dialog"aria-labelledby="myModalLabel"aria-hidden="true"> <divclass="modal-dialog"> <divcla
温馨提示注:本公众号纯属个人公益公众号!不存在任何收费项目!免费分享所有学习资料!只求大家多多支持!多多关注!!作者:CSU_Dennis 链接:https://blog.csdn.net/dennis_wu_/article/details/73437097作用:SSM框架是springMVC,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层。使用springMVC负责请求的转发和视图管理。spring实现业务对象管理,mybatis作为数据对象的持久化引擎。原理:SpringMVC:1.客户端发送请求到DispacherServlet(分发器)2.由DispacherServlet控制器查询HanderMapping,找到处理请求的Controller3.Controller调用业务逻辑处理后,返回ModelAndView4.DispacherSerclet查询视图解析器,找到ModelAndView指定的视图5.视图负责将结果显示到客户端Spring:我们平时开发接触最多的估计就是IOC容器
背景: computenode上安装openstack-nova-compute.service后,启动服务,在controller看不到compute的nova-compute 分析: 1、computenode上,查看openstack-nova-compute.service状态,发现服务无法启动 2、查看log日志(/var/log/nova/nova-compute.log),发现几处错误 错误一: 解决方法:关闭controller的防火墙 systemctlstopfirewalld.service systemctldisablefirewalld.service 错误二: 错误原因: ocata版本中,部署nova开始使用novacell,需要配置placement。官方配置中未增加placement的配置项 解决方法: ##controllernode## yuminstallopenstack-nova-placement-api-y.admin-openrcopenstackservicecreate--nameplacement--descrip
项目中,我须要PopupWindow的时候特别多,这个东西也特别的好使,所以我今天给大家写一款PopupWindow仿微信弹出效果。这样大家直接拿到项目里就能够用了!首先让我们先看效果: 那么我首先先看下布局代码很easy:例如以下 <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pop_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/bg_pulish" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/btn_hand" android:layout_width="fill_parent" android:layout_height="wrap_co
**基数排序** 核心思想: 对排序数据进行个位、十位、百位...的拆分(类似于桶排序的分组),先对个位比较排序,排完后再对十位比较排序,直到比较的位数大于最大值时,返回结果。 letarr=[1,-8,6,-50,34,15,-12,42,48,30,11]; letarrMin=Math.min(...arr);//获取当前数据最大值 letarrMax=Math.max(...arr);//获取当前数据最小值 letarr_=[];//每阶段比较后临时存储排序 letremainder=10;//取余 letinteger=1;//取整 for(leti=0;i<arr.length;i++){//先对数据进行负数取正操作(方便后面进行比较排序) arr[i]=arr[i]-arrMin; } for(letj=10;j<(arrMax-arrMin)*10;j*=10,remainder*=10,integer*=10){//判断阶段循环结束,即:数组最大数为80,那么位数判断一定为十位,不可能到百位 for(leti=0;i<arr.lengt
今天来分析server模块的master,MasterServer类 /* *LicensedtotheApacheSoftwareFoundation(ASF)underoneormore *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distrib
抓取csdn论坛 实现功能 获取论坛分类所有链接,并拼接成推荐精华页的完成的链接 获取推荐精华页的帖子状态,赏分,帖子标题,作者,发布时间,回复量,查看量,最后发表时间 置顶内容不爬取,只打印置顶内容的帖子标题,作者信息和帖子链接 跳过没有内容的版块,并打印出来 把获取到的内容添加到数据库 未实现功能 获取非技术论坛时遇到一个讨论帖子,前面没有帖子状态,出现index下标异常 未爬取推荐精华页的所有帖子(只实现了第一页的爬取) 未爬取帖子内容(帖子发布的内容和回复信息等等) 未爬取发帖人的个人信息(排名,发帖数,回帖数,结帖率等等) 总结: python的很多基础方法不知道 字符串操作不熟练 xpath语法不熟练 peewee很多方法不知道 马虎,判断帖子有没有内容时,后面忘加一个方法导致运行错误,找了半个多小时才找到 未实现功能应该都能解决,只是嫌麻烦 """ 抓取 解析 存储 """ importre importast fromurllibimportparse importrequests
前言 公司绩效里面写了要学习docker,其实平时用也会用,但是没有系统的认知。 考虑到这个东西除了工作外,NAS和单子都有用到,就系统学一学吧。 下面是学习一本叫《第一本Docker书》的笔记。 另外因为成书的时间较早,需要一些外围的资料补充才能跑现在的docker。 目标1:把单子的project打包到docker 目标2:把书看完 嗯,开始吧~ PS1:下面的所有操作都是基于Ubuntu的,缅怀一下已经没了的Centos~ PS2:其实如果是用管理员登入的话就免去好多的sudo了~ 一.Docker简介 Docker优点 提供一个简单、轻量的建模方式 职责的逻辑分离 快速、高效的开发生命周期 鼓励使用面向服务的架构 Docker架构 镜像是构建Docker世界的基石。 镜像是Docker生命周期中的构建或打包阶段,而容器则是启动或执行阶段。 Docker借鉴了标准集装箱的概念,不同的是:集装箱运输货物,而Docker运输软件。 镜像是分层的,你可以对其进行迅速的迭代。 二.Docker安装 写在最开始 下面是按照书上所说的做,最后是不行的,想要速
Given s1, s2, s3,findwhether s3 isformedbytheinterleavingof s1 and s2. Forexample,Given:s1 = "aabcc",s2 = "dbbca", When s3 = "aadbbcbcac",returntrue.When s3 = "aadbbbaccc",returnfalse. 思路:动态规划,dp[i][j]表示s1[0...i]和s2[0...j]是否满足s3[i+j]匹配的要求。 初始条件:dp[0][0]=true; 状态转移方程:dp[i][0]=(dp[i-1][0]&&s1[i-1]==s3[i-1])、dp[0][j]=(dp[0][j-1]&&s2[j-1]==s3[j-1]);dp[i][j]=(dp[i-1][j]&&(s1[i-1]==s3[i+j-
项目地址; 如果觉得有帮助,希望大家给个star鼓励以下;同时也希望大家多多fork,一起加入进来。 为什么选择做这个开源项目 首先,希望提高自己;因为选择做这个,自己肯定就会花时间去提高自己的技术,多看技术书籍,多在项目中进行实践。 其次,想让自己坚持做一件有意义的事情;因为我想在Github上靠自己的努力维护一个万级别star的项目,我会一直努力去做好这件事情。 最后,希望成为一个真正的geek;爱技术,爱开源,爱看书,爱生活。 JavaInterview的组成 JVM篇 该篇主要总结JVM底层的知识,包括运行时数据区域、垃圾回收器、垃圾回收算法等。 Java8篇 该篇总结Java8新特性,比如StreamAPI、lambada表达式、默认方法以及新的类的更新。 数据结构篇 该篇总结Java里面数据结构的知识,比如:List、Set、Map、ThreadPool等。 代码篇 该篇主要总结面试代码题相关的知识,主要包括leetcode、以及一些网站上收集的面试题的讲解。 Lock篇 该篇主要总结Java锁方面的知识,包括Java里面各种锁的实现原理和源码分析。 IO篇 总结Java