java静默打印PDF(可实现生产环境下服务器写入PDF模板,然后调用客户端打印机打印)

java静默打印PDF可实现生产环境下服务器写入PDF模板,然后调用客户端打印机打印

  • 一、简
      • 需求
      • 实现步骤
  • 二、代码实现
    • 0、打印模板
    • 1、服务器部分 (端口:8090)
      • 1.1、maven依赖
      • 1.2、实体
        • 1.2.1、接口返回类
        • 1.2.2、标签纸页面参数类
        • 1.2.3、PDF模板参数类
      • 1.3、Controller层接口
      • 1.4、写入pdf工具类
      • 1.5、调用客户端jar接口
    • 2、打印机客户端jar (端口:9050)
      • 2.1、依赖
      • 2.2、实体类
        • 2.2.1、纸张对象
        • 2.2.2、统一返回对象
      • 2.3、Controller层,接收服务器调用打印请求
      • 2.4、配置打印参数调用打印机
  • 三、测试
    • 1、调用测试
    • 2、实现结果
    • 3、查看客户端打印机
  • 总结

一、简

需求

写这个的原因主要是因为当时项目中的打印功能是用户打印标签时,每次点击打印是通过把PDF文件下载到客户端浏览器,然后需要通过浏览器去点击打印机实现打印,就非常麻烦,每次都步骤非常复杂,而且每次参数都要重新设置。于是就想着怎么通过java实现自己调用打印机,用户只需要输入需要写入pdf模板的参数,提前配置好打印参数,然后后台自己去调用打印不需要通过浏览器去单个打印。

具体实现把文字、二维码、条形码、图片实现通过模板写入pdf文件,然后再到打印机打印处理

实现步骤

  • 先大致介绍一下这篇文章的内容,主要是通过 Adobe Acrobat DC(或者其他的PDF模板制作app),制作好PDF模板,然后通过itextpdf框架把数据写入到模板对应的文本域中,可以实现PDF文件打开,写入的内容可以正常显示代表pdf文件制作没用问题了。
  • 然后在需要连接打印机打印的上部署一个调用本地打印机的jar包,jar主要通过pdfbox框架实现调用本地打印机,成功把需要打印的pdf文件传递到打印机的打印队列,实现打印。
  • 在打印机主机的jar写好接受服务器打印的pdf的http接口,用于接收服务器传递过来的需要打印的pdf文件以及一些打印参数(包括指定打印机、自定义纸张大小、设置打印参数、以及显示打印对话框等)

二、代码实现

主要包括服务器部分(这里只包括写入pdf模板到调用打印机客户端接口,具体业务根据自己实际业务修改就行)和打印机客户端。

0、打印模板

通过 Adobe Acrobat DC配置对应的文本域,具体配置可以百度查看,这里就不赘述了
在这里插入图片描述

1、服务器部分 (端口:8090)

yml只设置了端口,就不展示出来了

1.1、maven依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.5.15</version></dependency>
<!--pdf生成--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.1</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.23</version></dependency><!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.48</version></dependency>

1.2、实体

1.2.1、接口返回类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {/*** 是否成功**/private Boolean success;/*** 错误信息**/private String message;/*** 请求状态 200-成功 400-失败**/private Integer code;/*** 当前时间戳**/private Long timestamp;/*** 返回结果**/private Object result;public static Result ok() {return new Result(true, null, 200, System.currentTimeMillis(),null);}public static Result ok(Object data) {return new Result(true, null, 200,System.currentTimeMillis(),data);}public static Result ok(List<?> data) {return new Result(true, null, 200,System.currentTimeMillis(),data);}public static Result error(String errorMsg) {return new Result(false, errorMsg, 400,System.currentTimeMillis(),null);}
}

1.2.2、标签纸页面参数类

打印的标签纸页面参数类,添加默认值

