代码生成器实现

 代码生成器实现

实现封装元数据的工具类实现代码生成器的代码编写掌握模板创建的

构造数据模型

需求分析

借助Freemarker机制可以方便的根据模板生成文件,同时也是组成代码生成器的核心部分。对于Freemarker而

言,其强调 数据模型 + 模板 = 文件 的思想,所以代码生成器最重要的一个部分之一就是数据模型。在这里数据

模型共有两种形式组成:

  • 数据库中表、字段等信息

针对这部分内容,可以使用元数据读取并封装到java实体类中

  • 用户自定义的数据

为了代码生成器匹配多样的使用环境,可以让用户自定义的数据,并且以key-value的形式配置到properties文件中

接下来针对这两方面的数据进行处理

PropertiesUtils工具类自定义数据

通过PropertiesUtils工具类,统一对properties文件夹下的所有.properties文件进行加载,并存入内存中

package cn.itcast.generate.utils;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;/*** 需要将自定义的配置信息写入到properties文件中*      配置到相对于工程的properties文件夹下*/
public class PropertiesUtils {public static Map<String,String> customMap = new HashMap<>();static {File dir = new File("properties");try {List<File> files = FileUtils.searchAllFile(new File(dir.getAbsolutePath()));for (File file : files) {if(file.getName().endsWith(".properties")) {Properties prop = new Properties();prop.load(new FileInputStream(file));customMap.putAll((Map) prop);}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {PropertiesUtils.customMap.forEach((k, v)->{System.out.println(k+"--"+v);});}
}

骚戴理解:这里的PropertiesUtils工具类的作用就是把properties文件夹下的所有.properties文件读取处理,主要就是用于用户自定义的数据,可能有的数据不是从数据库里面读取的,所以就可以定义在properties配置文件里,然后读取配置文件获取数据,再加载到模板里面

导入代码生成器依赖的配置文件

#SQL类型和java类型替换规则
VARCHAR=String
BIGINT=Long
INT=Integer
DATE=java.util.Date
DATETIME=java.util.Date
DOUBLE=Double
TEXT=String
VARCHAR2=String
NVARCHAR2=String
NUMBER=Long
CHAR=String
MEDIUMTEXT=String
TINYINT=Integer
LONGTEXT=String#Table的前缀或者后缀
tableRemovePrefixes=tb_,co_,pe_,bs_

元数据处理

加载指定数据库表,将表信息转化为实体类对象(Table)

package cn.itcast.generate.utils;import cn.itcast.generate.entity.Column;
import cn.itcast.generate.entity.DataBase;
import cn.itcast.generate.entity.Table;import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;public class DataBaseUtils {//获取到mysql中所有的数据库名称//获取数据库连接public static Connection getConnection(DataBase db) throws Exception {Properties props = new Properties();props.put("remarksReporting","true");//获取数据库的备注信息props.put("user",db.getUserName());props.put("password",db.getPassWord());Class.forName(db.getDriver());//注册驱动return DriverManager.getConnection(db.getUrl(),props);}//获取数据库列表public static List<String> getSchemas(DataBase db) throws Exception {//1.获取元数据Connection connection = getConnection(db);DatabaseMetaData metaData = connection.getMetaData();//2.获取所有数据库列表ResultSet rs = metaData.getCatalogs();List<String> list = new ArrayList<>();while (rs.next()) {list.add(rs.getString(1));}rs.close();connection.close();return list;}/*** 获取数据库中的表和字段构造实体类*      Table对象**  1.参数*      DataBase 数据库对象*  2.操作步骤*      1.获取连接*      2.获取databasemetaData*      3.获取当前数据库中的所有表*      4.获取每个表中的所有字段*      5.封装到java对象中即可*/public static List<Table> getDbInfo(DataBase db) throws  Exception {//1.获取连接Connection connection = getConnection(db);//2.获取元数据DatabaseMetaData metaData = connection.getMetaData();//3.获取当前数据库中的所有表ResultSet tables = metaData.getTables(null, null, "pe_permission", new String[]{"TABLE"});List<Table> list = new ArrayList<>();while (tables.next()) {Table tab = new Table();//i.表名String tableName = tables.getString("TABLE_NAME"); //bs_user  User//ii.类名String className = removePrefix(tableName);//iii.描述String remarks = tables.getString("REMARKS");//iiii.主键(主键可能是组合主键,有多个,所以primaryKeys是多个主键的set集合)ResultSet primaryKeys = metaData.getPrimaryKeys(null, null, tableName);String keys = "";while (primaryKeys.next()) {String keyname = primaryKeys.getString("COLUMN_NAME");keys += keyname+",";}tab.setName(tableName);tab.setName2(className);tab.setComment(remarks);tab.setKey(keys);//处理表中的所有字段ResultSet columns = metaData.getColumns(null, null, tableName, null);List <Column> columnList = new ArrayList<>();while (columns.next()) {Column cn = new Column();//构造Column对象//列名称String columnName = columns.getString("COLUMN_NAME"); //user_id  userId , create_time createTimecn.setColumnName(columnName);//属性名String attName = StringUtils.toJavaVariableName(columnName);cn.setColumnName2(attName);//java类型和数据库类型String dbType = columns.getString("TYPE_NAME");//VARCHAR,DATETIMEcn.setColumnDbType(dbType);String javaType = PropertiesUtils.customMap.get(dbType);cn.setColumnType(javaType);//备注String columnRemark = columns.getString("REMARKS");//VARCHAR,DATETIMEcn.setColumnComment(columnRemark);//是否主键String pri = null;if(StringUtils.contains(columnName ,keys.split(","))) {pri = "PRI";}cn.setColumnKey(pri);columnList.add(cn);}columns.close();tab.setColumns(columnList);list.add(tab);}tables.close();connection.close();return list;}public static String removePrefix(String tableName) {String prefix = PropertiesUtils.customMap.get("tableRemovePrefixes");//bs_,     tb_    , co_    ,String temp = tableName;  //bs_userfor(String pf : prefix.split(",")) {temp = StringUtils.removePrefix(temp,pf,true);}//temp = userreturn StringUtils.makeAllWordFirstLetterUpperCase(temp);}public static void main(String[] args) throws Exception {DataBase db = new DataBase("MYSQL","ihrm");db.setUserName("root");db.setPassWord("111111");List<Table> dbInfo = DataBaseUtils.getDbInfo(db);for (Table table : dbInfo) {List<Column> columns = table.getColumns();for (Column column : columns) {System.out.println(column);}}}
}

骚戴理解:removePrefix方法就是把数据库表名的前缀去掉,然后再转成首字母大写的实体类名称,表名前缀都写在了配置文件里面,所以先通过PropertiesUtils获取配置文件的前缀配置信息,如下所示,然后调用StringUtils的removePrefix方法去掉前缀,最后调用StringUtils的makeAllWordFirstLetterUpperCase方法转成首字母大写

#Table的前缀或者后缀
tableRemovePrefixes=tb_,co_,pe_,bs_

实现代码生成

需求分析

为了代码更加直观和易于调用,实现代码生成共有两个类组成:

