视频教程

大家好,我录制的视频《Java 之优雅编程之道》已经在 CSDN 学院发布了,有兴趣的同学可以购买观看,相信大家一定会收获到很多知识的。谢谢大家的支持……

视频地址:http://edu.csdn.net/lecturer/994

提出问题

如何利用 Java + Freemarker 实现代码生成器?

解决问题

* 前言 *

做业务开发的时候,经常要根据建立好的数据库表,生成相关的 Model , DTO , Service, Controller , DAO 等等。包括基本的增删改查。而这些细活往往比较简单且没有挑战性,纯粹苦力活。因此,根据公司的框架,开发一个代码生成器是很有必要的。

这里:假如你有一定的 java 基础;假如你熟悉 freemarker 模板引擎;假如你熟悉 MVC 框架;假如你熟悉 Spring Data 框架

* 技术选型 *

由于代码生成器是要生成很多文件的,包 Test.java , TestDTO.java ,TestController.java , TestServiceImpl.java , ITestService.java , TestDAO.java 等等这些文件。所有考虑用 freemarker 强大的模板引擎,制作相关的模板。

* 实现思路 *

首先,假如在数据库中有一张表 ay_test.

CREATE TABLE "public"."ay_test" ("id" varchar(32) COLLATE "default" NOT NULL,"name" varchar(10) COLLATE "default","birth_date" timestamp(6),"remark" text COLLATE "default",CONSTRAINT "ay_test_pkey" PRIMARY KEY ("id")
)

我们首先要获取数据库的连接,这里我只贴出相关的代码。

private final String URL = "jdbc:postgresql://192.168.3.160:10655/cibpm";
private final String USER = "postgres";
private final String PASSWORD = "888888";
private final String DRIVER = "org.postgresql.Driver";public Connection getConnection() throws Exception{Class.forName(DRIVER);Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);return connection;
}

获取数据库表的元数据

private final String changeTableName = replaceUnderLineAndUpperCase(tableName);Connection connection = getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");

最后根据元数据获取表字段,注释等等,生成相关的文件

代码实现

Java 代码实现

