代码生成器使用原理以及使用方法

代码生成器使用原理以及使用方法

版本号:1.0

二Ο二五年二月

目录

文档介绍

1.1编写目的

1.2文档范围

1.3读者对象

系统设计

2.1设计目标

2.2设计思路

2.3代码实现原理

使用方法

3.1如何使用

3.2如何修改?

对原程序的bug修改及简化

4.1 一个bug

4.2 Controler层三个if改成接口形式1->3

4.3引擎中几次替换修改为小的方法调用

4.4改进建议

文档介绍

1.1编写目的

1.让修改者了解代码执行过程,为未来可能的修改做准备。

2.让使用者了解怎么使用,需要输入哪些参数才能执行

1.2文档范围

代码模块组成,代码执行过程解析,先前代码的错误原因分析以及修改方法。

1.3读者对象

有一定java基础 知晓”类” ”注解”这些java内容以及使用方式。

系统设计

2.1设计目标

通用的代码生成器。有几个部分:

第一个部分:代码模板的生成。

第二个部分:webmodelvo参数构建。

第三部分:webmodelvo转为map。

第四部分:构建模板位置及目标位置。

第五部分:引擎实现。

2.2设计思路

代码生成器几乎代码都是是通过 `OnlineGeneratorController` 类开始执行的。正常使用时应当从浏览器端输入,下面介绍的是用main制作的样例输入。

1. 初始化 `onewebModelVo` 对象

WebModelVo onewebModelVo = OneMockWebModelVo.initWo();

作用

  调用 `OneMockWebModelVo.initWo()` 方法,初始化一个 `WebModelVo` 对象 `onewebModelVo`。  

  这个对象通常是一个数据模型(DTO 或 VO),用于描述单表模型的结构。  

  `onewebModelVo` 包含 14 个字段,其中 11 个是 `String` 类型。

思路  

  通过模拟数据(Mock Data)生成一个单表模型的数据对象,为后续的代码生成提供输入。

---

2.初始化 `OnlineGeneratorController` 并设置模板引擎

OnlineGeneratorController onlineGeneratorController = new OnlineGeneratorController();

onlineGeneratorController.setFreemakerEngine(new FreemakerEngineImpl());

作用

  创建 `OnlineGeneratorController` 的实例,用于控制代码生成的过程。  

  设置 `FreemakerEngineImpl` 作为模板引擎,用于解析和生成代码模板。

思路  

  `Freemaker` 是一个模板引擎,可以根据模板文件和数据模型生成代码。  

  这里通过 `setFreemakerEngine` 方法将 `FreemakerEngineImpl` 注入到 `OnlineGeneratorController` 中,以便后续使用。

---

3.生成单表模型的代码

onlineGeneratorController.codeGeneratesingletablewithouttree(onewebModelVo);

作用  

  调用 `codeGeneratesingletablewithouttree` 方法,传入 `onewebModelVo` 作为参数,生成单表模型的代码。

思路  

  `onewebModelVo` 描述了单表模型的结构,`codeGeneratesingletablewithouttree` 方法会根据这个结构生成对应的代码文件(如实体类、DAO、Service 等)。

4.初始化 `treewebModelVo` 对象

WebModelVo treewebModelVo = TreeMockWebModelVo.initWo();

作用  

  调用 `TreeMockWebModelVo.initWo()` 方法,初始化一个 `WebModelVo` 对象 `treewebModelVo`。  

  这个对象通常用于描述树形结构模型(如菜单、分类等)。

思路  

  通过模拟数据生成一个树形结构模型的数据对象,为后续的代码生成提供输入。

5.生成树形结构模型的代码

onlineGeneratorController.codeGeneratesingletablewithouttree(treewebModelVo);

作用

  调用 `codeGeneratesingletablewithouttree` 方法,传入 `treewebModelVo` 作为参数,生成树形结构模型的代码。

思路  

  `treewebModelVo` 描述了树形结构模型的结构,`codeGeneratesingletablewithouttree` 方法会根据这个结构生成对应的代码文件。

6.初始化 `onetomanywebModelVo` 对象

WebModelVo onetomanywebModelVo = OneToManyMockWebModelVo.initWo();