  • UI界面统一调用的入口类:GeneratorFacade

方便多种界面调用,主要完成数据模型获取,调用核心代码处理类完成代码生成

  • 代码生成核心处理类:Generator

根据数据模型和模板文件路径,统一生成文件到指定的输出路径

模板生成

  • 配置统一调用入口类GeneratorFacade
package cn.itcast.generate.core;import cn.itcast.generate.entity.DataBase;
import cn.itcast.generate.entity.Settings;
import cn.itcast.generate.entity.Table;
import cn.itcast.generate.utils.DataBaseUtils;
import cn.itcast.generate.utils.PropertiesUtils;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 1.采集用户UI界面输入的数据*      模板位置*      代码生成路径*      工程配置对象 setting*      数据库对象   DataBase* 2.准备数据模型*      1.自定义配置*      2.元数据*      3.setting* 3.调用核心处理类完成代码生成工作*      方法:Generator*/
public class GeneratorFacade {private String templatePath;private String outPath;private Settings settings;private DataBase db;private Generator generator;public GeneratorFacade(String templatePath, String outPath, Settings settings, DataBase db) throws Exception {this.templatePath = templatePath;this.outPath = outPath;this.settings = settings;this.db = db;this.generator = new Generator(templatePath,outPath);}/*** 1.准备数据模型* 2.调用核心处理类完成代码生成工作*/public void generatorByDataBase() throws  Exception {List<Table> tables = DataBaseUtils.getDbInfo(db);for (Table table : tables) {//对每一个Table对象进行代码生成/*** 数据模型* 调用Generator核心处理类*/Map<String,Object> dataModel = getDataModel(table);
//
//            for(Map.Entry<String,Object> entry:dataModel.entrySet()) {
//                System.out.println(entry.getKey() + "--" + entry.getValue());
//            }
//            System.out.println("------------------------");generator.scanAndGenerator(dataModel);}}/*** 根据table对象获取数据模型*/private  Map<String,Object> getDataModel(Table table) {Map<String,Object> dataModel = new HashMap<>();//1.自定义配置dataModel.putAll(PropertiesUtils.customMap);//2.元数据dataModel.put("table",table);  //table.name2//3.settingdataModel.putAll(this.settings.getSettingMap());//4.类型dataModel.put("ClassName",table.getName2());return dataModel;}
}

骚戴理解:通过DataBaseUtils.getDbInfo(db);获取到的是数据库表数据的元数据信息,getDataModel方法的作用是为了封装数据模型,数据模型结合模板生成代码,数据模型包括自定义配置、元数据、setting里面的数据,而ClassName只是为了方便后面拿这个类名而已,所以也封装在其中