/*** @author zhengfuping* @version 1.0* 110*65 的标签纸页面*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PaperVo {/**宽*/private double width = 100*2.83;/**高*/private double height = 60*2.83;/** X 坐标*/private double x = 15;/** Y 坐标*/private double y = 10;/*** 打印页面方向:*      0:横向 从右向左,1:横向 从左向右,2:纵向。* */private Integer orientation = PageFormat.PORTRAIT;private String name;
}

1.2.3、PDF模板参数类

对应pdf模板的文本域名称

/*** @author zhengfuping* @version 1.0* pdf模板参数*/
@Data
@Builder
public class Template {private String time;private String code;private String qrCode;private String barCode;private String image;private String age;private String name;
}

1.3、Controller层接口

@RequestMapping("/pdf")
@RestController
public class PDFController {@Autowiredprivate Netty netty;@Autowiredprivate HttpPdf httpPdf;/*** @author yingfeng* @Param * @param params 包括两个参数 copies:打印张数、duplex:是否打印反面* @param request* @return * @return Result*/@PostMapping("/print")public Result print(@RequestBody Map<String ,Object> params, HttpServletRequest request){//因为测试原因,便于理解,所以参数直接添加String Code = "43504277201002308221C0100C010145006";String barCode = "43504277201002308221C0100C010145006-bar";String time = DateUtil.format(new Date(), "yyyyMMdd");String qrCode = "https://blog.csdn.net/weixin_52315708";String name = "张三";String image = "D:/1zheng/dai/excel/exportexcel/a1.jpg";Template template = Template.builder().qrCode(qrCode).code(Code).time(time).barCode(barCode).image(image).name(name).age("18").build();//转为map是因为需要循环把值写入对应的文本域Map<String, Object> map = BeanUtil.beanToMap(template);//调用写入文本域工具类,返回对应的byte[]数据byte[] pdf = PDFUtil.test(data);params.put("pdf",pdf);//用于调用客户端的接口Result result = httpPdf.doPostWith(params);return result;}

1.4、写入pdf工具类

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.qrcode.EncodeHintType;
import com.itextpdf.text.pdf.qrcode.ErrorCorrectionLevel;
import com.zheng.exceltest.pdf.entity.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import sun.misc.BASE64Encoder;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;/*** @author zhengfuping* @version 1.0* 实现往打印机打印*/
@Slf4j
public class PDFUtil {public static byte[] test(Map<String, Object> data)  {BASE64Encoder encoder = new BASE64Encoder();BufferedInputStream bin = null;ByteArrayOutputStream bos = null;PdfStamper ps = null;OutputStream fos = null;try {// pdf模板String fileName = "exportexcel/PDF打印测试模板.pdf";//读取pdfPdfReader reader  = new PdfReader(fileName);bos = new ByteArrayOutputStream();//将要生成的目标PDF文件名称ps = new PdfStamper(reader, bos);
//        PdfContentByte under = ps.getUnderContent(1);
//        取出报表模板中的所有字段AcroFields fields = ps.getAcroFields();//        对表单数据进行赋值fillData(fields,ps,data);ps.setFormFlattening(true);ps.close();fos = new FileOutputStream("D:/模板打印测试/a1.pdf");fos.write(bos.toByteArray());fos.flush();fos.close();   //实际应该finally在关闭一次bos.close();  //注意,需要在得到 byte[]之前关闭流//            执行打印byte[] bytes = bos.toByteArray();return bytes;}catch (Exception e){e.printStackTrace();}return null;}/*** 具体往模板的对应文本域写入数据* @author zhengfuping* @date 2023/8/9 15:55* @param fields AcroFields对象* @param ps PdfStamper对象* @param data 数据*/public static void fillData(AcroFields fields, PdfStamper ps, Map<String, Object> data) throws IOException, DocumentException {
//        设置中文字体BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);ArrayList<BaseFont> fonts = new ArrayList<>();Font font = FontFactory.getFont(getFontPath("SimHei.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED,(short)14);fonts.add(font.getBaseFont());fonts.add(bf);fields.setSubstitutionFonts(fonts);//循环遍历集合中的文本域字段,根据名称进行不同处理for (String key : data.keySet()) {System.out.println(key+":"+data.get(key));if (data.get(key)==null)continue;if (key.equals("image")) {      //      生成图片String value = data.get(key).toString();String imgpath = value;int pageNo = fields.getFieldPositions(key).get(0).page;Rectangle signRect = fields.getFieldPositions(key).get(0).position;float x = signRect.getLeft();float y = signRect.getBottom();// 根据路径读取图片Image image = Image.getInstance(imgpath);// 获取图片页面PdfContentByte under = ps.getOverContent(pageNo);// 图片大小自适应image.scaleToFit(signRect.getWidth(), signRect.getHeight());// 添加图片image.setAbsolutePosition(x, y);under.addImage(image);} else if (key.equals("barCode")) {     //生成条形码//遍历条码字段String value = data.get(key).toString();
//              获取位置(左上右下)AcroFields.FieldPosition fieldPosition = fields.getFieldPositions(key).get(0);
//                  ?nullPdfNumber rNum = fields.getFieldItem(key).getWidget(0).getAsDict(PdfName.AP).getAsNumber(PdfName.R);if (rNum == null) {fieldPosition.position.setRotation(0);} else {fieldPosition.position.setRotation(rNum.intValue());}//绘制条码Barcode128 barcode128 = new Barcode128();barcode128.setSize(8);if (fieldPosition.position.getRotation() == 90 || fieldPosition.position.getRotation() == 270) {barcode128.setBarHeight(25);barcode128.setX(0.82f);} else {//条码宽高
//                    barcode128.setBarHeight(fieldPosition.position.getHeight() - 40);
//                    barcode128.setX(fieldPosition.position.getWidth() / 150);barcode128.setBarHeight(25);barcode128.setX(0.5f);}//条码与数字间距barcode128.setBaseline(8);//条码值barcode128.setCode(value);barcode128.setStartStopText(false);barcode128.setExtended(true);//绘制在第一页PdfContentByte cb = ps.getOverContent(1);//生成条码图片Image image128 = barcode128.createImageWithBarcode(cb, null, null);//旋转度数image128.setRotationDegrees(fieldPosition.position.getRotation());//左边距(居中处理)float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;//条码位置image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, fieldPosition.position.getBottom());//加入条码cb.addImage(image128);}else if ("qrCode".equals(key)){        //生成二维码//           遍历二维码字段String value = data.get(key).toString();// 获取属性的类型if (value != null ) {//获取位置(左上右下)AcroFields.FieldPosition fieldPosition = fields.getFieldPositions(key).get(0);//绘制二维码float width = fieldPosition.position.getRight()/2 - fieldPosition.position.getLeft()/2;//设定容错性二维码容错率用字母表示,容错能力等级分为:L、M、Q、H四级:L :7%;M:15%;Q:25%;H:30%Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);BarcodeQRCode pdf417 = new BarcodeQRCode(value.toString(), (int) width, (int) width, hints);//生成二维码图像Image image128 = pdf417.getImage();//绘制在第一页PdfContentByte cb = ps.getOverContent(1);//左边距(居中处理)float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;//条码位置image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, fieldPosition.position.getBottom()-3f);//加入条码cb.addImage(image128);}}else{          //生成文字String value = data.get(key).toString();
//                String partCode = (String) data.get("name");
                设置文本大小
//                if (partCode.length()<8 && key.equals("age")){
//                    fields.setFieldProperty(key,"textsize",(float)36,null);
//
//                }else {
//                    fields.setFieldProperty(key,"textsize",(float)9,null);
//                }
//                设置文本字体if (Pattern.compile("[\u4E00-\u9FA5]").matcher(key).find()){fields.setFieldProperty(key,"textfont",bf,null);    //中文fields.setField(key, value);}else {fields.setFieldProperty(key,"textfont",font.getBaseFont(),null);  //英文fields.setField(key, value);}}}}/*** 获取本机的字体文件** @param fontName*/private static String getFontPath(String fontName) {String fontPath = "C:\\Windows\\Fonts\\" + fontName;// 判断系统类型,加载字体文件java.util.Properties prop = System.getProperties();String osName = prop.getProperty("os.name").toLowerCase();if (osName.indexOf("linux") > -1) {fontPath = "/usr/share/fonts/" + fontName;}log.info(osName + "-------------------" + fontPath);return fontPath;}

1.5、调用客户端jar接口

/*** @author zhengfuping* @version 1.0* 调用客户端打印机的jar* @date 2023/4/14 14:35*/
@Service
public class HttpPdf {@Autowiredprivate RestTemplate restTemplate;//接口路径final String url = "http://127.0.0.1:9050/print/print";public Result doPostWith(Map<String ,Object> params){PaperVo paperVo = new PaperVo();System.out.println();params.put("paper",paperVo);Result result = restTemplate.postForObject(url, params, Result.class);return result;}

2、打印机客户端jar (端口:9050)

2.1、依赖

 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.23</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.4.0</version></dependency></dependencies>

2.2、实体类

同上

2.2.1、纸张对象

@Data
public class PaperVo {/**长*/private double width = 216;/**宽*/private double height = 360;/** X 坐标*/private double x = 5;/** Y 坐标*/private double y = 100;/*** 打印页面方向:*      0:横向 从右向左,1:横向 从左向右,2:纵向。* */private Integer orientation = PageFormat.PORTRAIT;
}

2.2.2、统一返回对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {/*** 是否成功**/private Boolean success;/*** 错误信息**/private String message;/*** 请求状态 200-成功 400-失败**/private Integer code;/*** 当前时间戳**/private Long timestamp;/*** 返回结果**/private Object result;public static Result ok() {return new Result(true, null, 200, System.currentTimeMillis(),null);}public static Result ok(Object data) {return new Result(true, null, 200,System.currentTimeMillis(),data);}public static Result ok(List<?> data) {return new Result(true, null, 200,System.currentTimeMillis(),data);}public static Result error(String errorMsg) {return new Result(false, errorMsg, 400,System.currentTimeMillis(),null);}
}

2.3、Controller层,接收服务器调用打印请求

/*** @author zhengfuping* @version 1.0* 接收调用打印请求*/
@RequestMapping("/print")
@RestController
public class PrintController {/*** @Description: 默认使用打印机的名称。可以存在数据库里做持久化*/private static String printName = "SATO CL4NX Plus 305dpi";/*** @Description: 获取打印机列表* @Param: []* @Return: com.wq.print.util.R*/@RequestMapping("/list")public Result list() {ArrayList<String> list = new ArrayList<>();// 遍历所有打印机的名称for (PrintService ps : PrinterJob.lookupPrintServices()) {list.add(ps.getName());}if (list.size() != 0) {return Result.ok(list);}return Result.error("暂无可用打印机,请检查系统打印机设置");}/*** @Description: 设置使用的打印机* @Param:* @Return: com.wq.print.util.R*/@PostMapping("/setPrint")public Result setPrint(@RequestParam("printName") String printName) {PrintController.printName = printName;return Result.ok("打印机设置成功");}@PostMapping("/print")public Result print(@RequestBody Map<String ,Object> params, HttpServletRequest request){try {String pdfBase64Str = String.valueOf(params.get("pdf"));if (StrUtil.isEmptyIfStr(pdfBase64Str)) {return Result.error("pdf的Base64字符串有误或为空,请检查");}//因为传输过程中会把 byte[]转为 pdfBase64Str,需要重新转回来byte[] pdfByte = PrintUtil.base64ToFileByte(pdfBase64Str);//设置参数,没设置也要给默认值int copies = params.get("copies") == null ?1 : Integer.parseInt(params.get("copies").toString());boolean duplex = params.get("duplex") != null && Boolean.parseBoolean(params.get("duplex").toString());Map<String,Object> pdf = (Map<String,Object>) params.get("paper");PaperVo paperVo = null;//如果服务器没有传对应参数,就用这边的if (pdf==null){paperVo = new PaperVo();}else {paperVo = BeanUtil.mapToBean(pdf, PaperVo.class, false, new CopyOptions());}Boolean print = PrintUtil.print(pdfByte, PrintController.printName, copies, duplex,paperVo);if (print){return Result.ok("打印完成");}else {return Result.ok("打印失败");}} catch (NumberFormatException e) {e.printStackTrace();return Result.ok("打印失败"+e.getMessage());}}
}

2.4、配置打印参数调用打印机

配置配置参数调用客户端打印机

public class PrintUtil {/** * 调用配置打印机* @author zhengfuping* @param pdfByte 数据* @param printName  打印机名称* @param copies 打印张数* @param duplex 是否打印反面* @param paperVo 纸张参数* @return Boolean */public static Boolean print(byte[] pdfByte, String printName, int copies, boolean duplex , PaperVo paperVo) {//加载pdf文件对象try(PDDocument document = PDDocument.load(pdfByte)){//            创建打印任务PrinterJob job = PrinterJob.getPrinterJob();//            遍历所有打印机的名称for (PrintService ps : PrinterJob.lookupPrintServices()){String psName = ps.getName();if (psName.equals(printName)){job.setPrintService(ps);break;}}job.setPageable(new PDFPageable(document));
//            纸张对象Paper paper = new Paper();// 设置打印纸张大小paper.setSize(paperVo.getWidth(),paperVo.getHeight());// 设置打印位置 坐标paper.setImageableArea(paperVo.getX(),paperVo.getY(),paper.getWidth(),paper.getHeight());//            打印的页面参数PageFormat pageFormat = new PageFormat();pageFormat.setPaper(paper);pageFormat.setOrientation(paperVo.getOrientation()); //横向 从右向左Book book = new Book();//            打印页面对象--配置PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.SHRINK_TO_FIT, true, 0, true);book.append(pdfPrintable,pageFormat,1);job.setPageable(book);
//            打印份额job.setCopies(copies);if (duplex){HashPrintRequestAttributeSet printSet = new HashPrintRequestAttributeSet();printSet.add(Sides.DUPLEX);job.print(printSet);}else {job.print();}document.close();return true;}catch (Exception e){e.printStackTrace();return false;}}/** * Base64转换编码* @Param * @param strBase64*/public static byte[] base64ToFileByte(String strBase64) {return java.util.Base64.getDecoder().decode(strBase64);}

三、测试

1、调用测试

使用postman调用服务器的打印接口
在这里插入图片描述

最终实现的打印文件因为测试我是直接写入到本地的,实际项目中可能是通过浏览器调用,需要上载到浏览器,直接配置request就行,如果文件可以正常打开,并且客户端有接收到参数,pdf中有数据,说明服务器端代码没问题了。

在这里插入图片描述

