java导出pdf文件

  • 一、介绍
  • 二、准备
  • 三、实现效果
  • 四、代码

一、介绍

上一篇文章(java使用freemarker操作word(携带动态表格,图片))https://blog.csdn.net/weixin_45853881/article/details/129298494

紧跟上文,现在不仅需要word,而且还要pdf
在这里插入图片描述

二、准备

导入依赖,这里使用iText 5没有使用iText 7的,追求快点写,至于iText 7,下次一定

<!-- iText 5核心库-->
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.2.0</version>
</dependency>
<!--字体-->
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>

三、实现效果

所有图片均来源于网络,两个表格使用不同的方法进行写的,水印透明度和颜色可以调节,水印页码也可以调整
刚加入了水印设置,懒得截图了也,代码里面有
在这里插入图片描述
在这里插入图片描述

四、代码

这里把代码都贴上来了,就把一下操作隐藏了,替换为了手敲,先上代码,后展示样式

package com.wy;import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.wy.tools.Staff;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;public class demo1 {public static void main(String[] args) {try {generatePDF();} catch (Exception e) {e.printStackTrace();}}// 生成 pdfpublic static void generatePDF() throws Exception{//临时文件目录String name = "检查报告-" + UUID.randomUUID();FileOutputStream fos = new FileOutputStream("C:\\Users\\admin\\Downloads\\" + name + ".pdf");// 服务器对客户端的HTTP请求的响应对象// HttpServletResponse response// ServletOutputStream os = response.getOutputStream();//新建文档Document document = new Document();// 将内存中的 PDF 文档内容转换为二进制数据,处理流PdfWriter writer = PdfWriter.getInstance(document, fos);writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);writer.setPageSize(PageSize.A4);// 注册页码事件writer.setPageEvent(new PageNumberEvent());// 注册水印事件writer.setPageEvent(new WatermarkEvent());// 打开文档document.open();// 首页part1(document,writer);// 总览页(表格1)document.newPage();part2(document);//内容第一页(表格2)document.newPage();part3(document);// 查看页码设置生效了没document.newPage();Paragraph con = new Paragraph(" ");document.add(con);// 关闭文档document.close();}// 首页 封面public static void part1(Document document, PdfWriter writer) throws Exception{// pdf首页据上方默认无限边界,所有先设置一个空的 好调整位置,不设置空的也可以,使用时间那里的绝对定位进行设置// 获取页面尺寸信息(A4默认宽595f,高842f,可根据实际调整)float pageWidth = document.getPageSize().getWidth();float pageHeight = document.getPageSize().getHeight();// 计算居中的坐标(x为页面水平中心)float centerX = pageWidth / 2;// 空白占据Paragraph blank = new Paragraph(" "); //有空格,证明有内容,才可以进行设置间距blank.setSpacingBefore(10f); // 上方留出10磅的间距blank.setSpacingAfter(10f); // 下方留出10磅的间距document.add(blank);//logoParagraph logo = new Paragraph();Image image;try {image = Image.getInstance("https://img-home.csdnimg.cn/images/20201124032511.png");} catch (Exception e) {image = createBlankImage();}image.scaleToFit(100, 100); // 调整图片大小// 方法作用是创建一个包含图像的文本块 最后一个参数:是否调整行高以适应图像, 设置为ture之后上一步设置的scaleToFit需要等比设置才生效(例如image.scaleToFit(100, 100);会生效100,image.scaleToFit(200, 100);也会生效100)logo.add(new Chunk(image, 18, 0, true));Chunk textChunk = new Chunk("CSND", getFont(12, Font.BOLD));textChunk.setCharacterSpacing(-2f); //字符间距logo.add(textChunk);logo.setSpacingBefore(2f);logo.setIndentationLeft(19f); //左方缩进document.add(logo);//标题Paragraph title = new Paragraph();title.add(new Chunk("XXX用户", getFont(28,Font.BOLD)));title.add(Chunk.NEWLINE);title.add(new Chunk("文章检测报告", getFont(28,Font.BOLD)));title.setLeading(0, 2.8f);title.setAlignment(Element.ALIGN_CENTER);title.setSpacingBefore(49f); // 上方留出49磅的间距document.add(title);// 底部时间float bottomY = 130f;ColumnText ct = new ColumnText(writer.getDirectContent());Paragraph time = new Paragraph();time.add(new Chunk("官方检测", getFont(18,Font.BOLD)));time.add(Chunk.NEWLINE);time.add(new Chunk("二〇二五年七月二十九日", getFont(18,Font.BOLD)));time.setLeading(0, 1.8f);time.setAlignment(Element.ALIGN_CENTER);ct.setSimpleColumn(centerX - 200f, //左侧bottomY, //下方centerX + 200f, //右边bottomY + 100f //上边);ct.addElement(time);ct.go();}// 总览页public static void part2(Document document) throws Exception {Paragraph blank = new Paragraph(" ");blank.setSpacingAfter(10f);document.add(blank);Paragraph title = new Paragraph();title.add(new Chunk("xxx用户", getFont(18, Font.BOLD)));title.add(new Chunk("检测认证", getFont(18, Font.BOLD)));title.setAlignment(Element.ALIGN_CENTER);title.setSpacingAfter(10f);document.add(title);Paragraph content = new Paragraph();content.add(new Chunk("受xxx委托,xxx官方对xxx用户信息进行审核。",getFont(16, Font.NORMAL)));content.setLeading(0, 2.4f); //设置段落的行间距// 设置首行缩进(约2个中文字符,假设16号字体下1个字符≈16磅)content.setFirstLineIndent(32f);content.setSpacingAfter(10f);document.add(content);// 创建一个2列的表格PdfPTable table = new PdfPTable(2);table.setWidthPercentage(90); // 可以减少宽度以避免边缘挤压,根据实际需要设置// 定义表格各行的单元格内容,按顺序添加String[][] cellTexts = {{"检查时间:2025.5.29"},{"检查渠道:", "CSDN"}, // 第二行第二列将合并到第三行{"检查官方:", ""},  // 第三行第二列留空(已被合并){"图片1:",""}, // 合并单元格,使用单元格的值,在进行附加{"",""},};for (int i = 0; i < cellTexts.length; i++) {String[] rowTexts = cellTexts[i];for (int j = 0; j < rowTexts.length; j++) {String cellText = rowTexts[j];// 跳过已被合并的单元格 第三行第二列  第四行第二列if ((i == 2 || i == 3) && j == 1) {continue;}PdfPCell cell;// 处理需要插入图片的单元格if (i == 3  || i == 4) { //4行和第5行try {Paragraph paragraph = new Paragraph();Image image;if (i == 3) { //第四行合并了paragraph.add(new Chunk(cellText, getFont(14, Font.NORMAL)));paragraph.add(Chunk.NEWLINE);try {image = Image.getInstance("https://pics2.baidu.com/feed/e824b899a9014c08c4754f93412bd5037bf4f412.jpeg");} catch (Exception e) {image = createBlankImage();}image.scaleToFit(100, 100); // 调整图片大小paragraph.add(new Chunk(image, 0, 0, true));cell = new PdfPCell();cell.addElement(paragraph);} else { //第五行有两个if (j == 0) {paragraph.add(new Chunk("图片2:", getFont(14, Font.NORMAL)));paragraph.add(Chunk.NEWLINE);try {image = Image.getInstance("https://pics2.baidu.com/feed/7e3e6709c93d70cf8e1b7905b58c060bbba12bb5.jpeg");} catch (Exception e) {image = createBlankImage();}// 设置图片属性image.scaleToFit(100, 100); // 缩放图片以适应单元格cell = new PdfPCell();cell.addElement(paragraph);paragraph.add(new Chunk(image, 0, 0, true));} else {try {image = Image.getInstance("https://pics6.baidu.com/feed/d833c895d143ad4b000f8b7dce528da4a50f06c2.jpeg");} catch (Exception e) {image = createBlankImage();}// 设置图片属性image.scaleToFit(100, 100); // 缩放图片以适应单元格image.setAlignment(Image.ALIGN_CENTER); // 图片居中// 创建包含图片的单元格cell = new PdfPCell(image, true); // 第二个参数true表示拉伸图片以填满单元格}}} catch (Exception e) {// 图片加载失败时,使用文本替代cell = new PdfPCell(new Phrase("图片加载失败", getFont(14, Font.ITALIC)));e.printStackTrace();}} else {// 普通文本单元格cell = new PdfPCell(new Phrase(cellText, getFont(14, Font.NORMAL)));}// 第一行合并两列if (i == 0) {cell.setColspan(2); // 合并两列cell.setHorizontalAlignment(Element.ALIGN_LEFT); // 左对齐}// 第二行第二列:合并两行if (i == 1 && j == 1) {cell.setRowspan(2); // 合并下面一行}if (i == 3) {cell.setColspan(2); // 合并两列cell.setHorizontalAlignment(Element.ALIGN_LEFT); // 左对齐}// 设置单元格内边距cell.setPadding(5);// 设置单元格内容垂直居中cell.setVerticalAlignment(Element.ALIGN_MIDDLE);cell.setHorizontalAlignment(Element.ALIGN_CENTER);table.addCell(cell);}}// 将表格添加到文档document.add(table);}// 内容页public static void part3(Document document) throws Exception{Paragraph title = new Paragraph();title.add(new Chunk("情况汇总表", getFont(18,Font.BOLD)));title.setAlignment(Element.ALIGN_CENTER);title.setSpacingAfter(20f);document.add(title);// 创建一个5列的表格PdfPTable table = new PdfPTable(5);table.setWidthPercentage(100); // 可以减少宽度以避免边缘挤压,根据实际需要设置table.setHorizontalAlignment(Element.ALIGN_CENTER); //表格水平居中// 设置表格列宽比例float[] columnWidths = {1f, 4f, 3f,4f,3f};table.setWidths(columnWidths);// 添加表头String[] headers = {"序号", "姓名", "年龄","职位","图片"};for (String header : headers) {PdfPCell cell = new PdfPCell(new Phrase(header, getFont(12,null)));cell.setHorizontalAlignment(Element.ALIGN_CENTER); //表头水平居中cell.setPadding(5);table.addCell(cell);}// 后续替换为接口对接查询List<Staff> list = new ArrayList<>();list.add(new Staff("1","张三","30","软件工程师","https://n.sinaimg.cn/sinakd20106/384/w2048h1536/20250517/64b2-bd7d404c74b6c162844f652af698d98e.jpg"));list.add(new Staff("2","李四","28","产品经理","https://img1.baidu.com/it/u=1520272912,1660814288&fm=253&fmt=auto&app=138&f=JPEG"));list.add(new Staff("3","王五","26","UI设计师","https://www.vipyl.com/user/webimg/2018123/20181231718374.jpg"));for (Staff staff : list) {addDataCell(table, staff.getId(), getFont(12,null));addDataCell(table, staff.getName(), getFont(12,null));addDataCell(table, staff.getAge(), getFont(12,null));addDataCell(table, staff.getWork(), getFont(12,null));Image image;try {image = Image.getInstance(staff.getPic());} catch (Exception e) {image = createBlankImage();}image.scaleToFit(100, 100);PdfPCell imageCell = new PdfPCell(image, true);imageCell.setHorizontalAlignment(Element.ALIGN_CENTER); // 图片水平居中imageCell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 图片垂直居中imageCell.setPadding(5);table.addCell(imageCell);}// 将表格添加到文档document.add(table);}// 添加数据单元格的辅助方法private static void addDataCell(PdfPTable table, String data, Font font) {PdfPCell cell = new PdfPCell(new Phrase(data, font));cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中cell.setPadding(5);table.addCell(cell);}// 图片获取失败处理 创建空白图像private static Image createBlankImage() {try {BufferedImage blankImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(blankImage, "PNG", baos);return Image.getInstance(baos.toByteArray());} catch (Exception e) {throw new RuntimeException("创建空白图像失败", e);}}// 字体设置public static Font getFont(Integer size,Integer type) throws Exception {if (size == null) size = 12;if (type == null) type = Font.NORMAL;BaseFont bf = BaseFont.createFont("STSong-Light",     // 字体名称(宋体)"UniGB-UCS2-H", // 字符编码(简体中文)BaseFont.NOT_EMBEDDED    // 不嵌入字体(依赖系统字体));Font font = new Font(bf, size, type);font.setColor(BaseColor.BLACK);font.setSize(size);return font;}// 页码事件类public static class PageNumberEvent extends PdfPageEventHelper {@Overridepublic void onEndPage(PdfWriter writer, Document document) {// 跳过首页(页码为1时不显示)if (writer.getPageNumber() == 1 || writer.getPageNumber() == 2) {return;}PdfContentByte cb = writer.getDirectContent();try {// 设置字体,使用支持中文的字体(仍需设置,避免其他内容乱码)Font font = getFont(10, Font.NORMAL);// 设置字体到内容字节cb.setFontAndSize(font.getBaseFont(), font.getSize());// 计算页码位置(底部居中)// 从第3页开始,显示实际页码-2(如第3页显示1,第4页显示2)String pageNumber = String.valueOf(writer.getPageNumber() - 2);float x = (document.left() + document.right()) / 2;float y = document.bottom() - 15; // 设置底部
//                float y = document.top(); // 设置顶部// 添加页码cb.beginText();cb.setTextMatrix(x, y);cb.showTextAligned(Element.ALIGN_CENTER, pageNumber, x, y, 0);cb.endText();} catch (Exception e) {e.printStackTrace();}}}// 水印事件类public static class WatermarkEvent extends PdfPageEventHelper {@Overridepublic void onEndPage(PdfWriter writer, Document document) {// 跳过首页(页码为1时不显示水印)if (writer.getPageNumber() == 1) {return;}PdfContentByte canvas = writer.getDirectContentUnder();try {// 设置水印字体Font font = getFont(12, Font.BOLD);// 设置水印文本String watermarkText = "CSDN检测报告";// 获取页面尺寸Rectangle pageSize = document.getPageSize();float width = pageSize.getWidth();float height = pageSize.getHeight();// 设置水印颜色和透明度canvas.saveState();// 创建 PdfGState 对象并设置透明度PdfGState gs = new PdfGState();gs.setFillOpacity(0.5f); // 填充透明度(0-1之间,0完全透明,1完全不透明)canvas.setGState(gs); // 将透明度应用到画布canvas.setRGBColorFill(200, 200, 200); // 灰色canvas.setFontAndSize(font.getBaseFont(), font.getSize());canvas.setTextMatrix(0, 0);// 设置水印旋转角度float angle = 30;// 计算水印位置并添加多个水印for (float y = -height / 2; y <= height * 1.5; y += 420) {for (float x = -width / 2; x <= width * 1.5; x += 300) {canvas.showTextAlignedKerned(Element.ALIGN_CENTER,watermarkText,x + width / 2,y + height / 2,angle);}}canvas.restoreState();} catch (Exception e) {e.printStackTrace();}}}}

实体类,水点字,就不写在同一个类下了

package com.wy.tools;public class Staff {private String id;private String name;private String age;private String work;private String pic;// 无参构造方法public Staff() {}// 有参构造方法public Staff(String id, String name, String age, String work, String pic) {this.id = id;this.name = name;this.age = age;this.work = work;this.pic = pic;}// Getter 和 Setter 方法public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getWork() {return work;}public void setWork(String work) {this.work = work;}public String getPic() {return pic;}public void setPic(String pic) {this.pic = pic;}// 重写 toString 方法@Overridepublic String toString() {return "Study{" +"id='" + id + '\'' +", name='" + name + '\'' +", age='" + age + '\'' +", work='" + work + '\'' +", pic='" + pic + '\'' +'}';}
}

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

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

相关文章

【dropdown组件填坑指南】鼠标从触发元素到下拉框中间间隙时,下拉框消失,怎么解决?

开发dropdown组件填坑之hideDelay 引言 在开发下拉菜单&#xff08;dropdown&#xff09;或弹出框&#xff08;popover&#xff09;组件时&#xff0c;一个常见的用户体验问题就是鼠标移出触发区域后&#xff0c;弹出内容立即消失&#xff0c;这会导致用户无法移动到弹出内容上…

Linux I/O 函数完整清单

Linux I/O 函数完整清单 1. 基础 I/O 函数 1.1 基本读写 #include <unistd.h>ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count);1.2 位置指定读写 #include <unistd.h>ssize_t pread(int fd, void *buf, siz…

面经——电子电路技术知识详解

电子电路技术知识详解 目录 德摩根定律周期性矩形波产生方法自激振荡器原理与设计晶体管温度效应分析反向饱和电流影响因素放大电路负反馈类型判断正弦波90相移电路直接耦合放大器的缺点二阶有源低通滤波器分析开关电源与线性电源对比 德摩根定律 德摩根定律&#xff08;De …

docker 安装 gitlab

null文章浏览阅读445次。问题&#xff1a;运行 docker run hello-world 报错。原因&#xff1a;原镜像源网络不稳定。https://blog.csdn.net/sszdzq/article/details/145733419 镜像获取 在线下载 docker pull gitlab/gitlab-ce:17.11.1-ce.0 离线获取 创建运行 sudo docke…

PHP中的日期/时间处理之Carbon组件

日常开发中&#xff0c;我们会经常用到日期和时间的操作&#xff0c;但官方的一般操作比较复杂&#xff0c;需要大量的时间进行格式化问题和大量计算等等。Carbon组件 可以帮助我们在 PHP 开发中处理日期/时间变得更加简单、更语义化&#xff0c;从而使得我们的代码更容易阅读和…

学习嵌入式第十八天

文章目录1.数据结构1.概念2.衡量代码质量和效率1.时间复杂度2.空间复杂度3.数据结构分类1.逻辑结构2.存储结构3.常见的数据结构2.链表1.与顺序表的区别2.链表分类1.单向链表1.定义链表节点类型2.空链表的创建3.链表的头插法4.链表的遍历5.链表元素删除3.makefile习题1.数据结构…

基于SpringBoot+Vue实现校园商铺系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参…

从资源闲置到弹性高吞吐,JuiceFS 如何构建 70GB/s 吞吐的缓存池?

AI 模型的训练与推理对存储系统提出了极为严苛的要求&#xff0c;特别是在高吞吐、高并发以及对海量小文件的高效处理方面&#xff0c;已成为三大主要挑战。尽管基于 Lustre 或 GPFS 的并行文件系统具备出色的性能&#xff0c;但其成本高昂、吞吐能力与容量强耦合&#xff0c;可…

提升JVM性能之CMS垃圾回收器的优化分析与案例剖析

这里写目录标题一、CMS基本介绍二、CMS核心优化策略1. 避免并发模式失败&#xff08;Concurrent Mode Failure&#xff09;2. 减少内存碎片3. 调优并发阶段耗时4. 新生代优化配合三、典型案例解析案例1&#xff1a;电商服务频繁Full GC案例2&#xff1a;金融交易系统碎片导致长…

Token系列 - 再谈稳定币

相关政策 2024年12月&#xff0c;欧洲《加密资产市场监管法案》正式成为法律2025年3月&#xff0c;日本细化了加密资产及稳定币的监管调整2025年5月&#xff0c;英国发布了关于稳定币发行、加密资产托管及加密资产公司财务稳健性的监管提案&#xff1b;2025年5月20日&#xff…

【20min 急速入门】使用Demucs进行音轨分离

创建环境 conda create --name mujica python3.10下载加速依赖 先用nvidia-smi检查机器使用的独显版本, 然后从pytorch官网下载对应的GPU版torch, torchaudio 比如我的是12.2, 就下载11.8版本的 pip3 install torch torchvision torchaudio --index-url https://download.p…

字节Seed发布扩散语言模型,推理速度达2146 tokens/s,比同规模自回归快5.4倍

用扩散模型写代码&#xff0c;不仅像开了倍速&#xff0c;改起来还特别灵活&#xff01;字节Seed最新发布扩散语言模型Seed Diffusion Preview&#xff0c;这款模型主要聚焦于代码生成领域&#xff0c;它的特别之处在于采用了离散状态扩散技术&#xff0c;在推理速度上表现出色…

海洋大地测量基准与水下导航系列之九我国海洋PNT最新技术进展(下)

三、海洋PNT技术装备研发与工程化应用 1.海底基准装备 研制了首批适应海洋环境的多型海底基准站装备&#xff0c;在我国南海海域成功布设了定位精度优于0.25m的海底大地测量试验基准网&#xff0c;实现了我国海底大地测量基准技术零的突破。基准方舱具备稳固、抗压、防腐、防…

入门MicroPython+ESP32:安装逗脑IDE及驱动

本篇文章将手把手带大家入门MicroPython ESP32&#xff0c;重点介绍逗脑IDE的安装过程以及相关驱动的安装。 一、下载逗脑IDE 要开始使用逗脑IDE&#xff0c;首先需要从官网下载最新版本。请访问以下网址进行下载&#xff1a;https://www.itprojects.cn/ide 下载时的界面大…

CentOS上部署Redis及其哨兵(Sentinel)模式

架构&#xff1a;说明我这里是伪集群的&#xff0c;redis 在同一台机器&#xff0c;Sentinel 只有一个&#xff0c;也存在单点故障问题只能当作开发环境使用&#xff0c;要满足生产至少是下面这种架构 ------------------- ------------------- ------------------- …

《软件测试与质量控制》实验报告二 单元测试

目 录 一、实验学时 二、实验目的 三、实验环境 &#xff08;一&#xff09;硬件环境&#xff1a; &#xff08;二&#xff09;软件环境&#xff1a; 四、实验内容 1、实验方案&#xff1a; 2、实验步骤&#xff1a; 3、设计思路&#xff1a; 1、安装JUnit和Eclemma…

k8s模式部署PolarDB-X

当前文档适配PolarDB-X V2.4.0 版本 环境描述&#xff1a; 部署机&#xff08;ops&#xff09;1x2.2x.2x8.116&#xff0c;部署机需要可以访问互联网。使用ansible进行部署&#xff0c;自行安装ansible。需要部署两个k8s集群&#xff0c;分别在其上安装一个polardb-x集群。 部…

Flask + YARA-Python*实现文件扫描功能

以下是一个 完整的 Web API 示例&#xff0c;使用 Flask YARA-Python 实现文件扫描功能&#xff0c;支持上传文件并返回 YARA 规则匹配结果。 ✅ 功能说明 提供一个 /scan 接口&#xff0c;支持文件上传使用预加载的 YARA 规则进行扫描返回 JSON 格式的匹配结果支持多规则、可…

WinForm之NumericUpDown控件

NumericUpDown&#xff08;数字上下控件&#xff09;是 WinForm 中专门用于输入和调整数值的控件&#xff0c;它结合了文本框和上下按钮&#xff0c;用户可通过点击按钮或直接输入来设置数值&#xff0c;且能严格限制数值范围&#xff08;最小值、最大值&#xff09;和步长&…

一文读懂K8S kubectl 命令,运维小白必看!

一、Kubectl 是什么? Kubectl 是 Kubernetes(简称 K8S)集群的命令行工具,它就像是一把万能钥匙,让我们可以与 K8S 集群进行交互,轻松管理集群中的各种资源,像是 Pod、Service、Deployment 等等。通过向 K8S API 发送 REST 请求,kubectl 实现了对集群资源的增删改查等操…