  • 处理模板代码生成的核心类Generator
package cn.itcast.generate.core;import cn.itcast.generate.utils.FileUtils;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 代码生成器的核心处理类*      使用Freemarker完成文件生成*             数据模型 + 模板*  数据:*      数据模型*      模板的位置*      生成文件的路径**/
public class Generator {private String templatePath;//模板路径private String outPath;//代码生成路径private Configuration cfg;public Generator(String templatePath, String outPath) throws Exception {this.templatePath = templatePath;this.outPath = outPath;//实例化Configuration对象cfg = new Configuration();//指定模板加载器FileTemplateLoader ftl = new FileTemplateLoader(new File(templatePath));cfg.setTemplateLoader(ftl);}/*** 代码生成*      1.扫描模板路径下的所有模板*      2.对每个模板进行文件生成(数据模型)*/public void scanAndGenerator(Map<String,Object> dataModel) throws Exception {//1.根据模板路径找到此路径下的所有模板文件List<File> fileList = FileUtils.searchAllFile(new File(templatePath));//2.对每个模板进行文件生成for (File file : fileList) {executeGenertor(dataModel,file);}}/*** 对模板进行文件生成* @param dataModel : 数据模型* @param file      : 模板文件*            模板文件:c:com.ihrm.system.abc.java*/private void executeGenertor(Map<String,Object> dataModel,File file) throws Exception {//1.文件路径处理   (E:\模板\${path1}\${path2}\${path3}\${ClassName}.java)//templatePath : E:\模板\String templateFileName = file.getAbsolutePath().replace(this.templatePath,"");String outFileName = processTemplateString(templateFileName,dataModel);//2.读取文件模板Template template = cfg.getTemplate(templateFileName);template.setOutputEncoding("utf-8");//指定生成文件的字符集编码//3.创建文件File file1 = FileUtils.mkdir(outPath, outFileName);//4.模板处理(文件生成)FileWriter fw = new FileWriter(file1);template.process(dataModel,fw);fw.close();}public String processTemplateString(String templateString,Map dataModel) throws Exception {StringWriter out = new StringWriter();Template template = new Template("ts",new StringReader(templateString),cfg);template.process(dataModel,out);return out.toString();}public static void main(String[] args) throws Exception {String templatePath = "C:\\Users\\ThinkPad\\Desktop\\ihrm\\day13\\资源\\测试\\模板";String outPath = "C:\\Users\\ThinkPad\\Desktop\\ihrm\\day13\\资源\\测试\\生成代码路径";Generator generator = new Generator(templatePath, outPath);Map <String,Object> dataModel = new HashMap<>();dataModel.put("username","张三");generator.scanAndGenerator(dataModel);}}

骚戴理解:executeGenertor方法这段代码的作用是根据模板文件和数据模型生成代码文件。

1. String templateFileName = file.getAbsolutePath().replace(this.templatePath,"");

这行代码的作用是将模板文件的绝对路径中的模板根路径(即templatePath)替换为空字符串,得到模板文件名(不包含根路径)。

2. String outFileName = processTemplateString(templateFileName,dataModel);

这行代码的作用是将模板文件名中的变量替换为具体的值,得到输出文件的文件名。

3. Template template = cfg.getTemplate(templateFileName);

这行代码的作用是根据模板文件名,从Configuration对象中获取对应的Template对象。

4. template.setOutputEncoding("utf-8");

这行代码的作用是指定生成文件的字符集编码为UTF-8。

5. File file1 = FileUtils.mkdir(outPath, outFileName);

这行代码的作用是根据输出路径和输出文件名,创建输出文件。

6. FileWriter fw = new FileWriter(file1);

这行代码的作用是创建一个FileWriter对象,用于将模板处理后的结果输出到指定的文件中。

7. template.process(dataModel,fw);

这行代码的作用是将数据模型和FileWriter对象作为参数传入Template的process方法中,根据数据模型中的值,将模板文件中的变量替换为具体的值,并将输出结果写入FileWriter对象中。

8. fw.close();

这行代码的作用是关闭FileWriter对象,释放资源。

路径处理

使用字符串模板对文件生成路径进行统一处理