package com.evada.inno.pm.code.generate.util;
import com.evada.inno.pm.code.generate.model.ColumnClass;import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 描述:代码生成器* Created by Ay on 2017/5/1.*/
public class CodeGenerateUtils {private final String AUTHOR = "Ay";private final String CURRENT_DATE = "2017/05/03";private final String tableName = "tm_project_quality_problem";private final String packageName = "com.evada.pm.process.manage";private final String tableAnnotation = "质量问题";private final String URL = "jdbc:postgresql://192.168.3.160:10655/cibpm";private final String USER = "postgres";private final String PASSWORD = "888888";private final String DRIVER = "org.postgresql.Driver";private final String diskPath = "D://";private final String changeTableName = replaceUnderLineAndUpperCase(tableName);public Connection getConnection() throws Exception{Class.forName(DRIVER);Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);return connection;}public static void main(String[] args) throws Exception{CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();codeGenerateUtils.generate();}public void generate() throws Exception{try {Connection connection = getConnection();DatabaseMetaData databaseMetaData = connection.getMetaData();ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");//生成Mapper文件generateMapperFile(resultSet);//生成Dao文件generateDaoFile(resultSet);//生成Repository文件generateRepositoryFile(resultSet);//生成服务层接口文件generateServiceInterfaceFile(resultSet);//生成服务实现层文件generateServiceImplFile(resultSet);//生成Controller层文件generateControllerFile(resultSet);//生成DTO文件generateDTOFile(resultSet);//生成Model文件generateModelFile(resultSet);} catch (Exception e) {throw new RuntimeException(e);}finally{}}private void generateModelFile(ResultSet resultSet) throws Exception{final String suffix = ".java";final String path = diskPath + changeTableName + suffix;final String templateName = "Model.ftl";File mapperFile = new File(path);List<ColumnClass> columnClassList = new ArrayList<>();ColumnClass columnClass = null;while(resultSet.next()){//id字段略过if(resultSet.getString("COLUMN_NAME").equals("id")) continue;columnClass = new ColumnClass();//获取字段名称columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));//获取字段类型columnClass.setColumnType(resultSet.getString("TYPE_NAME"));//转换字段名称,如 sys_name 变成 SysNamecolumnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));//字段在数据库的注释columnClass.setColumnComment(resultSet.getString("REMARKS"));columnClassList.add(columnClass);}Map<String,Object> dataMap = new HashMap<>();dataMap.put("model_column",columnClassList);generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateDTOFile(ResultSet resultSet) throws Exception{final String suffix = "DTO.java";final String path = "D://" + changeTableName + suffix;final String templateName = "DTO.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateControllerFile(ResultSet resultSet) throws Exception{final String suffix = "Controller.java";final String path = diskPath + changeTableName + suffix;final String templateName = "Controller.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateServiceImplFile(ResultSet resultSet) throws Exception{final String suffix = "ServiceImpl.java";final String path = diskPath + changeTableName + suffix;final String templateName = "ServiceImpl.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateServiceInterfaceFile(ResultSet resultSet) throws Exception{final String prefix = "I";final String suffix = "Service.java";final String path = diskPath + prefix + changeTableName + suffix;final String templateName = "ServiceInterface.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateRepositoryFile(ResultSet resultSet) throws Exception{final String suffix = "Repository.java";final String path = diskPath + changeTableName + suffix;final String templateName = "Repository.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateDaoFile(ResultSet resultSet) throws Exception{final String suffix = "DAO.java";final String path = diskPath + changeTableName + suffix;final String templateName = "DAO.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateMapperFile(ResultSet resultSet) throws Exception{final String suffix = "Mapper.xml";final String path = diskPath + changeTableName + suffix;final String templateName = "Mapper.ftl";File mapperFile = new File(path);Map<String,Object> dataMap = new HashMap<>();generateFileByTemplate(templateName,mapperFile,dataMap);}private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{Template template = FreeMarkerTemplateUtils.getTemplate(templateName);FileOutputStream fos = new FileOutputStream(file);dataMap.put("table_name_small",tableName);dataMap.put("table_name",changeTableName);dataMap.put("author",AUTHOR);dataMap.put("date",CURRENT_DATE);dataMap.put("package_name",packageName);dataMap.put("table_annotation",tableAnnotation);Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);template.process(dataMap,out);}public String replaceUnderLineAndUpperCase(String str){StringBuffer sb = new StringBuffer();sb.append(str);int count = sb.indexOf("_");while(count!=0){int num = sb.indexOf("_",count);count = num + 1;if(num != -1){char ss = sb.charAt(count);char ia = (char) (ss - 32);sb.replace(count , count + 1,ia + "");}}String result = sb.toString().replaceAll("_","");return StringUtils.capitalize(result);}}
FreeMarkerTemplateUtils 工具类

FreeMarkerTemplateUtils 工具类用来配置模板所在的路径

package com.evada.inno.pm.code.generate.util;import com.evada.inno.core.exception.BusinessException;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;import java.io.IOException;/*** Created by Ay on 2016/7/27.*/
public class FreeMarkerTemplateUtils {private FreeMarkerTemplateUtils(){}private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);static{//这里比较重要,用来指定加载模板所在的路径CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/templates"));CONFIGURATION.setDefaultEncoding("UTF-8");CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);}public static Template getTemplate(String templateName) throws IOException {try {return CONFIGURATION.getTemplate(templateName);} catch (IOException e) {throw e;}}public static void clearCache() {CONFIGURATION.clearTemplateCache();}
}
实体类 ColumnClass

ColumnClass 用来封装 数据库表元数据的信息,如字段名称,字段类型,字段注释等等。

package com.evada.inno.pm.code.generate.model;/*** 数据库字段封装类* Created by Ay on 2017/5/3.*/
public class ColumnClass {/** 数据库字段名称 **/private String columnName;/** 数据库字段类型 **/private String columnType;/** 数据库字段首字母小写且去掉下划线字符串 **/private String changeColumnName;/** 数据库字段注释 **/private String columnComment;public String getColumnComment() {return columnComment;}public void setColumnComment(String columnComment) {this.columnComment = columnComment;}public String getColumnName() {return columnName;}public void setColumnName(String columnName) {this.columnName = columnName;}public String getColumnType() {return columnType;}public void setColumnType(String columnType) {this.columnType = columnType;}public String getChangeColumnName() {return changeColumnName;}public void setChangeColumnName(String changeColumnName) {this.changeColumnName = changeColumnName;}
}

freemarker 模板文件

Freemarker 的模板文件,后缀都是以 ftl 结尾的。

Model.ftl 模型模板

Model.ftl 可以生成字段的属性,并且可以生成字段属性对应的 set 和 get 方法,包括字段在数据库中对应的注释,以及一些该引入的包和类注释。

package ${package_name}.model;
import com.evada.inno.common.domain.BaseModel;
import com.evada.inno.common.listener.ICreateListenable;
import com.evada.inno.common.listener.IDeleteListenable;
import com.evada.inno.common.listener.IModifyListenable;
import org.hibernate.annotations.Where;
import javax.persistence.*;
import java.util.Date;/**
* 描述:${table_annotation}模型
* @author ${author}
* @date ${date}
*/
@Entity
@Table(name="${table_name_small}")
@Where(clause = "status > '0'")
@Inheritance(strategy= InheritanceType.SINGLE_TABLE)
public class ${table_name} extends BaseModel implements ICreateListenable,IModifyListenable,IDeleteListenable {<#if model_column?exists><#list model_column as model>/***${model.columnComment!}*/<#if (model.columnType = 'varchar' || model.columnType = 'text')>@Column(name = "${model.columnName}",columnDefinition = "VARCHAR")private String ${model.changeColumnName?uncap_first};</#if><#if model.columnType = 'timestamp' >@Column(name = "${model.columnName}",columnDefinition = "TIMESTAMP")private Date ${model.changeColumnName?uncap_first};</#if></#list></#if><#if model_column?exists>
<#list model_column as model>
<#if (model.columnType = 'varchar' || model.columnType = 'text')>public String get${model.changeColumnName}() {return this.${model.changeColumnName?uncap_first};}public void set${model.changeColumnName}(String ${model.changeColumnName?uncap_first}) {this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};}</#if>
<#if model.columnType = 'timestamp' >public Date get${model.changeColumnName}() {return this.${model.changeColumnName?uncap_first};}public void set${model.changeColumnName}(Date ${model.changeColumnName?uncap_first}) {this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};}</#if>
</#list>
</#if>}
DTO.ftl 模板

DTO.ftl 文件用来生产 DTO 值对象,该对象继承 Model.ftl 文件中的对象。

package ${package_name}.dto;import ${package_name}.model.${table_name};/**
* 描述:${table_annotation}DTO
* @author ${author}
* @date ${date}
*/
public class ${table_name}DTO extends ${table_name}{}
Service.ftl 模板

Service.ftl 模板用来生成服务层实现类,在模板中已经添加了增 ,删,改,查等方法,同时可以注入 DAO 和 repository 到 service 中,一旦文件生成,就不需要我们去写了,很方便,提高开发的效率。

package ${package_name}.service.impl;
import com.evada.inno.core.service.impl.BaseServiceImpl;
import ${package_name}.model.${table_name};
import ${package_name}.repository.${table_name}Repository;
import ${package_name}.service.I${table_name}Service;
import ${package_name}.repository.mybatis.${table_name}DAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ${package_name}.dto.${table_name}DTO;
import org.apache.commons.beanutils.BeanUtils;
import com.evada.inno.core.enums.StatusEnum;/**
* 描述:${table_annotation} 服务实现层
* @author ${author}
* @date ${date}
*/
@Service
public class ${table_name}ServiceImpl extends BaseServiceImpl<${table_name}, String> implements I${table_name}Service {@Autowiredprivate ${table_name}DAO ${table_name?uncap_first}DAO;@Autowiredprivate ${table_name}Repository ${table_name?uncap_first}Repository;@Overridepublic ${table_name}DTO findDTOById(String id) throws Exception {${table_name}DTO ${table_name?uncap_first}DTO = ${table_name?uncap_first}DAO.findDTOById(id);return ${table_name?uncap_first}DTO;}@Overridepublic ${table_name}DTO create${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {${table_name} ${table_name?uncap_first} = new ${table_name}();BeanUtils.copyProperties(${table_name?uncap_first},${table_name?uncap_first}DTO);${table_name?uncap_first}.setStatus(StatusEnum.ENABLE.toString());${table_name?uncap_first} = ${table_name?uncap_first}Repository.saveAndFlush(${table_name?uncap_first});return this.findDTOById(${table_name?uncap_first}.getId());}@Overridepublic ${table_name}DTO update${table_name}(${table_name}DTO ${table_name?uncap_first}DTO)throws Exception {${table_name} ${table_name?uncap_first} = new ${table_name}();BeanUtils.copyProperties(${table_name?uncap_first},${table_name?uncap_first}DTO);${table_name?uncap_first} = ${table_name?uncap_first}Repository.saveAndFlush(${table_name?uncap_first});return this.findDTOById(${table_name?uncap_first}.getId());}
Interface.ftl 模板

Interface.ftl 用来生成服务层接口,接口中定义了增,删,改,查等接口。

package ${package_name}.service;
import com.evada.inno.core.service.IBaseService;
import ${package_name}.model.${table_name};
import ${package_name}.dto.${table_name}DTO;
/**
* 描述:${table_annotation} 服务实现层接口
* @author ${author}
* @date ${date}
*/
public interface I${table_name}Service extends IBaseService<${table_name},String> {/*** 描述:根据Id获取DTO* @param id*/${table_name}DTO findDTOById(String id)throws Exception;${table_name}DTO create${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception;void delete${table_name}(String id) throws Exception;${table_name}DTO update${table_name}(${table_name}DTO ${table_name?uncap_first}DTO) throws Exception;}
Respontory.ftl 模板

Respontory.ftl 用来生成 Repository 文件,这一块是 Spring Data 的内容,可能不同的公司,使用的框架不一样。

package ${package_name}.repository;
import com.evada.inno.core.repository.BaseJpaRepository;
import ${package_name}.model.${table_name};/**
* 描述:${table_annotation} Repository接口
* @author ${author}
* @date ${date}
*/
public interface ${table_name}Repository extends BaseJpaRepository<${table_name}, String> {}
Mappter.ftl 模板

Mappter.ftl 用来生成 MyBatis 使用到的 mappter 文件,在文件中,定义了查询的 sql 语句。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="${package_name}.repository.mybatis.${table_name}DAO"><resultMap id="${table_name}DTOResultMap" type="${package_name}.dto.${table_name}DTO"></resultMap><sql id="findDtoSql">select * from (select * from  ${table_name_small} temp) t</sql><select id="findDTOById" parameterType="String" resultMap="${table_name}DTOResultMap"><include refid="findDtoSql"></include><where>and t.id = ${r'#{id}'}</where></select><select id="find${table_name}Page" parameterType="${package_name}.dto.${table_name}DTO" resultMap="${table_name}DTOResultMap"><include refid="findDtoSql" /><where></where></select></mapper>
Controller.ftl 模板

Controller.ftl 文件用来生成控制层类,类中已经帮我们生成了,增,删,改,查等路由。同时可以注入接口道控制层中。

package ${package_name}.controller;
import com.evada.inno.core.annotation.Rest;
import ${package_name}.service.I${table_name}Service;
import ${package_name}.model.${table_name};
import ${package_name}.dto.${table_name}DTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.http.MediaType;
import com.evada.inno.common.domain.ResultData;
import com.evada.inno.core.util.AssertUtils;/**
* 描述:${table_annotation}控制层
* @author ${author}
* @date ${date}
*/
@Rest(${table_name}.class)
public class ${table_name}Controller {@Autowiredprivate I${table_name}Service ${table_name?uncap_first}Service;/*** 描述:根据Id 查询* @param id  ${table_annotation}id*/@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)public ResultData findById(@PathVariable("id") String id)throws Exception {${table_name}DTO ${table_name?uncap_first}DTO = ${table_name?uncap_first}Service.findDTOById(id);AssertUtils.checkResourceFound(${table_name?uncap_first}DTO);return new ResultData(${table_name}DTO.class, ${table_name?uncap_first}DTO);}/*** 描述:创建${table_annotation}* @param ${table_name?uncap_first}DTO  ${table_annotation}DTO*/@RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)public ResultData create(@RequestBody ${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {return new ResultData(${table_name}.class,${table_name?uncap_first}Service.create${table_name}(${table_name?uncap_first}DTO));}/*** 描述:删除${table_annotation}* @param id ${table_annotation}id*/@RequestMapping(value = "/{id}/bulk", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)public void deleteById(@PathVariable("id") String id) throws Exception {${table_name?uncap_first}Service.deleteById(id);}/*** 描述:更新${table_annotation}* @param id ${table_annotation}id*/@RequestMapping(value = "/{id}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)public ResultData update${table_name}(@PathVariable("id") String id,@RequestBody ${table_name}DTO ${table_name?uncap_first}DTO) throws Exception {${table_name?uncap_first}DTO.setId(id);return new ResultData(${table_name}.class,${table_name?uncap_first}Service.update${table_name}(${table_name?uncap_first}DTO));}}

通过上面的代码生成,我们就可以把生成的文件复制到相关的目录,重新启动系统,这样,基本的增,删,改,查就实现了。


作者:阿_毅

来源链接:

https://blog.csdn.net/huangwenyi1010/article/details/71249258

Java实现自己想要的代码生成器!相关推荐

  1. 企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台

    企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台 JavaFast是一款基于代码生成器的智能快速开发平台,可以帮助解决java项目中80%的重复工作,让开发者更多关注业务 ...

  2. Stack Overflow : 55.9%的Java程序员想“抛弃”Java

    著名网站StackOverflow每年都会搞一个开发人员的调查,今年有65000名全世界的程序员参与,他们来自于这些地方: 美国和印度的圈圈都很大,加拿大,西欧等国,巴西的圈圈也不小, 中国的圆圈就有 ...

  3. 关于 Java 18 你想知道的一切

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  4. influxdb java_身为Java程序员想拿高薪?这份分布式的pdf你一定不能错过

    身为后端工程师,你对这类招聘要求肯定不陌生:熟悉分布式系统的设计和应用:熟悉分布式.缓存.消息.搜索等机制:对分布式常用技术进行合理应用.解决问题等等. 而这其中,又以分布式协议与算法尤甚.很多大公司 ...

  5. java 动软_动软代码生成器下载_2017动软代码生成器下载及相关推荐 - noYes软件大全...

    <雅轩YY协议马甲生成器>顾名思义是①款YY马甲生成器,只需要自定义马甲前缀名和后缀名及其生成数量,然后再选择生成马甲的种类,就可以①键成海量的马甲名称了,生成后①键轻松复制即可. < ...

  6. java制作网站的原理_代码生成器原理

    代码生成器原理很简单,用一句话概括就是:将数据库字段转换成Java字段并输出内容. 如下图所示: 因此,首先需要做的是获取表信息以及表的字段信息,一般有两种方式,第一种:连接到数据库,执行相关SQL, ...

  7. 现在企业编程用java还是python_想转行做程序员,是学习 Java 还是 Python 更好?

    只有小孩子才做选择,我都要 我们学习的目的是为了更好的就业,那当然Java就是首先,然后在学Python 下面给你谈谈我为什么建议你先学Java JAVA的市场占有率相当高,因其广泛的应用型和不易出错 ...

  8. java后台框架 springmvc mybaits 集代码生成器 SSM SSH

    获取[下载地址]   QQ: 313596790   [免费支持更新] 支持三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体 [ 新录针对本系统的视频教 ...

  9. Java实现哥德巴赫猜想

    验证哥德巴赫猜想:任何一个大于 6 的偶数,都能分解成两个质数的和.要求输入一个整数,输出这个 数能被分解成哪两个质数的和. eg : 14 14=3+11 14=7+7 public class T ...

  10. 关于Java,你想知道的一切,这里说透了

    关于学习java,小伙伴们总是有各种各样的问题,如果你也有意从事 Java 编程事业的话,可能就会比较关心实际的问题了.总结起来,无非就是以下几个,看看你有没有中招吧~ [请选择]下面这些问题,你都关 ...

最新文章

  1. 在React 组件中使用Echarts
  2. Linux opencv安装与编译
  3. eas 在linux下安装_linux下easy_install的安装与使用详解
  4. php yii2 finfo file,FileHelper:文件系统助手
  5. yuv格式转换是那个组织定义的_AI 如何赋能摄像机?这场沙龙为你解锁“软件定义”新概念...
  6. 华为首批升级鸿蒙系统的手机,鸿蒙系统首批升级机型曝光!荣耀手机遗憾缺席,原因很简单...
  7. Android View框架总结(九)KeyEvent事件分发机制
  8. 25个深度学习相关公开数据集
  9. 数据库三大顶级会议 VLDB ICDE SIGMOD
  10. cairo填充_Cairo图形指南
  11. 重积分 | 第二类曲面积分投影法正负判断
  12. 使用集成学习提升机器学习算法性能
  13. 《算法竞赛入门经典》第三章思考题
  14. 《易经》对中华文化的影响
  15. spss分组统计的方法
  16. AndroidStudio运行项目报build\intermediates下文件错误
  17. 基于android的汽车租赁出租车打车洗车app
  18. 极光开发者周刊【No.0806】
  19. Mac anaconda相关
  20. 我最喜欢的科目是计算机英语,我最喜欢的科目英语作文带翻译

热门文章

  1. C语言,函数调用使用方法
  2. python之输出语句
  3. C语言练习题,鸡兔同笼
  4. java 阶乘算法_Java 实现阶乘算法
  5. 数据结构学习-Java实现复数类
  6. ipad写python代码用什么软件_iPad 能用来写代码吗?有哪些必备软件推荐?
  7. 简单python程序代码_几个简单的python程序分享
  8. 论文笔记-深度估计(4) Semi-Supervised Deep Learning for Monocular Depth Map Prediction
  9. 十大最受欢迎蓝牙耳机品牌推荐,学生党打工人平价蓝牙耳机
  10. oracle基于脚本的安装失败,脚本建库导致 Oracle 组件未安装故障案例