freemarker生成pdf,同时pdf插入页脚,以及数据量大时批量处理

news2024/10/6 3:22:34

最近公司有个需求,就是想根据一个模板生成一个pdf文档,当即我就想到了freemarker这个远古老东西,毕竟freemarker在模板渲染方面还是非常有优势的。

准备依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>html2pdf</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--pdf 支持中文(默认不支持)-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>

我这里不想选freemarker版本,直接用spring集成的省事。
配置一下freemarker的配置

import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@org.springframework.context.annotation.Configuration
public class FreemarkerConfig {

	// 我这里为了省事,不想创建那么多的Configuration,而且创建Configuration太多不好
    @Bean(name = "cfg")
    public Configuration freemarkerConfigurer() throws IOException {
    	// 选择版本,不同版本对不同的模板语法或者模板转换也会有差异,如果你css 样式比较新,建议选高版本准没错
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
        // 选择你存放模板的位置
        final ClassPathResource classPathResource = new ClassPathResource("templates");
        cfg.setDirectoryForTemplateLoading(classPathResource.getFile());
        cfg.setDefaultEncoding("UTF-8");
        // 模板异常处理
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        return cfg;
    }
}

然后我们准备下我们的ftl模板【freemarker的模板文件】----pdf.ftl
freemarker框架类似于beetlthymeleafjspVelocity等模板引擎
JSP就不用说了吧,基本上开发Java的基本上都会了解开发过

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    .logo {
        width: 320px;
        height: 80px;
    }
    .user-info {
        padding: 10px 10px;
        background: RGB(221, 235, 247);
    }

    .label {
        width: 150px;
        padding: 0 20px 0 0;
        text-align: left;
    }

    .time {
        width: 100px;
        margin-right: 10px;
        text-align: center;
    }

    .label, .time {
        display: inline-block;
    }

    .range-time {
        margin: 20px 0;
    }

    .table-data {
        width: 100%;
    }
    table{
        border-collapse: collapse;
    }
    .header > th {
        text-align: left;
        height: 50px;
    }
    .divider-line {
        margin: 20px 0;
        height: 3px;
        background: #000;
    }
    .desc {
        padding: 15px 10px;
    }
    .date {
        width: 100px;
    }
    .fee {
        width: 50px;
    }
    .name {
        width: 140px;
    }
    .name, .fee, .date {
        padding: 0 10px;
    }
    .download-date {
        text-align: right;
    }
    .bottom-footer-tip {
        width: 100%;
        margin-top: 300px;
        font-size: 12px;
        transform: scale(.9);
    }
</style>
<body>

<div class="download-date">Download on 2022/2/2</div>
<div class="range-time">
    <span class="time">${startTime}</span>
    <span>to</span>
    <span class="time">${endTime}</span>
</div>

<table class="table-data">
    <tr class="header">
        <th>Date</th>
        <th>Name</th>
        <th>desc</th>
        <th>fee</th>
    </tr>
    <tr class="divider-line">
        <th></th>
        <th></th>
        <th></th>
        <th></th>
    </tr>
    <#list list as item>
        <tr>
            <td class="date">${item.date}</td>
            <td class="name">${item.name}</td>
            <td class="desc">
                <div>${item.desc}</div>
            </td>
            <td class="fee">${item.fee}</td>
        </tr>
    </#list>
    <tr class="divider-line">
        <th></th>
        <th></th>
        <th></th>
        <th></th>
    </tr>
</table>
</body>
</html>

这里ftl的语法,我就不多做解释了,我这里附上freemarker的官方文档,感兴趣的自己去学习一下。

然后准备下我们的代码处理逻辑

首先是PDF实体数据

import lombok.Data;

import java.util.List;

@Data
public class PDFData {
    private String logo;
    private String name;
    private String address;
    private String startTime;
    private String endTime;
    private List<TableData> list;
}

然后是关联(table)数据


import lombok.Data;

@Data
public class TableData {
    private String date;
    private String desc;
    private String name;
    private String fee;
}

然后我们处理我们处理逻辑的代码

import com.alibaba.fastjson.JSONObject;
import com.example.web.pojo.TableData;
import com.example.web.pojo.PDFData;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.TextAlignment;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Component
public class FreemarkerExecution {
	