    public String processTemplateString(String templateString,Map dataModel) throws Exception {StringWriter out = new StringWriter();Template template = new Template("ts",new StringReader(templateString),cfg);template.process(dataModel,out);return out.toString();}

骚戴理解:这段代码是使用FreeMarker模板引擎来处理模板字符串,将模板字符串中的变量替换为具体的值,最终返回替换后的字符串。

1.StringWriter out = new StringWriter();

这行代码的作用是创建一个StringWriter对象,用于接收模板处理后的输出结果。

2.Template template = new Template("ts",new StringReader(templateString),cfg);

这行代码的作用是创建一个Template对象,用于解析模板字符串并进行变量替换。其中,第一个参数是模板名称(随意取名),第二个参数是StringReader对象,用于读取模板字符串,第三个参数是Configuration对象,用于配置模板引擎的相关参数。

3.template.process(dataModel,out);

这行代码的作用是将数据模型和输出流作为参数传入Template的process方法中,根据数据模型中的值,将模板字符串中的变量替换为具体的值,并将输出结果写入输出流。

4.return out.toString();

这行代码的作用是将输出流中的内容转换为字符串,并返回该字符串。

制作模板

模板制作的约定

  • 模板位置

模板统一放置到相对于当前路径的模板文件夹下

  • 自定义数据

自定义的数据以 .propeties 文件(key-value)的形式存放入相对于当前路径的 properties 文件夹下

  • 数据格式

名称

说明

author

作者

project

工程名

path1

包名1

path2

包名2

path3

包名3

pPackage

完整包名

projectComment

工程描述

ClassName

类名

table

数据库信息

table中数据内容:

name

表名

comment

表注释

key

表主键

columns

所有列信息

columnName

字段列名

columnName2

属性名

columnType

java类型

columnDbType

数据库类型

columnComment

注释

columnKey

是否主键

需求分析

制作通用的SpringBoot程序的通用模板

  • 实体类

类路径,类名,属性列表(getter,setter方法)

  • 持久化层

类路径,类名,引用实体类

  • 业务逻辑层

类路径,类名,引用实体类,引用持久化层代码

  • 视图层

类路径,类名,引用实体类,引用业务逻辑层代码,请求路径

