spring cloud+vue線上視訊網站 7.程式碼生成模組 part 1
這一章主要是完成程式碼生成的模組,用到的工具是 freemaker ,在完成程式碼生成模組的同時會完成小節部分的程式碼。
freemaker 的基本用法
一般來說一個 freemaker 的模版基本會包括下面四部分。
文字:直接輸出的部分
註釋:<#–2333–>格式部分,不會輸出
插值:即${…}或#{…}格式的部分,將使用資料模型中的部分替代輸出
FTL指令:FreeMarker指定,和HTML標記類似,名字前加#予以區分,不會輸出
引入 freemaker
首先在 course 的依賴管理中新增 freemaker 依賴:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.29</version>
</dependency>
然後在 course 中新建 generator 包作為程式碼生成模組,pom 檔案中新增 freemaker 依賴。
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
資料庫持久層生成
mabatis generator 生成持久層
修改 server 中 resource 的 generatorConfig 最後的 tableName 和 domainObjectName 。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Mysql" targetRuntime="MyBatis3" defaultModelType="flat">
<!-- 新增後sql語句中的關鍵字和表用``區分-->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 生成xml檔案自動覆蓋之前的檔案 -->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<!-- 生成例項類的tostring方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- 刪除所有註釋-->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--連線資料庫,修改自己的資料庫名使用者名稱密碼-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/course"
userId="root"
password="czj666666">
</jdbcConnection>
<!-- domain類的位置 -->
<javaModelGenerator targetProject="src/main/java"
targetPackage="com.course.server.domain"/>
<!-- mapper xml的位置 -->
<sqlMapGenerator targetProject="src/main/resources"
targetPackage="mapper"/>
<!-- mapper類的位置 -->
<javaClientGenerator targetProject="src/main/java"
targetPackage="com.course.server.mapper"
type="XMLMAPPER" />
<!-- <table tableName="test" domainObjectName="Test"></table>-->
<!-- <table tableName="chapter" domainObjectName="Chapter"></table>-->
<table tableName="section" domainObjectName="Section"></table>
</context>
</generatorConfiguration>
執行 mybatis-generator 後生成持久層程式碼。
生成資料庫表
這裡用之前的 doc/db/all.sql 來生成資料庫表,並新增資料。
drop table if exists `section`;
create table `section` (
`id` char(8) not null default '' comment 'ID',
`title` varchar(50) not null comment '標題',
`course_id` char(8) comment '課程|course.id',
`chapter_id` char(8) comment '大章|chapter.id',
`video` char(200) comment '視訊',
`time` int comment '時長|單位秒',
`charge` char(1) comment '收費|C 收費;F 免費',
`sort` int comment '順序',
`created_at` DATETIME(3) comment '建立時間',
`updated_at` datetime(3) comment '修改時間',
primary key (`id`)
)engine=innodb default charset=utf8mb4 comment='小節';
insert into `section` (id, title, course_id, chapter_id, video, time, charge, sort, created_at, updated_at)
values ('00000001','測試小節01','00000001','00000000','',500,'F',1,now(),now());
控制層服務層模版檔案
freemaker 工具類
在 generator 模組中,建立如下結構的包。ftl 包存放 freemaker 模版檔案,控制層和服務層程式碼都由這裡的 ftl 模版生成;util 包存放 freemaker 工具類,server 中的 main 方法會呼叫抽離的工具類;server 中包含生成程式碼的 main 方法。
這裡首先建立了一個 freemaker 的工具類。其中包含了 init 方法和 generator 方法。
其中 init 方法的作用是初始化 freemaker 設定,載入模版檔案;generatro 方法的作用是生成檔案並寫入 map 對應的程式碼。
package com.course.generator.util;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
public class FreemarkerUtil {
static Template temp;
public static void initConfig(String ftlPath,String ftlName) throws IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);
cfg.setDirectoryForTemplateLoading(new File(ftlPath));
cfg.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_29));
temp = cfg.getTemplate(ftlName);
}
public static void generator(String fileName, Map<String, Object> map) throws IOException, TemplateException {
FileWriter fw = new FileWriter(fileName);
BufferedWriter bw = new BufferedWriter(fw);
temp.process(map, bw);
bw.flush();
fw.close();
}
}
控制層模板檔案
模板檔案有對應控制層和服務層的,這裡用 ${domain}
代替 chapter
,用 ${Domain}
代替 Chapter
,在下面生成小節程式碼時分別用 section 和 Section 代替。
這裡沒有解決校驗和文字的問題。
controller.ftl
package com.course.${module}.controller.admin;
import com.course.server.dto.${Domain}Dto;
import com.course.server.dto.PageDto;
import com.course.server.dto.ResponseDto;
import com.course.server.service.${Domain}Service;
import com.course.server.util.ValidatorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/admin/${domain}")
public class ${Domain}Controller {
private static final Logger LOG = LoggerFactory.getLogger(${Domain}Controller.class);
public static final String BUSINESS_NAME = "${tableNameCn}";
@Resource
private ${Domain}Service ${domain}Service;
@PostMapping("/list")
public ResponseDto list(@RequestBody PageDto pageDto){
${domain}Service.list(pageDto);
ResponseDto responseDto = new ResponseDto();
responseDto.setContent(pageDto);
return responseDto;
}
@PostMapping("/save")
public ResponseDto save(@RequestBody ${Domain}Dto ${domain}Dto){
// 儲存校驗
${domain}Service.save(${domain}Dto);
ResponseDto responseDto = new ResponseDto();
responseDto.setContent(${domain}Dto);
return responseDto;
}
@DeleteMapping("/delete/{id}")
public ResponseDto delete(@PathVariable String id){
${domain}Service.delete(id);
ResponseDto responseDto = new ResponseDto();
return responseDto;
}
}
服務層模板檔案
service.ftl
package com.course.server.service;
import com.course.server.domain.${Domain};
import com.course.server.domain.${Domain}Example;
import com.course.server.dto.${Domain}Dto;
import com.course.server.dto.PageDto;
import com.course.server.mapper.${Domain}Mapper;
import com.course.server.util.CopyUtil;
import com.course.server.util.UuidUtil;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import com.github.pagehelper.PageHelper;
import org.springframework.util.StringUtils;
@Service
public class ${Domain}Service {
@Resource
private ${Domain}Mapper ${domain}Mapper;
public void list(PageDto pageDto){
PageHelper.startPage(pageDto.getPage(),pageDto.getSize());
${Domain}Example ${domain}Example = new ${Domain}Example();
List<${Domain}> ${domain}List = ${domain}Mapper.selectByExample(${domain}Example);
PageInfo<${Domain}> pageInfo = new PageInfo<>(${domain}List);
pageDto.setTotal(pageInfo.getTotal());
List<${Domain}Dto> ${domain}DtosList;
${domain}DtosList = CopyUtil.copyList(${domain}List,${Domain}Dto.class);
pageDto.setList(${domain}DtosList);
}
public void save(${Domain}Dto ${domain}Dto){
${Domain} ${domain} = CopyUtil.copy(${domain}Dto,${Domain}.class);
if(StringUtils.isEmpty(${domain}.getId())){
this.insert(${domain});
}else{
this.update(${domain});
}
}
private void insert(${Domain} ${domain}){
${domain}.setId(UuidUtil.getShortUuid());
${domain}Mapper.insert(${domain});
}
private void update(${Domain} ${domain}){
${domain}Mapper.updateByPrimaryKey(${domain});
}
public void delete(String id){
${domain}Mapper.deleteByPrimaryKey(id);
}
}
dto 層程式碼生成
要生成 dto 層的程式碼,首先要去資料庫讀取其中含有的欄位等資訊,然後將取得的資訊進行處理,最後呼叫 generator 中的方法生成程式碼。
新建 field 類
其中,新建了 field 類來儲存各個欄位的資訊:
package com.course.generator.util;
public class Field {
private String name; // 欄位名:course_id
private String nameHump; // 欄位名小駝峰:courseId
private String nameBigHump; // 欄位名大駝峰:CourseId
private String nameCn; // 中文名:課程
private String type; // 欄位型別:char(8)
private String javaType; // java型別:String
private String comment; // 註釋:課程|ID
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameHump() {
return nameHump;
}
public void setNameHump(String nameHump) {
this.nameHump = nameHump;
}
public String getNameBigHump() {
return nameBigHump;
}
public void setNameBigHump(String nameBigHump) {
this.nameBigHump = nameBigHump;
}
public String getNameCn() {
return nameCn;
}
public void setNameCn(String nameCn) {
this.nameCn = nameCn;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getJavaType() {
return javaType;
}
public void setJavaType(String javaType) {
this.javaType = javaType;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Field{");
sb.append("name='").append(name).append('\'');
sb.append(", nameHump='").append(nameHump).append('\'');
sb.append(", nameBigHump='").append(nameBigHump).append('\'');
sb.append(", nameCn='").append(nameCn).append('\'');
sb.append(", type='").append(type).append('\'');
sb.append(", javaType='").append(javaType).append('\'');
sb.append(", comment='").append(comment).append('\'');
sb.append('}');
return sb.toString();
}
}
新建 DbUtil 類
接著新建了 DbUtil 類,來連結資料庫,取到資料庫表的各個欄位並處理。
package com.course.generator.util;
//import com.course.generator.enums.EnumGenerator;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DbUtil {
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/course?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai";
String user = "root";
String pass = "czj666666";
conn = DriverManager.getConnection(url, user, pass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 獲得表註釋
* @param tableName
* @return
* @throws Exception
*/
public static String getTableComment(String tableName) throws Exception {
Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select table_comment from information_schema.tables Where table_name = '" + tableName + "'");
String tableNameCH = "";
if (rs != null) {
while(rs.next()) {
tableNameCH = rs.getString("table_comment");
break;
}
}
rs.close();
stmt.close();
conn.close();
System.out.println("表名:" + tableNameCH);
return tableNameCH;
}
/**
* 獲得所有列資訊
* @param tableName
* @return
* @throws Exception
*/
public static List<Field> getColumnByTableName(String tableName) throws Exception {
List<Field> fieldList = new ArrayList<>();
Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("show full columns from `" + tableName + "`");
if (rs != null) {
while(rs.next()) {
String columnName = rs.getString("Field");
String type = rs.getString("Type");
String comment = rs.getString("Comment");
String nullAble = rs.getString("Null"); //YES NO
Field field = new Field();
field.setName(columnName);
field.setNameHump(lineToHump(columnName));
field.setNameBigHump(lineToBigHump(columnName));
field.setType(type);
field.setJavaType(DbUtil.sqlTypeToJavaType(rs.getString("Type")));
field.setComment(comment);
if (comment.contains("|")) {
field.setNameCn(comment.substring(0, comment.indexOf("|")));
} else {
field.setNameCn(comment);
}
fieldList.add(field);
}
}
rs.close();
stmt.close();
conn.close();
System.out.println("列資訊:" + fieldList);
return fieldList;
}
/**
* 下劃線轉小駝峰
*/
public static String lineToHump(String str){
Pattern linePattern = Pattern.compile("_(\\w)");
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 下劃線轉大駝峰
*/
public static String lineToBigHump(String str){
String s = lineToHump(str);
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
/**
* 資料庫型別轉為Java型別
*/
public static String sqlTypeToJavaType(String sqlType) {
if (sqlType.toUpperCase().contains("varchar".toUpperCase())
|| sqlType.toUpperCase().contains("char".toUpperCase())
|| sqlType.toUpperCase().contains("text".toUpperCase())) {
return "String";
} else if (sqlType.toUpperCase().contains("datetime".toUpperCase())) {
return "Date";
} else if (sqlType.toUpperCase().contains("int".toUpperCase())) {
return "Integer";
} else if (sqlType.toUpperCase().contains("long".toUpperCase())) {
return "Long";
} else if (sqlType.toUpperCase().contains("decimal".toUpperCase())) {
return "BigDecimal";
} else {
return "String";
}
}
}
新建 dto 模板
最後新建了 dto 的模板檔案。
package com.course.server.dto;
<#list typeSet as type>
<#if type=='Date'>
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
</#if>
<#if type=='BigDecimal'>
import java.math.BigDecimal;
</#if>
</#list>
public class ${Domain}Dto {
<#list fieldList as field>
/**
* ${field.comment}
*/
<#if field.javaType=='Date'>
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
</#if>
private ${field.javaType} ${field.nameHump};
</#list>
<#list fieldList as field>
public ${field.javaType} get${field.nameBigHump}() {
return ${field.nameHump};
}
public void set${field.nameBigHump}(${field.javaType} ${field.nameHump}) {
this.${field.nameHump} = ${field.nameHump};
}
</#list>
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
<#list fieldList as field>
sb.append(", ${field.nameHump}=").append(${field.nameHump});
</#list>
sb.append("]");
return sb.toString();
}
}
生成方法
這裡首先去讀取 generatorConfig.xml 中修改的 tableName 和 domainObjectName ,接著呼叫 DbUtil 中的方法讀取處理各個欄位,最後分別生成各個模組的程式碼。
package com.course.generator.server;
import com.course.generator.util.DbUtil;
import com.course.generator.util.Field;
import com.course.generator.util.FreemarkerUtil;
import freemarker.template.TemplateException;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class ServerGenerator {
static String MODULE = "business";
static String ftlPath = "/Users/chenzhijie/Documents/course/generator/src/main/java/com/course/generator/ftl/";
static String toDtoPath = "/Users/chenzhijie/Documents/course/server/src/main/java/com/course/server/dto/";
static String toServicePath = "/Users/chenzhijie/Documents/course/server/src/main/java/com/course/server/service/";
static String toControllerPath = "/Users/chenzhijie/Documents/course/" + MODULE +
"/src/main/java/com/course/" + MODULE + "/controller/admin/";
static String generatorConfigPath = "/Users/chenzhijie/Documents/course/server/src/main/resources/generator/generatorConfig.xml";
public static void main(String[] args) throws Exception {
String module = MODULE;
// 只生成配置檔案中的第一個table節點
File file = new File(generatorConfigPath);
SAXReader reader=new SAXReader();
//讀取xml檔案到Document中
Document doc=reader.read(file);
//獲取xml檔案的根節點
Element rootElement=doc.getRootElement();
//讀取context節點
Element contextElement = rootElement.element("context");
//定義一個Element用於遍歷
Element tableElement;
//取第一個“table”的節點
tableElement=contextElement.elementIterator("table").next();
String Domain = tableElement.attributeValue("domainObjectName");
String tableName = tableElement.attributeValue("tableName");
String tableNameCn = DbUtil.getTableComment(tableName);
String domain = Domain.substring(0, 1).toLowerCase() + Domain.substring(1);
System.out.println("表:"+tableElement.attributeValue("tableName"));
System.out.println("Domain:"+tableElement.attributeValue("domainObjectName"));
List<Field> fieldList = DbUtil.getColumnByTableName(domain);
Set<String> typeSet = getJavaTypes(fieldList);
Map<String, Object> map = new HashMap<>();
map.put("Domain", Domain);
map.put("domain", domain);
map.put("tableNameCn", tableNameCn);
map.put("module", module);
map.put("fieldList", fieldList);
map.put("typeSet", typeSet);
//service層程式碼生成
FreemarkerUtil.initConfig(ftlPath, "service.ftl");
FreemarkerUtil.generator(toServicePath + Domain + "Service.java", map);
//controller層程式碼生成
FreemarkerUtil.initConfig(ftlPath, "controller.ftl");
FreemarkerUtil.generator(toControllerPath + Domain + "Controller.java", map);
//dto層程式碼生成
FreemarkerUtil.initConfig(ftlPath,"dto.ftl");
FreemarkerUtil.generator(toDtoPath + Domain + "Dto.java", map);
}
/**
* 獲取所有的Java型別,使用Set去重
*/
private static Set<String> getJavaTypes(List<Field> fieldList) {
Set<String> set = new HashSet<>();
for (int i = 0; i < fieldList.size(); i++) {
Field field = fieldList.get(i);
set.add(field.getJavaType());
}
return set;
}
}
相關文章
- 【VIP視訊網站專案上線】基於Nodejs的Express框架開發的VIP視訊網站專案及完整程式碼分享...網站NodeJSExpress框架
- 線上視訊網站加密技術詳解網站加密
- 推薦4個國外線上視訊下載網站,YouTube、vimeo、推特視訊網站!網站
- ThinkPHP開發線上視訊網站原始碼,後臺完整許可權管理PHP網站原始碼
- AI繪畫線上生成網站,無需下載直接線上生成ai美圖AI網站
- THINKPHP開發 優酷視訊網|線上視訊|PHP
- 幾個有趣的線上python 程式碼學習網站Python學習網站
- PyCon 2018: 中文視訊(1):理解位元組碼
- 【Java】若依(ruoyi)——7.程式碼生成(二)細節操作Java
- 騰訊、新浪短網址怎麼線上生成
- 網站做好後後臺修改?網站使用者修改密碼模組?網站密碼
- PHP視訊解析網站原始碼+後臺PHP網站原始碼
- 二維碼線上生成
- 重磅訊息·OpenMLDB官方網站 今日正式上線!網站
- TP FANS線上教育系統|慕課網|線上視訊|
- 功能性模組: (5)圖片生成視訊:ffmpeg版和OpenCV版OpenCV
- 網站密碼顯隱功能實現視訊網站密碼
- JavaScript實現線上Qrcode二維碼生成工具-toolfk程式設計師線上工具網JavaScript程式設計師
- 巧用 Swagger 線上編輯器生成前端介面程式碼Swagger前端
- 免費線上音訊轉字幕網站 All In One音訊網站
- OpenMLDB 線上模組架構解析架構
- java 考試系統 線上學習 視訊直播 人臉識別 模組設計方案Java
- 多檔案二維碼生成器線上報名功能,wps線上生成二維碼線上預覽線上分享
- 最快1天搭建短視訊APP!阿里雲短視訊解決方案上線APP阿里
- webpack官網文件 :指南 -- 7.程式碼分割 - 使用import()WebImport
- CSS 程式碼線上生成工具,讓你少寫幾百行程式碼~CSS行程
- Yii1使用Gii生成模組實現CURD
- 手機版線上租車公司網站原始碼網站原始碼
- 80iter線上工具模組上線啦!
- Spring-boot模組化程式設計Springboot程式設計
- 無線自組網AODV路由機制模擬原始碼路由原始碼
- IoT物聯網無線通訊模組該如何選擇?
- URL短網址線上生成工具
- 線上視訊教學線上教育直播程式教育培訓系統線上錄播、回播
- part2_模組一作業
- 網路爬蟲——Urllib模組實戰專案(含程式碼)爬取你的第一個網站爬蟲網站
- MOXA視訊中心正式上線
- thinkphp 5 自動生成模組,最簡單方式,一句程式碼PHP