	// 准备下字体文件
    private static String FONT = "./src/main/resources/templates/AlibabaPuHuiTi-3-65-Medium.ttf";
    // 后续转pdf时的配置
    private static ConverterProperties converterProperties = new ConverterProperties();
    private static String base64LogoData = null;
    {
        FontProvider dfp = new DefaultFontProvider();
        //添加字体库
        dfp.addFont(FONT);
        //设置解析属性
        converterProperties.setFontProvider(dfp);
        converterProperties.setCharset("utf-8");
        try {
        	// 有一个logo处理,因为一般服务器渲染的话一般建议将部分图片处理成base64然后放进来,或者大家看看其他的方式
            base64LogoData = imgToBase64(new FileInputStream("./src/main/resources/templates/logo.png"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Resource(name = "cfg")
    private Configuration configuration;

	// 普通处理逻辑
    public void converterHTML() {
    	// 这个会将处理后的html语法输出至 命令行窗口,可以手动创建一个html文件,然后把结果复制进去直接打开查看
        try (Writer out = new OutputStreamWriter(System.out)) {
        	// 获取数据
            final PDFData pdfData = getData();
            Template temp = configuration.getTemplate("pdf.ftl");
            // 直接写出文件
            temp.process(pdfData, out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

    private void writeToPDF(Template template, Map<String, Object> dataModel) {
        try {
            final File file = new File("D:/pdf/test.html");
            template.process(dataModel, new OutputStreamWriter(new FileOutputStream(file)));
            final File pdfFile = new File("D:/pdf/test.pdf");
            HtmlConverter.convertToPdf(file, pdfFile, converterProperties);
            PdfReader reader = new PdfReader(new File("D:/pdf/test.pdf"));
            PdfWriter writer = new PdfWriter(new FileOutputStream("D:/pdf/test_1.pdf"));
            PdfDocument pdfDocument = new PdfDocument(reader, writer);
            // 页大小
            final PageSize pageSize = pdfDocument.getDefaultPageSize();
            // 页数
            final int numberOfPages = pdfDocument.getNumberOfPages();
            for (int i = 1; i <= numberOfPages; i++) {
                PdfPage page = pdfDocument.getPage(i);
                final PdfDocument pdfDoc = page.getDocument();
                final Document document = new Document(pdfDoc);
                final Paragraph paragraph = new Paragraph("Page" + i)
                        .setFont(PdfFontFactory.createFont(FONT))
                        .setFontColor(new DeviceRgb(0, 0, 0))
                        .setFixedPosition(i, 0, 10, pageSize.getWidth())
                        .setFontSize(10)
                        .setTextAlignment(TextAlignment.CENTER);
                document.add(paragraph);
            }
            pdfDocument.close();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private PDFData getData() throws FileNotFoundException {
        PDFData data = new PDFData();
        data.setName("重生之我是蔡徐坤");
        data.setAddress("蔡徐坤蔡徐坤喜欢唱跳rap篮球");
        data.setStartTime("01-Feb-22");
        data.setEndTime("28-Feb-22");
        data.setLogo("data:image/png;base64," + base64LogoData);
        final LocalDateTime nowTime = LocalDateTime.now();
        final List<TableData> arr = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            final TableData tableData = new TableData();
            tableData .setDesc(i % 2 == 0 ? "交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大" : "交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大交会毫不我交会毫不我哒哒哒哒哒哒多多多多多多多交会毫不我电话电话大");
            tableData .setName("蔡徐坤" + i);
            tableData .setFee(1000 + i + "");
            tableData .setDate(nowTime.plusDays(-i).format(DateTimeFormatter.ofPattern("YYYY/MM/dd")));
            arr.add(tableData);
        }
        data.setList(arr);
        return data;
    }

    private String imgToBase64(InputStream inputStream) {
        byte[] data = null;
        try {
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(data);
    }
}

这里会又有一个问题出现,就是我们一般处理PDF的时候,数据不可能一次性处理到内存中,因为我们服务器内存等问题,假如我们有100w数据,肯定不能一次性查出来,由此我们就需要批量处理,这里我们可以将模板拆分开,重复的数据放一个模板文件,然后后续进行模板的组装。

首先,我将一个ftl模板文件拆成了三个 👉 header.ftl,content.ftl,footer.ftl,然后再由一个主的核心ftl模板来组装这几个模板。
思路:准备上述模板文件,然后渲染模板后继续解析成ftl模板文件,然后读取选然后的ftl模板文件,然后转成html,最后通过html文件处理成pdf文件。

这里content.ftl是批量的数据,因为不能一次读取大量数据,所以这里content.ftl要单独处理一下。

Main.ftl
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    .logo {
        width: 320px;
        height: 80px;
    }

    .user-info {
        padding: 10px 10px;
        background: RGB(221, 235, 247);
    }

    .label {
        width: 150px;
        padding: 0 20px 0 0;
        text-align: left;
    }

    .time {
        width: 100px;
        margin-right: 10px;
        text-align: center;
    }

    .label, .time {
        display: inline-block;
    }

    .range-time {
        margin: 20px 0;
    }

    .table-data {
        width: 100%;
    }

    table {
        border-collapse: collapse;
    }

    .header > th {
        text-align: left;
        height: 50px;
    }

    .divider-line {
        margin: 20px 0;
        height: 3px;
        background: #000;
    }

    .desc {
        padding: 15px 10px;
    }

    .date {
        width: 100px;
    }

    .name {
        width: 50px;
    }

    .fee{
        width: 140px;
    }

    .fee, .name , .date {
        padding: 0 10px;
    }

    .download-date {
        text-align: right;
    }

    .bottom-footer-tip {
        width: 100%;
        margin-top: 300px;
        font-size: 12px;
        transform: scale(.9);
    }
</style>
<body>


${headerPath}
<table class="table-data">
    <tr class="header">
        <th>Date</th>
        <th>Desc</th>
        <th>Name</th>
        <th>Fee</th>
    </tr>
    <tr class="divider-line">
        <th></th>
        <th></th>
        <th></th>
        <th></th>
    </tr>
    <#list contentPathList as content>
        ${content}
    </#list>
    <tr class="divider-line">
        <th></th>
        <th></th>
        <th></th>
        <th></th>
    </tr>
</table>
${footerPath}

<#--<#include "header.ftl">-->
<#--<#include "content.ftl">-->
<#--<#include "footer.ftl">-->

</body>
</html>
header.ftl
<img src="${logo}" class="logo">
<div class="download-date">Download on 2022/2/2</div>
<div class="user-info">
    <div>
        <div class="label">User:</div>
        <span>${name}</span>
    </div>
    <div>
        <div class="label">Address:</div>
        <span>${address}</span>
    </div>
</div>

<div class="range-time">
    <span class="time">${startTime}</span>
    <span>to</span>
    <span class="time">${endTime}</span>
</div>
content.ftl

    <#list list as item>
        <tr>
            <td class="date">${item.date}</td>
            <td class="desc">
                <div>${item.desc}</div>
            </td>
            <td class="fee">${item.fee}</td>
            <td class="name">${item.name}</td>
        </tr>
    </#list>

footer.ftl

    <#list list as item>
        <tr>
            <td class="date">${item.date}</td>
            <td class="desc">
                <div>${item.desc}</div>
            </td>
            <td class="fee">${item.fee}</td>
            <td class="name">${item.name}</td>
        </tr>
    </#list>

核心处理逻辑
    void allTemplatesWriteToPDF() {
        // 所有子模板
        final List<String> ftlNameList = new ArrayList<>();
        try {
        	// 读取对应的模板文件
            final Template template = getTemplate("content.ftl");
            final Template headerTemplate = getTemplate("header.ftl");
            final Template footerTemplate = getTemplate("footer.ftl");
            final PDFData data = getData();
            // 先处理头部和尾部
            headerTemplate.process(data, new FileWriter("D:/pdf/content/header.ftl"));
            footerTemplate.process(data, new FileWriter("D:/pdf/content/footer.ftl"));
            // mock 模拟数据库查询10次
            for (int i = 0; i < 10; i++) {
                // 组装10条数据,算上10次循环一共100条数据
                final PDFData pdfData = getData();
                String fileName = "D:/pdf/content/content" + i + ".ftl";
                final FileWriter writer = new FileWriter(fileName);
                // 存储最后框架模板的数据,这里是存储了freemarker include 语法连接所有的需要组装的数据模板名称
                ftlNameList.add("<#include \"" + fileName.substring(fileName.lastIndexOf("/") + 1, fileName.lastIndexOf(".")) + ".ftl \"/>");
                // 生成对应的模板文档
                template.process(pdfData, writer);
                writer.flush();
                writer.close();
            }
            // 获取所有子模板
            final Configuration cdf = new Configuration(Configuration.VERSION_2_3_22);
            cdf.setDirectoryForTemplateLoading(new File("D:/pdf/content"));
            cdf.setDefaultEncoding("UTF-8");
            cdf.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            final Template mainTemplate = getTemplate("main.ftl");
            final HashMap<Object, Object> map = new HashMap<>();
            map.put("headerPath", "<#include \"" + "header.ftl\"/>");
            map.put("contentPathList", ftlNameList);
            map.put("footerPath", "<#include \"" + "footer.ftl\"/>");
            mainTemplate.process(map, new FileWriter("D:/pdf/content/main.ftl"));
            final Template cdfTemplate = cdf.getTemplate("main.ftl");
            cdfTemplate.process(null, new FileWriter("D:/pdf/content/main.html"));
            final File pdfFile = new File("D:/pdf/test_new.pdf");
            HtmlConverter.convertToPdf(new File("D:/pdf/content/main.html"), pdfFile, converterProperties);
            PdfReader reader = new PdfReader(pdfFile);
            PdfWriter writer = new PdfWriter(new FileOutputStream("D:/pdf/test_new_1.pdf"));
            PdfDocument pdfDocument = new PdfDocument(reader, writer);
            // 页大小
            final PageSize pageSize = pdfDocument.getDefaultPageSize();
            // 页数
            final int numberOfPages = pdfDocument.getNumberOfPages();
            // 这里是处理页脚数据
            for (int i = 1; i <= numberOfPages; i++) {
                PdfPage page = pdfDocument.getPage(i);
                final PdfDocument pdfDoc = page.getDocument();
                final Document document = new Document(pdfDoc);
                final Paragraph paragraph = new Paragraph("Page" + i)
                        .setFont(PdfFontFactory.createFont(FONT))
                        .setFontColor(new DeviceRgb(0, 0, 0))
                        .setFixedPosition(i, 0, 10, pageSize.getWidth())
                        .setFontSize(10)
                        .setTextAlignment(TextAlignment.CENTER);
                document.add(paragraph);
            }
            pdfDocument.close();
            reader.close();
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }

    private Template getTemplate(String name) throws IOException {
        return configuration.getTemplate(name);
    }

在这里插入图片描述

在这里插入图片描述

OK,大概就这样,剩下的大家自己去玩吧, 解散!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【讲解下iOS语言基础】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【论文阅读】-- Visual Traffic Jam Analysis Based on Trajectory Data

基于轨迹数据的可视化交通拥堵分析 摘要1 引言2 相关工作2.1 交通事件检测2.2 交通可视化2.3 传播图可视化 3 概述3.1 设计要求3.2 输入数据说明3.3 交通拥堵数据模型3.4 工作流程 4 预处理4.1 路网处理4.2 GPS数据清理4.3 地图匹配4.4 道路速度计算4.5 交通拥堵检测4.6 传播图…

Halcon 产品周围缺口检测

*读取一张图像read_image (Image, 原图.jpg)*获取图像大小get_image_size(Image, Width, Height)*关闭已经打开的窗口dev_close_window ()*打开新窗口dev_open_window(0, 0, Width, Height, black, WindowHandle) //打开指定大小的窗口*对图像进行阈值操作threshold (Image, R…

C语言 指针和数组—指针数组及其在字符串处理中的应用

目录 问题的提出 问题的解决 回头看——指针、数组及其他类型的混合 指针数组与指向数组的指针 字符串的排序 问题的提出 问题的解决 回头看——指针、数组及其他类型的混合  基本数据类型  int 、 long 、 char 、 short 、 float 、 double……  数组是一种从…

001,函数指针是一种特殊的指针,它指向的是一个函数地址,可以存储函数并作为参数传递,也可以用于动态绑定和回调函数

函数指针是一种特殊的指针 001&#xff0c;函数指针是一种特殊的指针&#xff0c;它指向的是一个函数地址&#xff0c;可以存储函数并作为参数传递&#xff0c;也可以用于动态绑定和回调函数 文章目录 函数指针是一种特殊的指针前言总结 前言 这是ai回答的标准答案 下面我们…

SSM中小学生信息管理系统 -计算机毕业设计源码02677

摘要 随着社会的发展和教育的进步&#xff0c;中小学生信息管理系统成为学校管理的重要工具。本论文旨在基于SSM框架&#xff0c;采用Java编程语言和MySQL数据库&#xff0c;设计和开发一套高效、可靠的中小学生信息管理系统。中小学生信息管理系统以学生为中心&#xff0c;通过…

手把手搭建微信机器人,帮你雇一个24小时在线的个人 AI 助理(上)

上一篇&#xff0c;带领大家薅了一台腾讯云服务器&#xff1a;玩转云服务&#xff1a;手把手带你薅一台腾讯云服务器&#xff0c;公网 IP。 基于这台服务器&#xff0c;今天我们一起动手捏一个基于 LLM 的微信机器人。 0. 前置准备 除了自己常用的微信账号以外&#xff0c;还…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的生日聚会(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

【微服务】springboot对接Prometheus指标监控使用详解

目录 一、前言 二、微服务监控概述 2.1 微服务常用监控指标 2.2 微服务常用指标监控工具 2.3 微服务使用Prometheus监控优势 三、环境准备 3.1 部署Prometheus服务 3.2 部署Grafana 服务 3.3 提前搭建springboot工程 3.3.1 引入基础依赖 3.3.2 配置Actuator 端点 3.…

STM32实现看门狗(HAL库)

文章目录 一. 看门狗1. 独立看门狗&#xff08;IWDG&#xff09;1.1 原理1.2 相关配置1.3 相关函数 2. 窗口看门狗&#xff08;WWDG&#xff09;2.1 原理2.2 相关配置2.3 相关函数 一. 看门狗 单片机在日常工作中常常会因为用户配置代码出现BUG&#xff0c;而导致芯片无法正常工…

如何对GD32 MCU进行加密?

GD32 MCU有哪些加密方法呢&#xff1f;大家在平时项目开发的过程中&#xff0c;最后都可能会面临如何对出厂产品的MCU代码进行加密&#xff0c;避免产品流向市场被别人读取复制。 下面为大家介绍GD32 MCU所支持的几种常用的加密方法&#xff1a; 首先GD32 MCU本身支持防硬开盖…

无需服务器,浏览器跑700+AI模型?!【送源码】

Transformers.js 是一个创新的网络机器学习库&#xff0c;它将先进的 Transformer 模型直接带入浏览器&#xff0c;无需服务器端支持。这个库与 Hugging Face 的 Python transformers 库功能对等&#xff0c;提供相似的 API 接口来运行预训练模型&#xff0c;涵盖了自然语言处理…

人工智能系列-Python面向对象编程

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 面向对象编程和面向过程编程 在使用计算机语言进行代码编写时&#xff0c;常见的两种思路是面向对象编程和面向过程编程。 面向过程&#xff1a;根据业务逻辑从上到下写代码。…

Hi6602 恒压恒流SSR电源方案

Hi6602是一款针对离线式反激电源设计的高性能PWM控制器。Hi6602内集成有通用的原边恒流控制技术&#xff0c;可支持断续模式和连续模式工作&#xff0c;适用于恒流输出的隔离型电源应用中。Hi6602内部具有高精度65kHz开关频率振荡器&#xff0c;且带有抖频功能可优化EMI性能。H…

【Python迭代器探秘】:揭秘迭代器与生成器的魔法,掌握高效循环的艺术

文章目录 一、迭代器的基本概念1.1 迭代器优点1.2 迭代器的编写方法1.3 python内置迭代器函数1.4 小结1.5 迭代器对象与迭代对象1.5.1 区别1. 迭代对象2. 迭代器对象3. 小结 1.5.2 方法区分 二、生成器基本概念1. 生成器函数2. 生成器表达式 一、迭代器的基本概念 迭代器是Pyt…

【数据结构/操作系统 堆和栈】区别及应用场景、底层原理图解

堆和栈 比较有趣的是&#xff0c;计算机网络、操作系统中都会对堆栈有不同方面比较详细的描述&#xff0c;而使用的地方通常对这些底层的细节表现得没有那么明显。 但如果你能了解堆栈在计算机网络和操作系统中的表现形式&#xff0c;在你写代码时就会有不一样的认识&#xff…

基于AOP的数据字典实现:实现前端下拉框的可配置更新

作者&#xff1a;后端小肥肠 创作不易&#xff0c;未经允许严禁转载。 目录 1. 前言 2. 数据字典 2.1. 数据字典简介 2.2. 数据字典如何管理各模块的下拉框 3. 数据字典核心内容解读 3.1. 表结构 3.2. 核心代码 3.2.1. 根据实体类名称获取下属数据字典 3.2.2. 数据字…

【QT】显示类控件

显示类控件 显示类控件1. label - 标签2. LCD Number - 显示数字的控件3. ProgressBar - 进度条4. Calendar Widget - 日历5. Line Edit - 输入框6. Text Edit - 多行输入框7. Combo Box - 下拉框8. Spin Box - 微调框9. Date Edit & Time Edit - 日期微调框10. Dial - 旋钮…

3-4 优化器和学习率

3-4 优化器和学习率 主目录点这里 优化器是机器学习和深度学习模型训练过程中用于调整模型参数的方法。它的主要目标是通过最小化损失函数来找到模型参数的最优值&#xff0c;从而提升模型的性能。 在深度学习中&#xff0c;优化器使用反向传播算法计算损失函数相对于模型参数…

pycharm远程连接和conda环境参考博客自用整理

pycharm远程连接 pycharm的连接需要先用xftp把项目上传上去&#xff08;包括venv&#xff09;&#xff0c;似乎才能连 https://blog.csdn.net/weixin_41174300/article/details/134420981 注意要上传一份一模一样的&#xff0c;然后在deployment里面添加mapping 注意传输文件…