  • 配置文件

pom文件,springboot配置文件

SpringBoot通用模板

实体类

package ${pPackage}.pojo;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;@Entity
@Table(name = "${table.name}")
public class ${ClassName} implements Serializable {//这里table.columns是因为上面数据模型里面放的是 dataModel.put("table",table);<#list table.columns as column><#if column.columnKey??>@Id</#if>private ${column.columnType} ${column.columnName2};</#list><#list table.columns as column>public void set${column.columnName2?cap_first}(${column.columnType} value) {this.${column.columnName2} = value;}public ${column.columnType} get${column.columnName2?cap_first}() {return this.${column.columnName2};}</#list>
}

骚戴理解:这段代码使用FreeMarker模板语言生成Java类的属性和getter/setter方法。

具体来说,这段代码包含了以下两个部分:

1. 属性生成部分

-<#list table.columns as column>:这行代码使用FreeMarker的list指令,遍历数据模型中的table.columns字段,将每个元素赋值给变量column。

-<#if column.columnKey??>:这行代码使用FreeMarker的if指令,判断当前列是否为主键列。

-@Id:如果当前列是主键列,则生成@Id注解。

-<#if>:if指令的结束标签。

-private ${column.columnType} ${column.columnName2};:生成Java类的私有属性,属性名和属性类型分别对应数据模型中的column.columnName2和column.columnType。

-</#list>:list指令的结束标签。

2. getter/setter方法生成部分

-<#list table.columns as column>:这行代码使用FreeMarker的list指令,遍历数据模型中的table.columns字段,将每个元素赋值给变量column。

-public void set${column.columnName2?cap_first}(${column.columnType} value) {:生成Java类的setter方法,方法名为set+属性名(首字母大写),方法参数类型和属性类型相同,方法体为将参数值赋值给属性,其中?cap_first是使用内置函数,可以把column.columnName2变成首字母大写。

-public ${column.columnType} get${column.columnName2?cap_first}() {:生成Java类的getter方法,方法名为get+属性名(首字母大写),方法返回值类型为属性类型,方法体为返回属性值。

-</#list>:list指令的结束标签。

总之,这段代码的作用是根据数据模型中的表结构信息,生成Java类的属性和getter/setter方法。

Service层

<#assign classNameLower = ClassName ? uncap_first>
package ${pPackage}.service;import com.ihrm.common.utils.IdWorker;
import ${pPackage}.dao.${ClassName}Dao;
import ${pPackage}.pojo.${ClassName};
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service
public class ${ClassName}Service {@Autowiredprivate ${ClassName}Dao ${classNameLower}Dao;@Autowiredprivate IdWorker idWorker;/*** 保存*/public void add(${ClassName} ${classNameLower}) {//基本属性的设置String id = idWorker.nextId()+"";${classNameLower}.setId(id);${classNameLower}Dao.save(${classNameLower});}/*** 更新*/public void update(${ClassName} ${classNameLower}) {${classNameLower}Dao.save(${classNameLower});}/*** 删除*/public void deleteById(String id) {${classNameLower}Dao.deleteById(id);}/*** 根据id查询*/public ${ClassName} findById(String id) {return ${classNameLower}Dao.findById(id).get();}/*** 查询列表*/public List<${ClassName}> findAll() {return ${classNameLower}Dao.findAll();}
}

Controller层

<#assign classNameLower = ClassName ? uncap_first>
package ${pPackage}.controller;import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;
import com.ihrm.common.exception.CommonException;import ${pPackage}.service.${ClassName}Service;
import ${pPackage}.pojo.${ClassName};
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;//解决跨域问题
@CrossOrigin
@RestController
@RequestMapping(value="/${classNameLower}")
public class ${ClassName}Controller {@Autowiredprivate ${ClassName}Service ${classNameLower}Service;//保存@RequestMapping(value="",method = RequestMethod.POST)public Result save(@RequestBody ${ClassName} ${classNameLower})  {//业务操作${classNameLower}Service.add(${classNameLower});return new Result(ResultCode.SUCCESS);}//根据id更新@RequestMapping(value = "/{id}",method = RequestMethod.PUT)public Result update(@PathVariable(value="id") String id, @RequestBody ${ClassName} ${classNameLower} ) {//业务操作${classNameLower}.setId(id);${classNameLower}Service.update(${classNameLower});return new Result(ResultCode.SUCCESS);}//根据id删除@RequestMapping(value="/{id}",method = RequestMethod.DELETE)public Result delete(@PathVariable(value="id") String id) {${classNameLower}Service.deleteById(id);return new Result(ResultCode.SUCCESS);}//根据id查询@RequestMapping(value="/{id}",method = RequestMethod.GET)public Result findById(@PathVariable(value="id") String id) throws CommonException {${ClassName} ${classNameLower} = ${classNameLower}Service.findById(id);return new Result(ResultCode.SUCCESS,${classNameLower});}//查询全部@RequestMapping(value="",method = RequestMethod.GET)public Result findAll() {List<${ClassName}> list = ${classNameLower}Service.findAll();Result result = new Result(ResultCode.SUCCESS);result.setData(list);return result;}
}

Dao层

package ${pPackage}.dao;import ${pPackage}.pojo.${ClassName};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;public interface ${ClassName}Dao extends JpaRepository<${ClassName},String> ,JpaSpecificationExecutor<${ClassName}> {
}

配置文件

  • application.yml
server: port: 9001
spring: application:  name: ${project}-${path3} #指定服务名datasource:  driverClassName: ${driverName}url: ${url}username: ${dbuser}password: ${dbpassword}jpa: database: MySQLshow-sql: true
  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>${path2}_parent</artifactId><groupId>${path1}.${path2}</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>${path2}_${project}</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>${path1}.${path2}</groupId><artifactId>${path2}_common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
</project>

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

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

相关文章

Java idea查看自定义注解的调用地方

Java idea查看自定义注解的调用地方

学信息系统项目管理师第4版系列27_项目集管理和项目组合管理

1. 项目集发起人 1.1. 负责承诺将组织的资源应用于项目集&#xff0c;并致力于使项目集取得成功的人 1.2. 典型职责 1.2.1. 为项目集提供资金&#xff0c;确保项目集目标与战略愿景保持一致&#xff1b; 1.2.2. 使效益实现交付 1.2.3. 消除项目集管理与交付的困难和障碍 …

Qt 布局(QLayout 类QStackedWidget 类) 总结

一、QLayout类(基本布局) QLayout类是Qt框架中用于管理和排列QWidget控件的布局类。它提供了一种方便而灵活的方式来自动布局QWidget控件。QLayout类允许您以一种简单的方式指定如何安排控件&#xff0c;并能够自动处理控件的位置和大小&#xff0c;以使其适应更改的父窗口的大…

排序优化:如何实现一个通用的、高性能的排序函数?

文章来源于极客时间前google工程师−王争专栏。 几乎所有的编程语言都会提供排序函数&#xff0c;比如java中的Collections.sort()。在平时的开发中&#xff0c;我们都是直接使用&#xff0c;这些排序函数是如何实现的&#xff1f;底层都利用了哪种排序算法呢&#xff1f; 问题…

WPF DataGrid详细列表手动显示与隐藏

设置显示序号与折叠显示样式 <DataTemplate x:Key"dtNum"><Button BorderBrush"Transparent" Style"{x:Null}" Click"BtnRowDetail_ShowHideClick" FontSize"16" Background"Transparent"><Stack…

【ELK 使用指南】ELK + Filebeat 分布式日志管理平台部署

ELK和EFLK 一、前言1.1 日志分析的作用1.2 需要收集的日志1.3 完整日志系统的基本特征 二、ELK概述2.1 ELK简介2.2 为什么要用ELK?2.3 ELK的组件 三、ELK组件详解3.1 Logstash3.1.1 简介3.1.2 Logstash命令常用选项3.1.3 Logstash 的输入和输出流3.1.4 Logstash配置文件 3.2 E…

零代码编程:用ChatGPT批量采集bookroo网页上的英文书目列表

bookroo网页上有很多不错的英文图书书目。比如这个关于儿童花样滑冰的书单&#xff1a; https://bookroo.com/explore/books/topics/ice-skating 怎么批量下载下来呢&#xff1f; 这个网页是动态网页&#xff0c;要爬取下来比较麻烦&#xff0c;可以先查看源代码&#xff0c;…

Leetcode622.设计循环队列

本专栏内容为&#xff1a;leetcode刷题专栏&#xff0c;记录了leetcode热门题目以及重难点题目的详细记录 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Leetcode &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &…

第五十六章 学习常用技能 - 执行 SQL 查询

文章目录 第五十六章 学习常用技能 - 执行 SQL 查询执行 SQL 查询检查对象属性 第五十六章 学习常用技能 - 执行 SQL 查询 执行 SQL 查询 要运行 SQL 查询&#xff0c;请在管理门户中执行以下操作&#xff1a; 选择系统资源管理器 > SQL。如果需要&#xff0c;请选择标题…

苹果修复了旧款iPhone上的iOS内核零日漏洞

导语 近日&#xff0c;苹果发布了针对旧款iPhone和iPad的安全更新&#xff0c;回溯了一周前发布的补丁&#xff0c;解决了两个被攻击利用的零日漏洞。这些漏洞可能导致攻击者在受影响的设备上提升权限或执行任意代码。本文将介绍这些漏洞的修复情况以及苹果在修复漏洞方面的持续…

创邻科技Galaxybase—激活数据要素的核心引擎

10月11日下午&#xff0c;创邻科技创始人张晨博士受杭州电子科技大学邀请&#xff0c;前往杭电校园开展交流分享。交流会中&#xff0c;张晨博士为现场的师生带来一场题为《图数据库——激活数据要素的新基建》的精彩分享&#xff0c;探讨数字经济时代底层技术的创新价值与图技…

【Java学习之道】线程的概念与作用

引言 今天我们将探索多线程编程的基础概念和作用。对于初学者来说&#xff0c;掌握多线程编程是迈向Java高级技能的重要一步。通过本章的学习&#xff0c;你将了解线程是什么以及它在程序开发中的重要性&#xff0c;为你进一步深入学习和实际工作打下坚实的基础。让我们一起来…

基于微服务+Java+Spring Cloud开发的建筑工地智慧平台源码 云平台多端项目源码

建筑工地智慧平台源码&#xff0c;施工管理端、项目监管端、数据大屏端、移动APP端全套源码 技术架构&#xff1a;微服务JavaSpring Cloud VueUniApp MySql自主版权实际应用案例演示 建筑工地智慧平台已应用于线上巡查、质量管理、实名制管理、危大工程管理、运渣车管理、绿色…

【idea】 java: 找不到符号

idea 启动时提示 java: 找不到符号 java: 找不到符号 符号: 方法 getCompanyDisputeCount() 位置: 类型为com.yang.entity.AreaAnalyse的变量 areaAnalyse 在setting ——> Compiler ——>Shared build process VM options: 添加&#xff1a; -Djps.track.ap.dep…

快速自动化处理JavaScript渲染页面

在进行网络数据抓取时&#xff0c;许多网站使用了JavaScript来动态加载内容&#xff0c;这给传统的网络爬虫带来了一定的挑战。本文将介绍如何使用Selenium和ChromeDriver来实现自动化处理JavaScript渲染页面&#xff0c;并实现有效的数据抓取。 1、Selenium和ChromeDriver简介…

【从零开始学习Redis | 第三篇】在Java中操作Redis

前言&#xff1a; 本文算是一期番外&#xff0c;介绍一下如何在Java中使用Reids &#xff0c;而其实基于Java我们有很多的开源框架可以用来操作redis&#xff0c;而我们今天选择介绍的是其中比较常用的一款&#xff1a;Spring Data Redis 目录 前言&#xff1a; Spring Data…

HTML笔记

注释标签&#xff1a;<!-- --> 标题标签&#xff1a;&#xff08;作用范围依次递减&#xff09; <h1></h1> <h2></h2> <h3></h3> <h4></h4> <h5></h5> <h6></h6> 段落标签&#xff1a;<p&g…

NewStarCTF 2023 公开赛道 WEEK2|Crypto

目录 T1.滴啤 T2.不止一个pi T3.halfcandecode T4.Rotate Xor T5.broadcast T6.partial decrypt T1.滴啤 下载题目附件&#xff0c;我们获得到以下代码。 from Crypto.Util.number import * import gmpy2 from flag import flag def gen_prime(number):p getPrime(numb…

[动手学深度学习]生成对抗网络GAN学习笔记

论文原文&#xff1a;Generative Adversarial Nets (neurips.cc) 李沐GAN论文逐段精读&#xff1a;GAN论文逐段精读【论文精读】_哔哩哔哩_bilibili 论文代码&#xff1a;http://www.github.com/goodfeli/adversarial Ian, J. et al. (2014) Generative adversarial network…

VSCode自定义代码块详解

第一步&#xff1a;点击文件-首选项-用户代码片段 第二步&#xff1a;选择代码块作用域的文件类型 类型一&#xff1a;全局作用域 这种类型的代码块是创建在vscode软件内部的文件。是跟随这当前安装的vscode这个软件的&#xff0c;不会随着项目的关闭而失效&#xff0c;会一直存…