作用  

  调用 `OneToManyMockWebModelVo.initWo()` 方法,初始化一个 `WebModelVo` 对象 `onetomanywebModelVo`。  

  这个对象通常用于描述一对多关系模型(如订单和订单项)。

思路

  通过模拟数据生成一个一对多关系模型的数据对象,为后续的代码生成提供输入。

7.生成一对多关系模型的代码

onlineGeneratorController.codeGeneratesingletablewithouttree(onetomanywebModelVo);

作用  

  调用 `codeGeneratesingletablewithouttree` 方法,传入 `onetomanywebModelVo` 作为参数,生成一对多关系模型的代码。

思路  

  `onetomanywebModelVo` 描述了一对多关系模型的结构,`codeGeneratesingletablewithouttree` 方法会根据这个结构生成对应的代码文件。

---

总结

这段代码的核心思路是通过模拟数据生成不同类型的模型(单表模型、树形结构模型、一对多关系模型),然后调用 `OnlineGeneratorController` 的 `codeGeneratesingletablewithouttree` 方法生成对应的代码。  

每个步骤的作用如下:

1. 初始化数据模型对象(`onewebModelVo`、`treewebModelVo`、`onetomanywebModelVo`)。

2. 设置模板引擎(`FreemakerEngineImpl`)。

3. 调用代码生成方法,根据不同的模型生成代码。

这种设计模式非常适合需要快速生成代码的场景,例如代码生成器、低代码平台等。

2.3代码实现原理

2.2中提到了设计思路以及在什么时候调用什么类什么方法,这些都是在main函数里能看到的 2.3将进入这些类和方法作进一步研究。

先顺着main往下看,WebModelVO是遇到的第一个类,里面的代码定义了一个名为 `WebModelVo` 的 Java 类,它是一个数据模型类(Value Object,VO),用于封装代码生成器所需的相关配置和数据。以下是对代码的详细解释:

1.类定义与注解

```java

@Slf4j

@Data

@SuperBuilder

@AllArgsConstructor

@NoArgsConstructor

@Component

public class WebModelVo implements Serializable {

@Slf4j  

  这是 Lombok 提供的注解,用于自动生成日志对象 `log`,方便在类中直接使用日志功能。

@Data  

  Lombok 注解,自动生成 `getter`、`setter`、`toString`、`equals` 和 `hashCode` 方法。

@SuperBuilder  

  Lombok 注解,支持继承的 Builder 模式,允许通过链式调用的方式创建对象。

@AllArgsConstructor 和 @NoArgsConstructor  

  分别生成全参构造函数和无参构造函数。

@Component

  将该类标记为 Spring 的组件,使其可以被 Spring 容器管理。

implements Serializable

  实现 `Serializable` 接口,表示该类的对象可以被序列化(例如存储到文件或通过网络传输)。

2.字段定义

2.1 基本字段

private String author = "demo"; // 作者名称,默认值为 "demo"

private String testmodulename = ""; // 测试模块名称

private String deploymodulename = ""; // 部署模块名称

private String testuserDefinePackage = ""; // 测试用户自定义包名

private String deployuserDefinePackage = ""; // 部署用户自定义包名

private EnumDeployWay enumDeployWay; // 部署方式枚举

 这些字段用于存储代码生成器的配置信息,例如作者名称、模块名称、包名等。

 部分字段有默认值(如 `author`),其他字段需要外部赋值。

2.2 客户端相关字段

@NotEmpty

@Length(min = 10, max = 50)

private String codefromClientGUID = UUID.randomUUID().toString(); // 客户端生成的唯一标识

```

-@NotEmpty

  表示该字段不能为空。

@Length(min = 10, max = 50)

  表示该字段的长度必须在 10 到 50 之间。

UUID.randomUUID().toString()

  生成一个唯一的标识符,用于标识客户端请求。

2.3 输出目录字段

@NotNull

private String destinationOutPutDir; // 代码生成目录

@Length(min = 0, max = 100)

private String frontDestionOutPutDir; // 前端代码生成目录

@NotNull  

  表示该字段不能为 `null`。

@Length(min = 0, max = 100)  

  表示该字段的长度不能超过 100。

2.4 服务名称与包名

private String servicename = "service"; // 服务名称,默认值为 "service"

@Length(min = 5, max = 50)

private String packageName; // 包名,长度在 5 到 50 之间