  • 具体打印的pdf文件
    在这里插入图片描述

2、实现结果

具体直接最后一句document.close(); 调用打印机后,对应的打印队列中有任务,则说明实现成功
在这里插入图片描述

3、查看客户端打印机

在这里插入图片描述

总结

  • 具体实现上需要注意文本域的名称要对应上;

  • 局限是需要再客户端服务器需要在同一个局域网,如果不是的话,则客户端的接口也需要映射出去用于给服务器调用。

  • 客户端的代码实际上可以转为jar后通过 exe4j 转为.exe文件,再通过Inno Setup 把jdk绑定进去。

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

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

相关文章

OpenCV实例(八)车牌字符识别技术(一)模式识别

车牌字符识别技术&#xff08;一&#xff09;模式识别 1.模式识别流程2. 模式识别方式 影响并导致汽车牌照内字符出现缺损、污染、模糊等情况的常见因素有照相机的性能、采集车辆图像时光照的差异、汽车牌照的清洁度等。为了提高汽车牌照字符识别的准确率&#xff0c;本节将把英…

2.0 Maven基础

1. Maven概述 Maven概念 Apache Maven是一个软件项目管理工具&#xff0c;将项目开发和管理过程抽象程一个项目对象模型&#xff08;POM&#xff0c;Project Object Model&#xff09;。 Maven作用 项目构建 提供标准的、跨平台的自动化项目构建方式。 依赖管理 方便快捷…

深入探索 Spring MVC:构建优雅的Web应用

文章目录 前言一、什么是 Spring MVC1.1 什么是 MVC1.2 什么是 Spring MVC 二、Spring MVC 项目的创建2.1 项目的创建2.2 第一个 Spring MVC 程序 —— Hello World 三、RequestMapping 注解3.1 常用属性3.2 方法级别和类级别注解3.3 GetMapping、PostMapping、PutMapping、Del…

C# Blazor 学习笔记(12):css样式设置

文章目录 前言添加引入css保证razor和css的对应关系手动引入css文件 前言 由于Blazor UI库暂时还不完善&#xff0c;有时候需要我们自己写css。Razor做好了css动态隔离的设置。 ASP.NET Core Blazor CSS 隔离 C#小轮子&#xff1a;Visual Studio自动编译Sass文件 添加引入c…

eclipse Java Code_Style Code_Templates

Preferences - Java - Code Style - Code Templates Eclipse [Java_Code_Style_Code_Templates_ZengWenFeng] 2023.08.07.xml 创建一个新的工程&#xff0c;不然有时候不生效&#xff0c;旧项目可能要重新导入eclipse 创建一个测试类试一试 所有的设置都生效了

实践分享:小程序事件系统设计

微信小程序官方文档中解释说&#xff1a;事件是用于子组件向父组件传递数据&#xff0c;可以传递任意数据。 小程序开发中的事件是指视图层到逻辑层的通讯方式&#xff0c;主要是可以将用户的行为反馈到逻辑层进行处理。事件可以绑定在组件上&#xff0c;当达到触发事件&#…

2023年七夕情人节是什么时候? 淘宝天猫七夕节礼物优惠券怎么领取?

2023年七夕情人节是什么时候&#xff1f; 2023年七夕节时间是2023年8月22日&#xff08;农历七月初七&#xff0c;星期二&#xff09;&#xff1b; 七夕情人节&#xff0c;又称中国情人节&#xff0c;是浪漫的代名词。源自古人对牛郎织女一年一度相会的仰望&#xff0c;这一天…

嵌入式Linux下LVGL的移植与配置

一.sdk源码下载路径 1.官方源码下载路径如下: ​​​​​​ https://github.com/lvgl/lvgl git下载方式 git clone https://github.com/lvgl/lvgl.git 2.个人移植好的源码8.2版本下载路径: 链接&#xff1a;https://pan.baidu.com/s/1jyqIennsQpv-RB4RyKvZyg?pwdc68e 提取…

android 如何分析应用的内存(十八)终章——使用Perfetto查看内存与调用栈之间的泄露

android 如何分析应用的内存&#xff08;十八&#xff09; 在前面两篇文章中&#xff0c;先是介绍了如何用AS查看Android的堆内存&#xff0c;然后介绍了使用MAT查看 Android的堆内存。AS能够满足基本的内存分析需求&#xff0c;但是无法进行多个堆的综合比较&#xff0c;因此…

[保研/考研机试] KY163 素数判定 哈尔滨工业大学复试上机题 C++实现

题目链接&#xff1a; 素数判定https://www.nowcoder.com/share/jump/437195121691718831561 描述 给定一个数n&#xff0c;要求判断其是否为素数&#xff08;0,1&#xff0c;负数都是非素数&#xff09;。 输入描述&#xff1a; 测试数据有多组&#xff0c;每组输入一个数…

excel将主信息和明细信息整理为多对多(每隔几行空白如何填充)

excel导出的数据是主信息和明细信息形式。 方法如下:1、首先&#xff0c;从第一个单元格开始选中要填充的数据区域。2、按CtrlG或者F5调出定位对话框&#xff0c;点击左下角的【定位条件】。3、在【定位条件】中选择【空值】&#xff0c;然后点击【确定】按钮。4、按照上述操作…

Vue3+Ts+Vite项目全局配置Element-Plus主题色

概述 我找了很多博客&#xff0c;想全局配置Elmenet-Plus组件主题色&#xff0c;但都没有效果。所以有了这篇博客&#xff0c;希望能对你有所帮助&#xff01;&#xff01;&#xff01; 文章目录 概述一、先看效果二、创建全局颜色文件2.1 /src/styles 下新建 element-plus.sc…

Snapclear for mac图像背景删除软件

Snapclear使用先进的算法和人工智能技术&#xff0c;能够快速而准确地分离图像中的主题和背景。它可以自动识别边缘和细节&#xff0c;并生成平滑而清晰的抠图结果。 Snapclear Mac版下载-Snapclear for mac(图像背景删除软件)- Mac下载 功能 人工智能驱动。 精确的切片 100%…

skywalking忽略调用链路中的指定异常

文章目录 一、介绍二、演示项目介绍1. 支付服务2. 订单服务 三、项目演示1. 未忽略异常2. 忽略异常修改配置使用注解 四、结论 往期内容 一、skywalking安装教程 二、skywalking全链路追踪 三、skywalking日志收集 一、介绍 在前面介绍在微服务项目中使用skywalking进行全链…

小白到运维工程师自学之路 第七十一集 (kubernetes网络设置)

一、概述 Master 节点NotReady 的原因就是因为没有使用任何的网络插件&#xff0c;此时Node 和Master的连接还不正常。目前最流行的Kubernetes 网络插件有Flannel、Calico、Canal、Weave 这里选择使用flannel。 二、安装flannel 1、master下载kube-flannel.yml&#xff0c;所…

ABAP: SQL 多值查询

基础查数据 问题举例&#xff1a;例如查物料类型为ZFRT、ZROH和ZRSA的物料编码。 1、直接查询&#xff0c;三种不同类型的物料类型是或的关系。 SELECT DISTINCT ma~matnr ma~mtartFROM mara AS maINNER JOIN mbewh AS mbON ma~matnr mb~matnrINTO CORRESPONDING FIELDS OF…

Lombok的使用及注解含义

文章目录 一、简介二、如何使用2.1、在IDEA中安装Lombok插件2.2、添加maven依赖 三、常用注解3.1、Getter / Setter3.2、ToString3.3、NoArgsConstructor / AllArgsConstructor3.4、EqualsAndHashCode3.5、Data3.6、Value3.7、Accessors3.7.1、Accessors(chain true)3.7.2、Ac…

数据结构--最小生成树

数据结构–最小生成树 连通图 \color{red}连通图 连通图的生成树是 包含图中全部顶点的一个极小连通子图 \color{red}包含图中全部顶点的一个极小连通子图 包含图中全部顶点的一个极小连通子图。 若图中顶点数为n&#xff0c;则它的生成树含有 n-1 条边。对生成树而言&#xff…

Spring Profile与PropertyPlaceholderConfigurer实现项目多环境配置切换

最近考虑项目在不同环境下配置的切换&#xff0c;使用profile注解搭配PropertyPlaceholderConfigurer实现对配置文件的切换&#xff0c;简单写了个demo记录下实现。 基本知识介绍 Profile Profile通过对bean进行修饰&#xff0c;来限定spring在bean管理时的初始化情况&#…

[NOIP2003 普及组] 栈

题目背景 栈是计算机中经典的数据结构&#xff0c;简单的说&#xff0c;栈就是限制在一端进行插入删除操作的线性表。 栈有两种最重要的操作&#xff0c;即 pop&#xff08;从栈顶弹出一个元素&#xff09;和 push&#xff08;将一个元素进栈&#xff09;。 栈的重要性不言自…