servicename

  表示服务名称,默认值为 `"service"`。

packageName

  表示代码生成的包名,长度限制在 5 到 50 之间。

2.5 模型类型与表信息

private String jformType = "1"; // 表单类型,默认值为 "1"

@NotNull

private EnumModelType modeltype; // 模型类型枚举

@NotNull

@Valid

private TableVoDomain tableVoDomain; // 表信息对象

jformType  

  表示表单类型,默认值为 `"1"`。

EnumModelType  

  枚举类型,表示模型的类型(如单表模型、树形模型等)。

TableVoDomain  

  表示表信息的对象,使用 `@Valid` 注解表示需要对该对象进行嵌套验证。

3.设计思路

数据封装  

  `WebModelVo` 类封装了代码生成器所需的所有配置信息,包括作者、模块名称、包名、输出目录、模型类型等。

数据验证:  

  使用 Hibernate Validator 注解(如 `@NotEmpty`、`@NotNull`、`@Length`)对字段进行校验,确保数据的合法性。

默认值  

  部分字段(如 `author`、`servicename`、`jformType`)设置了默认值,简化了对象创建过程。

嵌套对象  

  通过 `TableVoDomain` 对象封装表信息,支持复杂数据结构的嵌套验证。

4.使用场景

代码生成器  

  该类用于代码生成器的配置管理,通过传入不同的 `WebModelVo` 对象,生成不同类型的代码(如单表模型、树形模型等)。

数据校验

  通过 Hibernate Validator 注解,确保传入的数据合法,避免生成错误的代码。

Spring 集成  

  通过 `@Component` 注解,该类可以被 Spring 容器管理,方便在其他组件中注入和使用。

总结

`WebModelVo` 是一个用于代码生成器的数据模型类,封装了代码生成所需的配置信息,并通过注解实现了数据校验和默认值设置。它的设计简洁且易于扩展,适合用于代码生成器、低代码平台等场景。

OneMockWebMode.intWo()的使用

public static WebModelVo initWo() throws Exception{
    WebModelVo wm = initWebModel();
    setWebModelWithoutTree(wm);
    return wm;
}//此方法在main第一个地方用到过 用于给别的变量赋值
//initWo 是一个静态方法,用于初始化并返回一个 WebModelVo 对象。
//该方法调用了两个辅助方法:initWebModel() 和 setWebModelWithoutTree(WebModelVo wm)。

这里的两个辅助方法不再作详细介绍 有兴趣可以观看 他们在同一个目录底下。

OnlineGeneratorController onlineGeneratorController=new OnlineGeneratorController();
onlineGeneratorController.setFreemakerEngine(new FreemakerEngineImpl());

这里创建了onlineGeneratorController这个变量并实例化 下文简称小o

第二行,帮助小o选择了FreemakerEngine接口底下的FreemakerEngineImpl这个类,小o里面的freemakerEngine变量接的就是FreemakerEngineImpl类了

注意!!!这个 FreemakerEngineImpl 类是一个基于 FreeMarker 模板引擎的代码生成器实现类。它的主要功能是根据模板文件和输入的数据模型(Map<String, Object>),生成目标代码文件,在模板路径和目标路径的地方用到了硬编码,直接移植有可能出错。

onlineGeneratorController.codeGeneratesingletablewithouttree(onewebModelVo)

从这一步,正式开始执行引擎作用

这段代码是一个 Spring Boot 控制器中的方法,用于根据传入的 `WebModelVo` 对象生成代码文件。它通过调用 `FreemakerEngine` 实现类(如 `FreemakerEngineImpl`)来处理 FreeMarker 模板,生成目标代码文件。以下是代码的详细解释:

1.方法签名

public Result<?> codeGeneratesingletablewithouttree(@RequestBody @Validated WebModelVo webModelVo) throws Exception

作用

   这是一个 RESTful API 方法,用于处理 POST 请求。

   接收一个 JSON 格式的请求体,并将其转换为 `WebModelVo` 对象。

   使用 `@Validated` 注解对 `WebModelVo` 对象进行校验。

返回值

   返回 `Result<?>` 对象,表示操作结果(成功或失败)。

2.方法逻辑

2.1 初始化模板路径

 定义一个空字符串 `templatepath`,用于存储模板路径。

 创建一个 `ExtTemplateLocaltion` 对象,用于管理模板路径。

2.2 初始化数据模型

 创建一个 `Map<String, Object>` 对象 `map`,用于存储模板中需要替换的变量。

 从 `webModelVo` 中获取模型类型(`enumModelType`),并根据模型类型设置不同的模板路径和数据模型。

2.3 根据模型类型处理不同场景

`default.one`(单表模型)

   设置模板路径为单表模型的路径。

   使用 `OneMapSet` 类生成数据模型(`map`)。

  templatepath = "C:\\Users\\413448405\\Desktop\\codetemplateservice-master\\jeecg-boot\\jeecg-module-system\\jeecg-system-biz\\src\\main\\resources\\jeecg\\code-template-online\\default\\one\\java";

  ParentMapSetFromWebModelVo oneMapSet = new OneMapSet();

  oneMapSet.buildMap(map, webModelVo);

`default.tree`(树形结构模型)

   设置模板路径为树形结构模型的路径。

   使用 `TreeMapSet` 类生成数据模型(`map`)。

  templatepath = "C:\\Users\\413448405\\Desktop\\codetemplateservice-master\\jeecg-boot\\jeecg-module-system\\jeecg-system-biz\\src\\main\\resources\\jeecg\\code-template-online\\default\\tree\\java";

  new TreeMapSet().buildMap(map, webModelVo);

`default.onetomany`(一对多关系模型):

设置模板路径为一对多关系模型的路径。

  使用 `OneToManyMapSet` 类生成数据模型(`map`),包括主表和子表的信息。

  templatepath = "C:\\Users\\413448405\\Desktop\\codetemplateservice-master\\jeecg-boot\\jeecg-module-system\\jeecg-system-biz\\src\\main\\resources\\jeecg\\code-template-online\\erp\\onetomany\\java";

  OneToManyMapSet om = new OneToManyMapSet();

  om.buildMap(map, webModelVo);

  om.buildSonTableMap(map, webModelVo);

  om.buildSonTableColumnMap(map, webModelVo);

  map.put("ftl_description", webModelVo.getTableVoDomain().getTableTxt());

2.4补充数据模型

 向 `map` 中添加当前日期和格式化工具类:

  map.put("currentDate", NonceUtils.nowformat());

  map.put("Format", new SimpleFormat());

 2.5设置生成文件的路径

创建一个 `ExtDestinationLocation` 对象,用于管理生成文件的目标路径。

设置实体名称和包名:

  destinationLocation.setEntityname(webModelVo.getTableVoDomain().getEntityName());

  destinationLocation.setEntitypackage(webModelVo.getPackageName());

 如果 `webModelVo` 中包含测试模块名称,则使用测试模块名称作为包名:

  if (webModelVo.getTestmodulename() != null) {

      destinationLocation.setEntitypackage(webModelVo.getTestmodulename());

  }

2.6 生成文件

 调用 `freemakerEngine.processextenh` 方法,生成目标代码文件:

  freemakerEngine.processextenh(map, templateLocaltion, destinationLocation);

2.7 返回结果

 返回操作成功的消息:

  return Result.ok("转换成功");

3. 代码中的关键点

模板路径

   模板路径是硬编码的,建议将路径配置在配置文件中,便于维护和移植。

数据模型生成

   根据不同的模型类型(单表、树形结构、一对多关系),调用不同的类(如 `OneMapSet`、`TreeMapSet`、`OneToManyMapSet`)生成数据模型。

文件生成

使用 `FreemakerEngine` 实现类(如 `FreemakerEngineImpl`)处理 FreeMarker 模板,生成目标代码文件。

使用方法

3.1如何使用

本程序的要点就在于FreemakerEngine这一部分,引擎有三个输入 分别是map,模板路径,目标路径,简单原理则为将map内容贴到模板上生成到目标路径上。调用OnlineGeneratorController 里的内容可以修改输入的map,更改templatepath可以变更模板位置,更改destinationLocation可以更新目标路径

3.2如何修改?

如果想增加模版类型,就新增一个类挂在Select接口下面,如图

如果想修改生成位置 在下图所示部分修改

destinationLocation类如图部分 修改路径(生成位置)

对原程序的bug修改及简化

4.1 一个bug

Bug位于FreemakerEngineImpl类中,原先代码实现生成结束后,tablename这一位置永远是null,经过debug发现在引擎部分tablenanme根本没有被添加到路径上,经过更改后tablename已经被添加,在图中if和else中用了两种方式,if中使用destinationLocation.getEntitypackage()方法从传入的参数找路径,else则是用String entitypackage = (String) map.get("tableName");直接去上一场map对象里去挖路径。

4.2 Controler层三个if改成接口形式1->3

把它改成接口类型 这样后续改进时候只需要新增类 而不需要在controller里面修改

以前输入方式是直接更改代码,更改为从浏览器输入更为合适。

图中红框为代替controller里if的部分

4.3引擎中几次替换修改为小的方法调用

4.4改进建议

用绝对路径非常不友好,不方便移植。

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

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

相关文章

STM32标准库-I2C通信

文章目录 一、I2C通信1.1 I2C1.2硬件电路1.3I2C时序基本单元1.4I2C时序 二、MPU60502.1简介2.2MPU6050参数2.3硬件电路2.4MPU6050框图 三、I2C外设(硬件)3.1简介3.2I2C框图3.3I2C基本结构3.4主机发送3.5主机接收3.6软件/硬件波形对比1. 时序精度2. 信号稳定性3. 速率与效率4. 波…

使用 Azure LLM Functions 与 Elasticsearch 构建更智能的查询体验

作者&#xff1a;来自 Elastic Jonathan Simon 及 James Williams 试用这个示例房地产搜索应用&#xff0c;它结合了 Azure Gen AI LLM Functions 与 Elasticsearch&#xff0c;提供灵活的混合搜索结果。在 GitHub Codespaces 中查看逐步配置和运行该示例应用的方法。 更多阅读…

模糊查询 的深度技术解析

以下是 模糊查询 的深度技术解析&#xff0c;涵盖核心语法、通配符策略、性能优化及实战陷阱&#xff1a; &#x1f50d; 一、核心运算符&#xff1a;LIKE SELECT * FROM 表名 WHERE 列名 LIKE 模式字符串;&#x1f3af; 二、通配符详解 通配符作用示例匹配案例%任意长度字符…

[论文阅读] (39)EuroSP25 CTINEXUS:基于大模型的威胁情报知识图谱自动构建

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…

强化学习三大分类

核心目标&#xff1a; 教会一个智能体&#xff08;比如机器人、游戏AI、推荐系统&#xff09;通过试错和奖励&#xff0c;学会在某个环境中完成特定任务的最佳策略。 核心角色&#xff1a; 智能体 (Agent)&#xff1a; 学习者&#xff0c;比如玩游戏的小人、控制温度的空调系…

城市排水生命线安全运行监测项目

近年来&#xff0c;城市内涝、污水溢流等问题频发&#xff0c;让排水管网这一"城市生命线"的安全运行备受关注。如何让地下的"毛细血管"更智能、更可靠&#xff1f;本文将带您深入解析城市排水生命线安全运行监测项目的建设逻辑与技术内核&#xff0c;看科…

LeetCode - 34. 在排序数组中查找元素的第一个和最后一个位置

题目 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣&#xff08;LeetCode&#xff09; 思路 查找左边界 初始化 left 0, right nums.size() - 1 当 left < right 时循环&#xff1a; 计算中点 mid left (right - left) / 2 如果 nums[mid] < target…

Tesollo四指灵巧手DG-4F:18自由度与多种抓取模式结合实现高精度操作

Tesollo四指灵巧手 DG-4F 是一款具备 18 自由度的多模态末端执行器&#xff0c;采用模块化结构设计&#xff0c;融合人手灵活性与夹爪高效性特点。该产品兼容 Universal Robots、Techman、Doosan Robotics、Rainbow Robotics 等主流机器人平台&#xff0c;适用于工业自动化、科…

深入浅出JavaScript 原型链:对象继承的“隐形链条”

深入浅出JavaScript 原型链&#xff1a;对象继承的“隐形链条” 在 JavaScript 的世界里&#xff0c;原型链&#xff08;Prototype Chain&#xff09;是一个核心概念。它如同一条隐形的链条&#xff0c;连接着所有对象&#xff0c;使得代码能够高效地共享属性和方法。理解原型…

LINUX中MYSQL的使用

LINUX中MYSQL的使用 MYSQL的数据类型 bool&#xff1a; 布尔类型 0 或者 1 CHAR&#xff1a; 单字符的字符 CHAR&#xff08;n&#xff09;:多字节字符 VARCHAR&#xff08;n&#xff09;&#xff1a;可变长度的字符型 TINYINT &#xff1a; 单字节整型 SMALLINT&#x…

打卡第48天:随机函数与广播机制

知识点回顾&#xff1a; 随机张量的生成&#xff1a;torch.randn函数卷积和池化的计算公式&#xff08;可以不掌握&#xff0c;会自动计算的&#xff09;pytorch的广播机制&#xff1a;加法和乘法的广播机制 ps&#xff1a;numpy运算也有类似的广播机制&#xff0c;基本一致 …

学习昇腾开发的第四天--基本指令

1、查看npu当前状态信息 npu-smi info 2、查看NPU的ID npu-smi info -l3、调用python python3 4、修改用户名 su - HwHiAiUser 5、查看cann版本 cat /usr/local/Ascend/ascend-toolkit/latest/compiler/version.info 6、删除文件夹 sudo rm -rf HelloWorld7、在本地环…

vue3 - 自定义hook

自定义hook 简单点来说就是将人物或者订单的所有数据和方法放在一个ts文件里面 这样便于维护 假如一个人只需要管 人物的模块 那他只需要操作usePerson.ts文件就可以了 //useDog.ts import { ref,reactive} from vue; import axios from axios;export default function(){…

【python】bash: !‘: event not found

报错 # 2. 测试smplx是否工作&#xff08;可能不需要chumpy&#xff09; python -c "import smplx; print(✅ smplx works!)"bash: !: event not found 分析 这是bash的历史扩展问题&#xff0c;感叹号被解释为历史命令。用这些方法解决&#xff1a; &#x1f680…

【Python打卡Day47】注意力热力图可视化@浙大疏锦行

可视化空间注意力热力图的意义&#xff1a; 提升模型可解释性 热力图能直观展示模型决策的依据区域&#xff0c;破除深度学习"黑箱"困境。例如在图像识别中&#xff0c;可以看到模型识别"猫"是因为关注了猫耳和胡须区域&#xff0c;识别"禁止通行&qu…

树状数组 2

L - 树状数组 2 洛谷 - P3368 Description 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某区间每一个数加上 x&#xff1b; 求出某一个数的值。 Input 第一行包含两个整数 N、M&#xff0c;分别表示该数列数字的个数和操作的总个数。…

YOLOv2 技术详解:目标检测的又一次飞跃

&#x1f9e0; YOLOv2 技术详解&#xff1a;目标检测的又一次飞跃 一、前言 在 YOLOv1 提出后&#xff0c;虽然实现了“实时性 单阶段”的突破&#xff0c;但其在精度和小物体检测方面仍有明显不足。为了弥补这些缺陷&#xff0c;Joseph Redmon 等人在 2017 年提出了 YOLOv2…

JAFAR Jack up Any Feature at Any Resolution

GitHub PaPer JAFAR: Jack up Any Feature at Any Resolution 摘要 基础视觉编码器已成为各种密集视觉任务的核心组件。然而&#xff0c;它们的低分辨率空间特征输出需要特征上采样以产生下游任务所需的高分辨率模式。在这项工作中&#xff0c;我们介绍了 JAFAR——一种轻量级…

SamWaf 开源轻量级网站防火墙源码(源码下载)

SamWaf网站防火墙是一款适用于小公司、工作室和个人网站的开源轻量级网站防火墙&#xff0c;完全私有化部署&#xff0c;数据加密且仅保存本地&#xff0c;一键启动&#xff0c;支持Linux&#xff0c;Windows 64位,Arm64。 主要功能&#xff1a; 代码完全开源 支持私有化部署…

79Qt窗口_QDockWidget的基本使用

目录 4.1 浮动窗⼝的创建 4.2 设置停靠的位置 浮动窗⼝ 在 Qt 中&#xff0c;浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗 ⼝⼀般是位于核⼼部件的周围&#xff0c;可以有多个。 4.1 浮动窗⼝的创建 浮动窗⼝的创建是通过 QDockWidget…