mirror of
https://github.com/moshowgame/SpringBootCodeGenerator.git
synced 2026-06-03 08:30:34 +08:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32f2a40726 | ||
|
|
830fd72e8b | ||
|
|
97ced7d86c | ||
|
|
28197660ff | ||
|
|
6ba3a2621f | ||
|
|
893aa237a0 | ||
|
|
75d880e520 | ||
|
|
685b952c8f | ||
|
|
19982259c4 | ||
|
|
fc44cd89c2 | ||
|
|
67185ad7af | ||
|
|
2a354f7aba | ||
|
|
6cb2af2c7a | ||
|
|
77936e30a2 | ||
|
|
19db269e92 | ||
|
|
6652a7c5a9 | ||
|
|
5131a4a3a3 | ||
|
|
07cd5c408f | ||
|
|
f99438718a | ||
|
|
0da68aeee0 | ||
|
|
abaaa40965 | ||
|
|
e9b7e9c477 | ||
|
|
74a4f3f293 | ||
|
|
b687f3666b | ||
|
|
f11a656a74 | ||
|
|
aeb5427d28 | ||
|
|
995e1e608a | ||
|
|
2e74d50296 | ||
|
|
2a70d7ecfc | ||
|
|
973f981c89 | ||
|
|
9bd42f81f6 | ||
|
|
b6c4bdb5b4 |
5
@run.cmd
5
@run.cmd
@@ -1,4 +1,3 @@
|
||||
java -jar "./generator-web/target/generator-web-3.0.jar"
|
||||
pause
|
||||
mvn clean compile package
|
||||
mvn clean compile
|
||||
mvn spring-boot:run
|
||||
pause
|
||||
590
README.md
590
README.md
@@ -1,200 +1,390 @@
|
||||
# SpringBootCodeGenerator
|
||||
----
|
||||
又名`Java代码生成器`、`JAVA在线代码生成平台`、`sql转java`、`大狼狗代码生成器`、`mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`<br>
|
||||

|
||||

|
||||

|
||||
[](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml)
|
||||
|
||||
# Author
|
||||
>powered by `Moshow郑锴(大狼狗)` , [https://zhengkai.blog.csdn.net](https://zhengkai.blog.csdn.net)
|
||||
|
||||
# Description
|
||||
>The `Spring Boot Code Generator` , Based on SpringBoot3 and Freemarker<br>
|
||||
> #基于`SpringBoot3`和`Freemarker`的代码生成平台
|
||||
>
|
||||
>Release your hands from tedious and repetitive CRUD tasks.<br>
|
||||
> #从繁琐重复的`CRUD工作`中释放你的双手
|
||||
>
|
||||
>Support mysql+oracle+pgsql , the most popular databases standard SQL<br>
|
||||
> #支持`MySQL`、Oracle、PgSQL三大主流数据库
|
||||
>
|
||||
>Generate various templates through table creation DDL statements, Insert SQL statements, Select SQL statements(*New), and simple JSON.<br>
|
||||
> 通过建表DDL语句、插入SQL语句、选择SQL语句(*新)以及简单JSON生成各种模板`JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper`.
|
||||
>
|
||||
>Thank you all for your use and feedback. The daily PV visits of 1.5k in BeJSON and 2K Stars on GitHub are the greatest encouragement and motivation. <br>
|
||||
> 感谢大家的使用与反馈,BeJSON上每天1.5K的PV访问量👀和 Github上2K的✨Stars是最大的鼓励与动力。
|
||||
>
|
||||
>May everyone maintain a work-life balance, stay healthy and safe. Wishing you all success in your work and continuous advancements!. <br>
|
||||
> 愿大家可以维持生活和工作平衡,保持健康和安全,祝大家工作顺利,步步高升!
|
||||
>
|
||||
>Welcome to submit your issue and useful templates , or put your good idea into PR <br>
|
||||
> 欢迎提交你的问题和常用有用模板,或者提交你的好主意到PR。
|
||||
|
||||
|
||||
# URL
|
||||
|
||||
- 感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是BeJSON专供的`金牌工具`(线上版本不一定是最新的,会有延迟,请谅解,谢谢).<br>
|
||||
- 感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。<br>
|
||||
- 感谢`BootCDN`提供稳定、快速、免费的前端开源项目 CDN 加速服务
|
||||
- Thanks for `JetBrains` providing us the `Licenses for Open Source Development` ,[Get free access to all JetBrains tools for developing your open source project!](https://www.jetbrains.com/community/opensource/#support) .<br>
|
||||
|
||||
| 访问地址 | http://localhost:1234/generator |
|
||||
|:-----------------------|:--------------------------------------------------------------|
|
||||
| BEJSON 金牌工具 在线地址 | https://java.bejson.com/generator/ |
|
||||
| JSON.CN 金牌工具 在线地址 | https://java.json.cn/generator/ |
|
||||
| Jully 在线地址 | https://jully.top/generator/ |
|
||||
| DEVTOOLS 在线地址(Demised) | https://java.devtools.cn |
|
||||
| CSDN BLOG | https://zhengkai.blog.csdn.net |
|
||||
| GITEE仓库 | https://gitee.com/moshowgame/SpringBootCodeGenerator/releases |
|
||||
| GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator |
|
||||
|
||||
# Tips or Features
|
||||
- 支持`DDL SQL`/`INSERT SQL`/`SIMPLE JSON`/`SELECT SQL`(*New)四种生成模式
|
||||
- `自动记忆`最近生成的内容,最多保留9个
|
||||
- 提供众多`通用模板`,易于使用,复制粘贴加简单修改即可完成CRUD操作
|
||||
- 支持`特殊字符`模板(`#`请用`井`代替;`$`请用`¥`代替)
|
||||
- `Util集合`提供一些基本对象的使用方法供方便COPY,如对应的CRUD SQL语句、setMap、getMap、get属性等等
|
||||
- 关于`类名注释`,可根据`comment=(mysql)`或者`comment on table(pgsql/oracle)`生成
|
||||
- 可设置是否`自动引包`(java中的import)及`引入包路径`(java类中的package),建议取消并配合IDEA的自动引包更智能(Settings→Editor→General→Auto Import,勾选Add unambiguous imports on the fly以及Optimize imports on the fly)。
|
||||
- 可设置`表名前缀`,例如sys_user前缀为sys_之后可以正确生成user类
|
||||
- 可在`applicaltion.yml`中的`OEM.mode`设置`js/css引入模式`为`local`(本地模式,默认)/`CDN`(云CDN模式,在线网站推荐,省流量)
|
||||
- OEM信息可以在`applicaltion.yml`中的`OEM`中更改
|
||||
- *支持公共js/css的Local/CDN模式切换,方便`本地`或者`工具站`进行部署,可以在`application.yml`的`OEM.Mode=`进行设置,之后请在`header-CDN-v2.html`/`header-local-v2.html`中检查对应js/css配置是否正确。默认为`CDN`模式。对于没有网络的环境请使用`local`模式。
|
||||
- 如何判断是否包含Date日期类并引入,搜索`<#assign importDdate = true />`即可找到对应的方法判断和引入
|
||||
|
||||
# Branch Detail 分支介绍
|
||||
- Master:主力分支,基于SpringBoot3+,需要JDK17+
|
||||
- JDK11:兼容分支,基于SpringBoot2+,支持JDK8/JDK11/JDK17等版本,请自行(切换jdk11分支)[https://github.com/moshowgame/SpringBootCodeGenerator/tree/jdk11]
|
||||
- NewUI:新UI界面改版尝鲜
|
||||
|
||||
# 更新预告
|
||||
1.计划优化一下前端界面,改善由于静态资源加载问题导致的访问缓慢问题,目前正在开发中
|
||||
2.根据大家Raised的Issue优化一下模板
|
||||
|
||||
# Update Logs
|
||||
| 更新日期 | 更新内容 |
|
||||
|:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 2025.03.16 | NewUI V2前端优化:<br>移除不必要内容,优化Local和CDN静态文件引入。<br><br>修复由于SQL类型大写导致无法转换的问题。(感谢@zzy-design的反馈)<br><br>JPA模板优化(感谢@PenroseYang的反馈):<br>修复不开启Lombok情况下Set/Get方法生成问题;<br>修复importDdate判断为true后没有引入日期类的问题<br> |
|
||||
| 2024.12.29 | 优化前端加载速度,优化输出代码着色,CDN改字节跳动静态资源公共库。<br> |
|
||||
| 2024.12.23 | 新增InsertSQL模式,采用JSQLParser引擎进行封装<br>优化代码封装<br>CDN恢复为staticfile.org加速(如果本地卡的话,建议切换local模式)。<br> |
|
||||
| 2024.04.23 | 切换为更快更稳定的BootCDN进行加速。<br>前端NEWUI改版(基于AdminLTE+Bootstrap+Vue+ElementUI混合模式)。 |
|
||||
| 2024.04.22 | [Java CI with Maven](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml) 更新<br>SpringBoot升级到3.2.5<br>FastJSON升级到FastJSON2.0.49 |
|
||||
| 2024.04.21 | 推出JDK11分支,支持JDK8/JDK11/JDK17等版本,兼容性较好但维护速度较慢,为了更好兼容旧机器和旧环境 |
|
||||
| 2024.04.20 | 修复CDN版本cdn.staticfile.org域名备份失败问题,已同步更新到cdn.staticfile.net(本地版本则不受影响) |
|
||||
| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu的PR) |
|
||||
| 2023.10.22 | 工具站CDN更新。 |
|
||||
| 2023.08.31 | (感谢@Nisus-Liu的PR)<br>fix 驼峰列名转命名风格错误问题<br>增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线<br>增加 NonCaseString 大小写不敏感字符串包装类, 简化编码<br>几点代码小优化。 |
|
||||
| 2023.07.11 | 安全更新,正式支持SpringBoot3,javax升级到jakarta。 |
|
||||
| 2023.01.02 | 新增TkMybatis模板(感谢@sgj666的建议)。 |
|
||||
| 2023.01.01 | 新增GCP BigQuery/Dataflow JJS/QlikSense BI模板。 |
|
||||
| 2022.09.28 | MySQL to Java type conversion 数据库类型转换优化(感谢@jadelike得贡献) |
|
||||
| 2022.07.02 | add the script to install and run,添加批处理以便直接构建或运行项目。 |
|
||||
| 2022.02.10 | 更新springboot、fastjson、lombok依赖(感谢@Abbykawai的建议)。 |
|
||||
| 2022.02.09 | 新增JPA-STARP模板(感谢@starplatinum3的贡献)。 |
|
||||
| 2022.01.11 | 优化mybatis的mapper文件生成(感谢@chendong的贡献)。 |
|
||||
| 2021.10.31 | 优化当有索引和额外的换行时的解析逻辑(感谢@feitian124的贡献)。<br>修复部分模板参数不对应(感谢@Thixiaoxiao的贡献)。<br>新增cookie记录所需配置字段逻辑,避免重复配置(感谢@Thixiaoxiao的贡献)。 |
|
||||
| 2021.08.07 | 新增当前模板保持功能,重新生成代码后依然会保持在当前选择模板。<br>新增renren-fast模板。 |
|
||||
| 2021.08.05 | 解决 update 方法语法错误;调整部分语句避免sonarLint告警(感谢@Henry586的PR);<br>add swagger-yml.ftl(感谢@fuuqiu的PR);<br>支持common-mapper&修复entity和plusentity的swagger引包错误(感谢@chentianming11的PR) |
|
||||
| 2021.03.24 | 修复Mybatis.XML中缺失test=关键字问题。(感谢@BWHN/YUEHUI的反馈)。 |
|
||||
| 2021.01.18 | OEM信息优化,支持多配置文件模式,支持在application*.yml自定义信息,以及切换local/cdn模式。 |
|
||||
| 2021.01.17 | 生成后自动trim掉前后空格输出。<br>完善ReadMe文档。<br>优化云CDN引入部分。<br>优化returnUtil部分。<br>表明前缀选项(感谢@wwlg的建议)。 <br>是否带字段注释设置(感谢@fengpojian的建议)。<br>优化Mybatis的''!=判断(感谢@zhongsb的建议)。<br>Mybatis-Plus增加Service层(感谢@yf466532479的建议)。 |
|
||||
| 2021.01.16 | 全新3.0版本:<br>一、前端半vue半js化,更多动态加载项。<br>二、支持更多生成设置,优化生成场景。<br>三、js导入支持本地/CDN模式,支持断网环境轻松使用。 |
|
||||
| 2020.10.22 | 1.tinyint多加一个Short类型转换(感谢@wttHero的建议) |
|
||||
| 2020.10.20 | 1.修复mapper2 insert代码问题(感谢@mXiaoWan的PR)<br>2.优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)。<br>3.新增日期类型的转换选择(感谢@qingkediguo的建议)。<br>4.新增是否包装类型的转换选择(感谢@gzlicanyi的建议)。 |
|
||||
| 2020.06.28 | 优化Util下的BeanUtil,支持更多map.put的操作。整合CRUD模板到SQL(CRUD)模板。 |
|
||||
| 2020.06.21 | 修复FreemarkerUtil的Path问题导致JAR包运行时无法获取template的问题。 |
|
||||
| 2020.05.25 | 1.一些fix,关于封装工具类以及layui模板优化等.<br> 2.优化表备注的获取逻辑.<br> 3.生成时间格式改为yyyy-MM-dd,移除具体的时间,只保留日期 |
|
||||
| 2020.05.22 | 1.新增insert-sql模式,支持对"insert into table (xxx) values (xxx)"语句进行处理,生成java代码(感谢三叔的建议). |
|
||||
| 2020.05.17 | 1.代码重构!异常处理优化,Freemarker相关工具类优化,简化模板生成部分,通过template.json来配置需要生成的模板,不需要配置java文件.<br> 2.修复包含comment关键字时注释无法识别的问题.(感谢@1nchaos的反馈).<br> 3.赞赏优化,感谢大家的赞赏.<br> 4.新增mapper2(Mybatis-Annotation模板)(感谢@baisi525和@CHKEGit的建议). |
|
||||
| 2020.05.03 | 1.优化对特殊字符的处理,对于包含#和$等特殊字符的,在模板使用井和¥代替便可,escapeString方法会自动处理.<br> 2.优化mybatisplus实体类相关(感谢@chunchengmeigui的反馈).<br> 3.修优化对所有类型的判断(感谢@cnlw的反馈).<br> 4.移除swagger-entity,该功能已经包含在‘swagger-ui’的下拉选项中 <br> 5.升级hutool和lombok版本 |
|
||||
| 2020.03.06 | 1.提交一套layuimini+mybatisplus的模板.<br> 2.修复mybatisplus一些相关问题. |
|
||||
| 2020.02.06 | 1.新增历史记录功能,自动保存最近生成的对象.<br> 2.新增swagger开关选项和修复@Column带name参数(感谢@liuyu-struggle的建议).<br> 3.去除mybatis模板中的方括号[]和修改模板里的类注释样式(感谢@gaohanghang的PR) |
|
||||
| 2019.12.29 | 1.修复bejson安全防护策略拦截问题(感谢@liangbintao和@1808083642的反馈).<br> 2.优化字段名含date字符串的处理(感谢@smilexzh的反馈).<br> 3.控制台动态输出项目访问地址(感谢@gaohanghang的提交) |
|
||||
| 2019.11.28 | 1.修复支持string-copy导致的以n结尾的字母不显示问题.<br> 2.jpa-entity新增swagger@ApiModel@ApiModelProperty注解和SQL字段@Column注解(感谢@yjq907的建议) |
|
||||
| 2019.11.26 | 1.springboot2内置tomcat更换为性能更强大的undertow.<br> 2.修复tinyintTransType参数丢失问题 |
|
||||
| 2019.11.24 | 1.java代码结构优化.<br> 2.新增简单的json生成模式.<br> 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献).<br> 4.新增对复制String代码中的乱SQL代码的支持 5.优化对JSON的父子节点/处理,JSONObject和JSONArray节点处理,子节点缺失'{'头处理 |
|
||||
| 2019.11.23 | 1.移除频繁出错和被过滤的layer,改为jquery-toast.<br> 2.Util功能优化,新增json和xml. |
|
||||
| 2019.11.16 | 优化对primary关键字的处理(感谢@liujiansgit的反馈). |
|
||||
| 2019.11.15 | 1.添加tinyint类型转换(感谢@lixiliang&@liujiansgit的Suggestion).<br> 2.添加一键复制功能(感谢@gaohanghang的Suggestion).<br> 3.Mybatis的insert增加keyProperty="id"用于返回自增id(感谢@88888888888888888888的Suggestion).<br> 4.优化date类型的支持(感谢@SteveLsf的反馈).<br> 5.其他一些优化. |
|
||||
| 2019.10.15 | 修复jdbcTemplates中insert语句第一个字段丢失的问题. |
|
||||
| 2019.09.15 | 1.添加对象getset模板.<br> 2.添加sql模板.<br> 3.启动类添加日志输出,方便项目使用(感谢@gaohanghang 的pull request) |
|
||||
| 2019.09.10 | 优化以及更新Maven依赖,减少打包体积.<br> 1.修复mapper接口load方法,但是xml中方法不匹配问题.<br> 2.移除mapper中CRUD时的@param 注解,会影响xml的解析(感谢@caojiantao的反馈).<br> 3.优化MyBatis的xml文件对Oracle的支持.(感谢@wylove1992的反馈).<br> 4.新增对boolean的处理(感谢@violinxsc的反馈)以及优化tinyint类型生成boolean类型问题(感谢@hahaYhui的反馈) |
|
||||
| 2019.09.09 | 添加是否下划线转换为驼峰的选择(感谢@youngking28 的pull request). |
|
||||
| 2019.05.18 | 1.优化注释.<br> 2.修改 mybatis模板中 controller注解.<br> 3.修改 mybatis模板中 dao文件使用为 mapper文件.<br> 4.修改 mybatis模板中 service实现类中的一个 bug.<br> 5.修改 index.ftl文件中 mybatis模板的 dao -> mapper(感谢@unqin的pull request) |
|
||||
| 2019.05.11 | 优化mybatis模块的dao和xml模板,修改dao接口注解为@Repository,所有dao参数改为包装类,删除update语句最后的UpdateTime = NOW(),修改dao接口文件的方法注释使其更符合javaDoc的标准,修改insert语句增加插入行主键的返回,修改load的方法名为selectByPrimaryKey,修改xml的update语句新增动态if判空,修改xml的insert语句新增动态插入判空,更符合mybatisGenerator标准(感谢@Archer-Wen的贡献 ). |
|
||||
| 2019.04.29 | 新增返回封装工具类设置.<br> 优化对oracle注释comment on column的支持(感谢@liukex反馈).<br> 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 ). |
|
||||
| 2019.02.11 | 提交gitignore,解决StringUtils.lowerCaseFirst潜在的NPE异常,校验修改为@RequestParam参数校验,lombok之@Data和@Slf4j优化,fix JdbcDAO模板类名显示为中文问题,WebMvcConfig整合MessageConverter,模板代码分类(感谢@liutf和@tfgzs的pull request). |
|
||||
| 2019.02.10 | 实体生成规则切换为包装类型,不再采用基本数据类型,为实体类生成添加显示的默认构造方法(感谢@h2so的pull request). |
|
||||
| 2019.01.06 | 修复处理number/decimal(x,x)类型的逻辑(感谢@arthaschan的反馈).<br> 修复JdbcTemplates模板两处错误(感谢@everflourish的反馈). |
|
||||
| 2018.12.12 | 首页UI优化.<br> 新增MybatisPlus模块(感谢@三叔同事的建议).<br> 修复作者名和包名获取失败问题(感谢@Yanch1994的反馈). |
|
||||
| 2018.11.22 | 优化正则表达式点号的处理,优化处理字段类型,对number类型增加int,long,BigDecimal的区分判断(感谢@lshz0088的指导). |
|
||||
| 2018.11.08 | 修复非字段描述"KEY FK_xxxx (xxxx)"导致生成KEY字段情况(感谢@tornadoorz反馈). |
|
||||
| 2018.10.18 | 支持double(x,x)的类型,以及comment里面包含一些特殊字符的处理(感谢@tanwubo的反馈). |
|
||||
| 2018.10.10 | CDN变更,修复CDN不稳定导致网页js报错问题. |
|
||||
| 2018.10.03 | 新增element-ui/bootstrap生成. |
|
||||
| 2018.10.02 | 修复公共CDN之Layer.js404问题,导致项目无法生成. |
|
||||
| 2018.09.27 | 优化COMMENT提取逻辑,支持多种复杂情况的注释(感谢@raodeming的反馈). |
|
||||
| 2018.09.26 | 全新BeetlSQL模块,以及一些小细节优化(感谢@三叔同事的建议). |
|
||||
| 2018.09.25 | 优化SQL表和字段备注的推断,包括pgsql/oralce的comment on column/table情况处理等. |
|
||||
| 2018.09.18 | 优化SQL类型推断.<br> 优化PrimaryKey判断.<br> 修复jpacontroller中Repository拼写错误问题. |
|
||||
| 2018.09.17 | 全新首页,静态文件全部采用CDN.新增jdbcTemplate模块. |
|
||||
| 2018.09.16 | 1.优化oracle支持,优化DDL语句中"或者'或者空格的支持.<br> 2.补充char/clob/blob/json等类型,如果类型未知,默认为String. |
|
||||
| 2018.09.15 | 新增Swagger-UI模板.修复一些命名和导入问题.JPA的Entity默认第一个字段为Id,如果不是请手工修改. |
|
||||
| 2018.09.13 | 修复字段没有描述以及类型为DATE型导致的问题.新增JPA的Controller模板. |
|
||||
| 2018.08.31 | 初始化项目.新增JPA系列Entity+Repository模板. |
|
||||
|
||||
# ClassInfo/TableInfo
|
||||
|名称|说明|
|
||||
|:----|:----|
|
||||
|packageName|自定义的包名|
|
||||
|authorName|自定义的作者名|
|
||||
|tableName|sql中的表名|
|
||||
|className|java类名|
|
||||
|classComment|sql表备注/java类备注|
|
||||
|fieldName|字段名|
|
||||
|fieldComment|字段备注|
|
||||
|
||||
# Options
|
||||
|名称|说明|默认值|
|
||||
|:----|:----|:----|
|
||||
|作者 |authorName|zhengkai.blog.csdn.net|
|
||||
|包名 |packageName|cn.devtools|
|
||||
|返回(成功)|returnUtilSuccess|Return.SUCCESS|
|
||||
|返回(失败)|returnUtilFailure|Return.ERROR|
|
||||
|忽略前缀|ignorePrefix |sys_|
|
||||
|输入类型 |dataType|DDL SQL|
|
||||
|TinyInt转换 |tinyintTransType|int|
|
||||
|时间类型 |timeTransType|Date|
|
||||
|命名类型 |nameCaseType|CamelCase/驼峰|
|
||||
|是否包装类型 |isPackageType|true|
|
||||
|是否swaggerUI|isSwagger|false|
|
||||
|是否字段注释|isComment|true|
|
||||
|是否自动引包|isAutoImport||
|
||||
|是否带包路径|isWithPackage||
|
||||
|是否Lombok|isLombok|true|
|
||||
|
||||
|
||||
# How to add a new template
|
||||
1. `resources/templates/code-generator`中找到对应类型
|
||||
2. COPY并编写freemarker模板文件`.ftl`
|
||||
3. 修改`template.json`文件,新增模板信息,页面可动态加载
|
||||
|
||||
# Upgrade Issue Resolution 升级问题解决方案
|
||||
- 如果你最近也在升级FastJson到FastJson2版本,而跟我一样也遇到了FastJsonHttpMessageConverter找不到类问题以及FastJsonConfig找不到问题,那么恭喜你,看完本文,安装完fastjson2、fastjson2-extension、fastjson2-extension-spring6这三个类库,你就可以成功使用新版FastJson2了。
|
||||
[FastJson2中FastJsonHttpMessageConverter找不到类问题](https://blog.csdn.net/moshowgame/article/details/138013669)
|
||||
|
||||
- 当项目从2.7.x的springboot升级到3.0.x的时候,遇到一个问题“java: 程序包javax.servlet.http不存在” 问题:
|
||||
[java: 程序包javax.servlet.http不存在](https://zhengkai.blog.csdn.net/article/details/131362304)
|
||||
|
||||
- [CSDN【SpringBoot2启示录】专栏](https://blog.csdn.net/moshowgame/category_9274885.html)
|
||||
|
||||
2025 NewUI V2版本
|
||||
<img src="./newui_version_2.png">
|
||||
配置模板
|
||||
<img src="./codegenerator2.png">
|
||||
网站流量分析-2024
|
||||
<img src="./site_analysis-2024.png">
|
||||
代码与你,越变越美
|
||||
<img src="./donate.png">
|
||||
|
||||
# SpringBootCodeGenerator 大狼狗代码生成器
|
||||
|
||||
***
|
||||
|
||||
又名`Java代码生成器`、`JAVA在线代码生成平台`、`sql转java`、`大狼狗代码生成器`、`mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`
|
||||

|
||||

|
||||

|
||||
[](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml)
|
||||
|
||||
# Author
|
||||
|
||||
> 🚀
|
||||
> Powered by `Moshow郑锴(大狼狗)` 🌟 Might the holy code be with you !
|
||||
> **`CSDN`传送门**️️➡️ <https://zhengkai.blog.csdn.net>
|
||||
> **微信公众号**➡️`软件开发大百科`
|
||||
|
||||
# Description
|
||||
|
||||
本项目是基于 Spring Boot 3 和 Freemarker 的高效代码生成平台,旨在帮助开发者告别繁琐重复的 CRUD 操作,释放双手,让开发更高效。项目支持主流数据库(MySQL、Oracle、PgSQL)和多种模板(JPA、Mybatis、MybatisPlus 等),并支持一键 ZIP 打包下载,开箱即用。
|
||||
|
||||
> 🚀 `Spring Boot Code Generator` — a powerful code generation platform built on SpringBoot3 & Freemarker\
|
||||
> ✨ 基于 `SpringBoot3` 和 `Freemarker` 的高效代码生成平台
|
||||
|
||||
> 👐 Say goodbye to repetitive CRUD work — free your hands and boost productivity\
|
||||
> 💡 告别繁琐重复的 CRUD 操作,释放你的双手,让开发更高效!
|
||||
|
||||
> 🛠️ Supports MySQL, Oracle, and PostgreSQL — the most popular SQL dialects\
|
||||
> 📦 支持主流数据库:`MySQL`、`Oracle`、`PgSQL`,标准 SQL 一网打尽
|
||||
|
||||
> ⚙️ Generate templates from DDL, INSERT SQL, SELECT SQL, or simple JSON — covering JPA, JdbcTemplate, Mybatis, MybatisPlus, BeetlSQL, CommonMapper\
|
||||
> 🧩 通过建表 DDL、插入 SQL、选择 SQL 或简单 JSON,一键生成 `JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper` 等模板代码
|
||||
|
||||
> 📦 **One-click ZIP download** — package all generated code into a structured ZIP in one click\
|
||||
> 📦 **一键 ZIP 打包下载** — 按模板分组自动归档,告别逐个文件复制
|
||||
|
||||
> 🙏 Thanks for your continued support! BeJSON once peaked at 1.5K daily PV 👀, and now maintains a steady flow of around 600 visits — plus 2K+ GitHub Stars ✨. Your feedback remains our greatest motivation to keep improving!
|
||||
> ❤️ 感谢大家一直以来的支持!BeJSON 曾创下日均访问量 1.5K 👀 的高峰,目前稳定在约 600 左右,GitHub Star 数也已突破 2K ✨。你们的反馈始终是我们不断前进的最大动力!
|
||||
|
||||
> 🌈 Wishing everyone balance, health, and success — may your code be bug-free and your coffee strong ☕\
|
||||
> 💬 祝大家工作顺利,生活平衡,身体健康,步步高升,代码无 bug,咖啡够劲!
|
||||
|
||||
> 📬 Feel free to submit issues, share useful templates, or contribute your brilliant ideas via PR\
|
||||
> 🤝 欢迎提交问题、分享常用模板,或将你的灵感通过 PR 实现!
|
||||
|
||||
> 🙌 Special thanks to BeJSON 前站长 `三叔` 的慧眼与支持,让项目得以脱颖而出,感恩!
|
||||
|
||||
<img src="./newui_version_2.png" width="600px">
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 支持多种生成模式
|
||||
|
||||
- DDL SQL 模式:通过建表语句生成代码
|
||||
- INSERT SQL 模式:通过插入语句生成代码
|
||||
- SELECT SQL 模式:通过查询语句生成代码
|
||||
- JSON 模式:通过 JSON 数据生成代码
|
||||
|
||||
### 支持多种模板
|
||||
|
||||
- JPA 模板
|
||||
- MyBatis 模板
|
||||
- MyBatis-Plus 模板
|
||||
- BeetlSQL 模板
|
||||
- CommonMapper 模板
|
||||
- TkMyBatis 模板
|
||||
- JDBC Template 模板
|
||||
- 前端 UI 模板(Element UI、Bootstrap UI 等)
|
||||
|
||||
### 其他特性
|
||||
|
||||
- 自动记忆最近生成的内容
|
||||
- 支持特殊字符模板(# 用 井 代替,$ 用 ¥ 代替)
|
||||
- 可设置表名前缀
|
||||
- 可选择是否自动引包
|
||||
- 支持本地/CDN 静态资源引入模式切换
|
||||
- **📦 一键 ZIP 打包下载**:将本次生成的全部代码按模板分组打成 ZIP 一键下载
|
||||
|
||||
## 技术栈
|
||||
|
||||
- Spring Boot 3
|
||||
- Freemarker 模板引擎
|
||||
- FastJSON2
|
||||
- JSqlParser SQL 解析器
|
||||
- Lombok 简化代码工具
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 启动项目
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://github.com/moshowgame/SpringBootCodeGenerator.git
|
||||
|
||||
# 进入项目目录
|
||||
cd SpringBootCodeGenerator
|
||||
# 编译项目
|
||||
mvn clean compile
|
||||
# 运行项目
|
||||
mvn spring-boot:run
|
||||
|
||||
# 访问项目
|
||||
http://localhost:1234/generator
|
||||
|
||||
# 打包项目(不验证单元测试)
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 运行测试
|
||||
mvn test
|
||||
# 查看JaCoCo测试覆盖率
|
||||
cd /target/site/jacoco
|
||||
```
|
||||
|
||||
### 添加新模板
|
||||
|
||||
1. 在 `resources/templates/code-generator` 目录中找到对应类型
|
||||
2. 复制并编写 Freemarker 模板文件(.ftl)
|
||||
3. 修改 `template.json` 文件,新增模板信息
|
||||
|
||||
### 📦 一键打包下载
|
||||
|
||||
在主界面"生成"按钮旁边新增了一个独立的 **下载 ZIP** 按钮,点击后将本次生成的全部代码按模板 `group` 自动分目录打包成 ZIP 下载,无需逐个文件复制。
|
||||
|
||||
#### 特性
|
||||
|
||||
- **自动目录分组**:例如 `mybatis/UserInfoController.java`、`ui/UserInfo-element-ui.html`,结构清晰
|
||||
- **文件名模板化**:在 `template.json` 中通过 `fileName` 字段定义,支持 `${className}` / `${tableName}` 等占位符
|
||||
- **重名自动去重**:相同文件名会自动加序号(如 `UserInfo_1.java`)
|
||||
- **中文文件名兼容**:使用 RFC 5987 `filename*` 编码,避免乱码
|
||||
- **零依赖**:使用 JDK 自带 `ZipOutputStream` 实现,不引入额外依赖
|
||||
|
||||
#### 后端接口
|
||||
|
||||
```
|
||||
POST /code/generate-zip
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
请求体与 `/code/generate` 一致,返回 `application/zip` 字节流,响应头携带 `Content-Disposition: attachment; filename="...zip"; filename*=UTF-8''...`。
|
||||
|
||||
#### 自定义文件名
|
||||
|
||||
编辑 `src/main/resources/template.json`,为模板条目添加 `fileName` 字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "20",
|
||||
"name": "controller",
|
||||
"description": "controller",
|
||||
"fileName": "${className}Controller.java"
|
||||
}
|
||||
```
|
||||
|
||||
支持的占位符:
|
||||
|
||||
- `${className}`:Java 类名(如 `UserInfo`)
|
||||
- `${tableName}`:原始表名(如 `t_user_info`)
|
||||
- 未填写 `fileName` 时,会根据模板 `group` / `name` 智能推断后缀(`.java` / `.xml` / `.html` / `.sql` 等)
|
||||
|
||||
#### 示例输出结构
|
||||
|
||||
```
|
||||
UserInfo.zip
|
||||
├── mybatis/
|
||||
│ ├── UserInfoController.java
|
||||
│ ├── UserInfo.java
|
||||
│ ├── UserInfoMapper.xml
|
||||
│ └── UserInfoService.java
|
||||
├── jpa/
|
||||
│ └── UserInfo.java
|
||||
├── ui/
|
||||
│ └── UserInfo-element-ui.html
|
||||
└── sql/
|
||||
└── t_user_info.sql
|
||||
```
|
||||
|
||||
### 配置说明
|
||||
|
||||
| **配置项** | **说明** | **默认值** |
|
||||
| :---------- | :---------------- | :--------------------- |
|
||||
| 作者 | authorName | zhengkai.blog.csdn.net |
|
||||
| 包名 | packageName | cn.devtools |
|
||||
| 返回(成功) | returnUtilSuccess | Return.SUCCESS |
|
||||
| 返回(失败) | returnUtilFailure | Return.ERROR |
|
||||
| 忽略前缀 | ignorePrefix | sys\_ |
|
||||
| 输入类型 | dataType | DDL SQL |
|
||||
| TinyInt转换 | tinyintTransType | int |
|
||||
| 时间类型 | timeTransType | Date |
|
||||
| 命名类型 | nameCaseType | CamelCase/驼峰 |
|
||||
| 是否包装类型 | isPackageType | true |
|
||||
| 是否swaggerUI | isSwagger | false |
|
||||
| 是否字段注释 | isComment | true |
|
||||
| 是否自动引包 | isAutoImport | <br /> |
|
||||
| 是否带包路径 | isWithPackage | <br /> |
|
||||
| 是否Lombok | isLombok | true |
|
||||
|
||||
| **模板变量** | **说明** |
|
||||
| :----------- | :------------- |
|
||||
| tableName | sql中的表名 |
|
||||
| className | java类名 |
|
||||
| classComment | sql表备注/java类备注 |
|
||||
| fieldName | 字段名 |
|
||||
| fieldComment | 字段备注 |
|
||||
|
||||
## 重构2025说明
|
||||
|
||||
本项目的重构2025在原有基础上进行了现代化重构,优化了项目结构和代码组织,使其更符合现代 Spring Boot 应用的最佳实践。
|
||||
|
||||
### 重构亮点
|
||||
|
||||
1. **清晰的分层架构**:采用 Controller-Service-DTO-VO 分层设计,各层职责明确
|
||||
2. **接口与实现分离**:服务层采用接口与实现分离的设计,便于测试和扩展
|
||||
3. **策略模式应用**:使用策略模式处理不同类型的 SQL 解析,易于扩展新的解析方式
|
||||
4. **现代化开发规范**:遵循 Spring Boot 和 Java 开发最佳实践
|
||||
5. **完善的异常处理**:统一异常处理机制,提供更友好的错误提示
|
||||
|
||||
### 重构后项目结构
|
||||
|
||||
```
|
||||
com.softdev.system.generator
|
||||
├── GeneratorApplication.java # 启动类
|
||||
├── config # 配置类包
|
||||
│ ├── WebMvcConfig.java # MVC配置
|
||||
│ └── GlobalExceptionHandler.java # 全局异常处理器
|
||||
├── controller # 控制层
|
||||
│ ├── PageController.java # 页面跳转控制器
|
||||
│ ├── CodeGenController.java # 代码生成相关接口
|
||||
│ └── TemplateController.java # 模板相关接口
|
||||
├── service # 服务层接口
|
||||
│ ├── CodeGenService.java # 代码生成服务接口
|
||||
│ ├── TemplateService.java # 模板服务接口
|
||||
│ └── parser
|
||||
│ ├── SqlParserService.java # SQL解析服务接口
|
||||
│ └── JsonParserService.java # JSON解析服务接口
|
||||
├── service.impl # 服务实现层
|
||||
│ ├── CodeGenServiceImpl.java # 代码生成服务实现
|
||||
│ ├── TemplateServiceImpl.java # 模板服务实现
|
||||
│ └── parser
|
||||
│ ├── SqlParserServiceImpl.java # SQL解析服务实现
|
||||
│ └── JsonParserServiceImpl.java # JSON解析服务实现
|
||||
├── entity # 实体类
|
||||
│ ├── dto
|
||||
│ │ ├── ParamInfo.java # 参数信息DTO
|
||||
│ │ ├── ClassInfo.java # 类信息DTO
|
||||
│ │ └── FieldInfo.java # 字段信息DTO
|
||||
│ ├── vo
|
||||
│ │ └── ResultVo.java # 统一返回结果VO
|
||||
│ └── enums
|
||||
│ └── ParserTypeEnum.java # 解析类型枚举
|
||||
├── util # 工具类包
|
||||
│ ├── FreemarkerUtil.java # Freemarker工具类
|
||||
│ ├── StringUtilsPlus.java # 字符串工具类
|
||||
│ ├── MapUtil.java # Map工具类
|
||||
│ ├── mysqlJavaTypeUtil.java # MySQL类型转换工具类
|
||||
│ └── exception
|
||||
│ ├── CodeGenException.java # 自定义业务异常
|
||||
│ └── SqlParseException.java # SQL解析异常
|
||||
└── constant # 常量定义
|
||||
└── CodeGenConstants.java # 代码生成常量(待实现)
|
||||
```
|
||||
|
||||
### 统一响应格式
|
||||
|
||||
所有控制器方法均返回 ResultVo 统一响应对象,保持与前端的兼容性:
|
||||
|
||||
```java
|
||||
// 成功响应
|
||||
ResultVo.ok(data);
|
||||
|
||||
// 错误响应
|
||||
ResultVo.error(message);
|
||||
```
|
||||
|
||||
## 重构优势
|
||||
|
||||
1. **结构清晰**:通过合理的包结构和分层设计,使项目结构更加清晰易懂
|
||||
2. **易于维护**:各层职责明确,便于定位和修复问题
|
||||
3. **易于扩展**:采用策略模式等设计模式,便于添加新的功能模块
|
||||
4. **现代化**:遵循 Spring Boot 和 Java 的最新最佳实践
|
||||
5. **前后端兼容**:保持与现有前端代码的数据交互格式,无缝升级
|
||||
|
||||
## 升级问题解决方案
|
||||
|
||||
### FastJSON 升级到 FastJSON2
|
||||
|
||||
如果在升级 FastJSON 到 FastJSON2 版本时遇到 FastJsonHttpMessageConverter 找不到类问题以及 FastJsonConfig 找不到问题,需要安装以下类库:
|
||||
|
||||
- fastjson2
|
||||
- fastjson2-extension
|
||||
- fastjson2-extension-spring6
|
||||
|
||||
### Spring Boot 3 升级
|
||||
|
||||
当项目从 Spring Boot 2.x 升级到 3.x 时,可能会遇到 "java: 程序包 javax.servlet.http 不存在" 问题,这是因为 Spring Boot 3 使用了 Jakarta EE 9+,包名从 javax.\* 变更为 jakarta.\*。
|
||||
|
||||
## 版权信息
|
||||
|
||||
本项目遵循相关开源协议,欢迎提交问题、分享常用模板,或将你的灵感通过 PR 实现!
|
||||
|
||||
## Stargazers over time
|
||||
|
||||
[](https://starchart.cc/moshowgame/SpringBootCodeGenerator)
|
||||
|
||||
配置模板 <img src="./codegenerator2.png">
|
||||
网站流量分析-2024 <img src="./site_analysis-2024.png">
|
||||
代码与你,越变越强 <img src="./donate.png">
|
||||
|
||||
# Update Logs
|
||||
|
||||
| 更新日期 | 更新内容 |
|
||||
| :--------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 2026.06.02 | 📦 新增"一键 ZIP 打包下载"功能:在生成按钮旁新增独立下载按钮,按模板 group 自动分目录打包成 ZIP;<br>支持 `template.json` 中 `fileName` 字段(含 `${className}` 占位符),智能推断文件后缀; |
|
||||
| 2025.12.09 | 优化Mybatis和Mybatis-Plus模板 |
|
||||
| 2025.12.08 | 引入单元测试和JaCoCo测试覆盖率,优化代码覆盖率 [UNIT\_TEST\_DOCUMENT.md](UNIT_TEST_DOCUMENT.md) |
|
||||
| 2025.12.07 | 后端重构优化 ;目录结构调整! |
|
||||
| 2025.09.14 | 优化JSqlParser Engine(DDL Create SQL和Select SQL),适配更高级复杂的SQL |
|
||||
| 2025.09.13 | JSqlParser Engine全新升级,目前Select SQL模式相对稳定! 更新SpringBoot等类库版本,修复漏洞修复CDN问题,切换为staticfile.org |
|
||||
| 2025.09.06 | 处理建表字段包含 using 字符时无法生成对应字段的情况(感谢@wubiaoo的反馈和@willxiang的PR) |
|
||||
| 2025.03.31 | 优化说明 |
|
||||
| 2025.03.16 | NewUI V2前端优化:移除不必要内容,优化Local和CDN静态文件引入。修复由于SQL类型大写导致无法转换的问题。(感谢@zzy-design的反馈)JPA模板优化(感谢@PenroseYang的反馈):修复不开启Lombok情况下Set/Get方法生成问题;修复importDdate判断为true后没有引入日期类的问题 |
|
||||
| 2024.12.29 | 优化前端加载速度,优化输出代码着色,CDN改字节跳动静态资源公共库。 |
|
||||
| 2024.12.23 | 新增InsertSQL模式,采用JSQLParser引擎进行封装优化代码封装CDN恢复为staticfile.org加速(如果本地卡的话,建议切换local模式)。 |
|
||||
| 2024.04.23 | 切换为更快更稳定的BootCDN进行加速。前端NEWUI改版(基于AdminLTE+Bootstrap+Vue+ElementUI混合模式)。 |
|
||||
| 2024.04.22 | [Java CI with Maven](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml) 更新SpringBoot升级到3.2.5FastJSON升级到FastJSON2.0.49 |
|
||||
| 2024.04.21 | 推出JDK11分支,支持JDK8/JDK11/JDK17等版本,兼容性较好但维护速度较慢,为了更好兼容旧机器和旧环境 |
|
||||
| 2024.04.20 | 修复CDN版本cdn.staticfile.org域名备份失败问题,已同步更新到cdn.staticfile.net(本地版本则不受影响) |
|
||||
| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu的PR) |
|
||||
| 2023.10.22 | 工具站CDN更新。 |
|
||||
| 2023.08.31 | (感谢@Nisus-Liu的PR)fix 驼峰列名转命名风格错误问题增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线增加 NonCaseString 大小写不敏感字符串包装类, 简化编码几点代码小优化。 |
|
||||
| 2023.07.11 | 安全更新,正式支持SpringBoot3,javax升级到jakarta。 |
|
||||
| 2023.01.02 | 新增TkMybatis模板(感谢@sgj666的建议)。 |
|
||||
| 2023.01.01 | 新增GCP BigQuery/Dataflow JJS/QlikSense BI模板。 |
|
||||
| 2022.09.28 | MySQL to Java type conversion 数据库类型转换优化(感谢@jadelike得贡献) |
|
||||
| 2022.07.02 | add the script to install and run,添加批处理以便直接构建或运行项目。 |
|
||||
| 2022.02.10 | 更新springboot、fastjson、lombok依赖(感谢@Abbykawai的建议)。 |
|
||||
| 2022.02.09 | 新增JPA-STARP模板(感谢@starplatinum3的贡献)。 |
|
||||
| 2022.01.11 | 优化mybatis的mapper文件生成(感谢@chendong的贡献)。 |
|
||||
| 2021.10.31 | 优化当有索引和额外的换行时的解析逻辑(感谢@feitian124的贡献)。修复部分模板参数不对应(感谢@Thixiaoxiao的贡献)。新增cookie记录所需配置字段逻辑,避免重复配置(感谢@Thixiaoxiao的贡献)。 |
|
||||
| 2021.08.07 | 新增当前模板保持功能,重新生成代码后依然会保持在当前选择模板。新增renren-fast模板。 |
|
||||
| 2021.08.05 | 解决 update 方法语法错误;调整部分语句避免sonarLint告警(感谢@Henry586的PR);add swagger-yml.ftl(感谢@fuuqiu的PR);支持common-mapper&修复entity和plusentity的swagger引包错误(感谢@chentianming11的PR) |
|
||||
| 2021.03.24 | 修复Mybatis.XML中缺失test=关键字问题。(感谢@BWHN/YUEHUI的反馈)。 |
|
||||
| 2021.01.18 | OEM信息优化,支持多配置文件模式,支持在application\*.yml自定义信息,以及切换local/cdn模式。 |
|
||||
| 2021.01.17 | 生成后自动trim掉前后空格输出。完善ReadMe文档。优化云CDN引入部分。优化returnUtil部分。表明前缀选项(感谢@wwlg的建议)。 是否带字段注释设置(感谢@fengpojian的建议)。优化Mybatis的''!=判断(感谢@zhongsb的建议)。Mybatis-Plus增加Service层(感谢@yf466532479的建议)。 |
|
||||
| 2021.01.16 | 全新3.0版本:一、前端半vue半js化,更多动态加载项。二、支持更多生成设置,优化生成场景。三、js导入支持本地/CDN模式,支持断网环境轻松使用。 |
|
||||
| 2020.10.22 | 1.tinyint多加一个Short类型转换(感谢@wttHero的建议) |
|
||||
| 2020.10.20 | 1.修复mapper2 insert代码问题(感谢@mXiaoWan的PR)2.优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)。3.新增日期类型的转换选择(感谢@qingkediguo的建议)。4.新增是否包装类型的转换选择(感谢@gzlicanyi的建议)。 |
|
||||
| 2020.06.28 | 优化Util下的BeanUtil,支持更多map.put的操作。整合CRUD模板到SQL(CRUD)模板。 |
|
||||
| 2020.06.21 | 修复FreemarkerUtil的Path问题导致JAR包运行时无法获取template的问题。 |
|
||||
| 2020.05.25 | 1.一些fix,关于封装工具类以及layui模板优化等. 2.优化表备注的获取逻辑. 3.生成时间格式改为yyyy-MM-dd,移除具体的时间,只保留日期 |
|
||||
| 2020.05.22 | 1.新增insert-sql模式,支持对"insert into table (xxx) values (xxx)"语句进行处理,生成java代码(感谢三叔的建议). |
|
||||
| 2020.05.17 | 1.代码重构!异常处理优化,Freemarker相关工具类优化,简化模板生成部分,通过template.json来配置需要生成的模板,不需要配置java文件. 2.修复包含comment关键字时注释无法识别的问题.(感谢@1nchaos的反馈). 3.赞赏优化,感谢大家的赞赏. 4.新增mapper2(Mybatis-Annotation模板)(感谢@baisi525和@CHKEGit的建议). |
|
||||
| 2020.05.03 | 1.优化对特殊字符的处理,对于包含#和$等特殊字符的,在模板使用井和¥代替便可,escapeString方法会自动处理. 2.优化mybatisplus实体类相关(感谢@chunchengmeigui的反馈). 3.修优化对所有类型的判断(感谢@cnlw的反馈). 4.移除swagger-entity,该功能已经包含在‘swagger-ui’的下拉选项中 5.升级hutool和lombok版本 |
|
||||
| 2020.03.06 | 1.提交一套layuimini+mybatisplus的模板. 2.修复mybatisplus一些相关问题. |
|
||||
| 2020.02.06 | 1.新增历史记录功能,自动保存最近生成的对象. 2.新增swagger开关选项和修复@Column带name参数(感谢@liuyu-struggle的建议). 3.去除mybatis模板中的方括号\[]和修改模板里的类注释样式(感谢@gaohanghang的PR) |
|
||||
| 2019.12.29 | 1.修复bejson安全防护策略拦截问题(感谢@liangbintao和@1808083642的反馈). 2.优化字段名含date字符串的处理(感谢@smilexzh的反馈). 3.控制台动态输出项目访问地址(感谢@gaohanghang的提交) |
|
||||
| 2019.11.28 | 1.修复支持string-copy导致的以n结尾的字母不显示问题. 2.jpa-entity新增swagger\@ApiModel\@ApiModelProperty注解和SQL字段@Column注解(感谢@yjq907的建议) |
|
||||
| 2019.11.26 | 1.springboot2内置tomcat更换为性能更强大的undertow. 2.修复tinyintTransType参数丢失问题 |
|
||||
| 2019.11.24 | 1.java代码结构优化. 2.新增简单的json生成模式. 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献). 4.新增对复制String代码中的乱SQL代码的支持 5.优化对JSON的父子节点/处理,JSONObject和JSONArray节点处理,子节点缺失'{'头处理 |
|
||||
| 2019.11.23 | 1.移除频繁出错和被过滤的layer,改为jquery-toast. 2.Util功能优化,新增json和xml. |
|
||||
| 2019.11.16 | 优化对primary关键字的处理(感谢@liujiansgit的反馈). |
|
||||
| 2019.11.15 | 1.添加tinyint类型转换(感谢@lixiliang&@liujiansgit的Suggestion). 2.添加一键复制功能(感谢@gaohanghang的Suggestion). 3.Mybatis的insert增加keyProperty="id"用于返回自增id(感谢@88888888888888888888的Suggestion). 4.优化date类型的支持(感谢@SteveLsf的反馈). 5.其他一些优化. |
|
||||
| 2019.10.15 | 修复jdbcTemplates中insert语句第一个字段丢失的问题. |
|
||||
| 2019.09.15 | 1.添加对象getset模板. 2.添加sql模板. 3.启动类添加日志输出,方便项目使用(感谢@gaohanghang 的pull request) |
|
||||
| 2019.09.10 | 优化以及更新Maven依赖,减少打包体积. 1.修复mapper接口load方法,但是xml中方法不匹配问题. 2.移除mapper中CRUD时的@param 注解,会影响xml的解析(感谢@caojiantao的反馈). 3.优化MyBatis的xml文件对Oracle的支持.(感谢@wylove1992的反馈). 4.新增对boolean的处理(感谢@violinxsc的反馈)以及优化tinyint类型生成boolean类型问题(感谢@hahaYhui的反馈) |
|
||||
| 2019.09.09 | 添加是否下划线转换为驼峰的选择(感谢@youngking28 的pull request). |
|
||||
| 2019.05.18 | 1.优化注释. 2.修改 mybatis模板中 controller注解. 3.修改 mybatis模板中 dao文件使用为 mapper文件. 4.修改 mybatis模板中 service实现类中的一个 bug. 5.修改 index.ftl文件中 mybatis模板的 dao -> mapper(感谢@unqin的pull request) |
|
||||
| 2019.05.11 | 优化mybatis模块的dao和xml模板,修改dao接口注解为@Repository,所有dao参数改为包装类,删除update语句最后的UpdateTime = NOW(),修改dao接口文件的方法注释使其更符合javaDoc的标准,修改insert语句增加插入行主键的返回,修改load的方法名为selectByPrimaryKey,修改xml的update语句新增动态if判空,修改xml的insert语句新增动态插入判空,更符合mybatisGenerator标准(感谢@Archer-Wen的贡献 ). |
|
||||
| 2019.04.29 | 新增返回封装工具类设置. 优化对oracle注释comment on column的支持(感谢@liukex反馈). 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 ). |
|
||||
| 2019.02.11 | 提交gitignore,解决StringUtils.lowerCaseFirst潜在的NPE异常,校验修改为@RequestParam参数校验,lombok之@Data和@Slf4j优化,fix JdbcDAO模板类名显示为中文问题,WebMvcConfig整合MessageConverter,模板代码分类(感谢@liutf和@tfgzs的pull request). |
|
||||
| 2019.02.10 | 实体生成规则切换为包装类型,不再采用基本数据类型,为实体类生成添加显示的默认构造方法(感谢@h2so的pull request). |
|
||||
| 2019.01.06 | 修复处理number/decimal(x,x)类型的逻辑(感谢@arthaschan的反馈). 修复JdbcTemplates模板两处错误(感谢@everflourish的反馈). |
|
||||
| 2018.12.12 | 首页UI优化. 新增MybatisPlus模块(感谢@三叔同事的建议). 修复作者名和包名获取失败问题(感谢@Yanch1994的反馈). |
|
||||
| 2018.11.22 | 优化正则表达式点号的处理,优化处理字段类型,对number类型增加int,long,BigDecimal的区分判断(感谢@lshz0088的指导). |
|
||||
| 2018.11.08 | 修复非字段描述"KEY FK\_xxxx (xxxx)"导致生成KEY字段情况(感谢@tornadoorz反馈). |
|
||||
| 2018.10.18 | 支持double(x,x)的类型,以及comment里面包含一些特殊字符的处理(感谢@tanwubo的反馈). |
|
||||
| 2018.10.10 | CDN变更,修复CDN不稳定导致网页js报错问题. |
|
||||
| 2018.10.03 | 新增element-ui/bootstrap生成. |
|
||||
| 2018.10.02 | 修复公共CDN之Layer.js404问题,导致项目无法生成. |
|
||||
| 2018.09.27 | 优化COMMENT提取逻辑,支持多种复杂情况的注释(感谢@raodeming的反馈). |
|
||||
| 2018.09.26 | 全新BeetlSQL模块,以及一些小细节优化(感谢@三叔同事的建议). |
|
||||
| 2018.09.25 | 优化SQL表和字段备注的推断,包括pgsql/oralce的comment on column/table情况处理等. |
|
||||
| 2018.09.18 | 优化SQL类型推断. 优化PrimaryKey判断. 修复jpacontroller中Repository拼写错误问题. |
|
||||
| 2018.09.17 | 全新首页,静态文件全部采用CDN.新增jdbcTemplate模块. |
|
||||
| 2018.09.16 | 1.优化oracle支持,优化DDL语句中"或者'或者空格的支持. 2.补充char/clob/blob/json等类型,如果类型未知,默认为String. |
|
||||
| 2018.09.15 | 新增Swagger-UI模板.修复一些命名和导入问题.JPA的Entity默认第一个字段为Id,如果不是请手工修改. |
|
||||
| 2018.09.13 | 修复字段没有描述以及类型为DATE型导致的问题.新增JPA的Controller模板. |
|
||||
| 2018.08.31 | 初始化项目.新增JPA系列Entity+Repository模板. |
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.softdev.system</groupId>
|
||||
<artifactId>SpringBootCodeGenerator</artifactId>
|
||||
<version>2023</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>generator-web</artifactId>
|
||||
<version>3.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail -->
|
||||
<!--<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>-->
|
||||
|
||||
|
||||
<!-- spring-data-jpa -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.32</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<!--解决idea打包没有xml-->
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<compilerId>javac</compilerId>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerVersion>1.8</compilerVersion>
|
||||
<verbose>true</verbose>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-compiler-eclipse</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<!--<failOnMissingWebXml>false</failOnMissingWebXml>-->
|
||||
<includeEmptyDirs>true</includeEmptyDirs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.2.3</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warSourceExcludes>upload/**</warSourceExcludes>
|
||||
</configuration>
|
||||
</plugin>-->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.softdev.system.generator.config;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* XSS过滤
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class XssFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest)request);
|
||||
chain.doFilter(xssRequest, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
package com.softdev.system.generator.config;
|
||||
|
||||
import jakarta.servlet.ReadListener;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* XSS过滤处理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
/**
|
||||
* 没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
|
||||
*/
|
||||
HttpServletRequest orgRequest;
|
||||
/**
|
||||
* html过滤
|
||||
*/
|
||||
private final static HTMLFilter htmlFilter = new HTMLFilter();
|
||||
|
||||
public XssHttpServletRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
orgRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
//非json类型,直接返回
|
||||
if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
//为空,直接返回
|
||||
String json = IOUtils.toString(super.getInputStream(), "utf-8");
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
//xss过滤
|
||||
json = xssEncode(json);
|
||||
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return bis.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
String value = super.getParameter(xssEncode(name));
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = xssEncode(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
String[] parameters = super.getParameterValues(name);
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
parameters[i] = xssEncode(parameters[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,String[]> getParameterMap() {
|
||||
Map<String,String[]> map = new LinkedHashMap<>();
|
||||
Map<String,String[]> parameters = super.getParameterMap();
|
||||
for (String key : parameters.keySet()) {
|
||||
String[] values = parameters.get(key);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = xssEncode(values[i]);
|
||||
}
|
||||
map.put(key, values);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
String value = super.getHeader(xssEncode(name));
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = xssEncode(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String xssEncode(String input) {
|
||||
return htmlFilter.filter(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最原始的request
|
||||
*/
|
||||
public HttpServletRequest getOrgRequest() {
|
||||
return orgRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最原始的request
|
||||
*/
|
||||
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
|
||||
if (request instanceof XssHttpServletRequestWrapper) {
|
||||
return ((XssHttpServletRequestWrapper) request).getOrgRequest();
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package com.softdev.system.generator.controller;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.softdev.system.generator.entity.ClassInfo;
|
||||
import com.softdev.system.generator.entity.ParamInfo;
|
||||
import com.softdev.system.generator.entity.ReturnT;
|
||||
import com.softdev.system.generator.service.GeneratorService;
|
||||
import com.softdev.system.generator.util.MapUtil;
|
||||
import com.softdev.system.generator.util.TableParseUtil;
|
||||
import com.softdev.system.generator.util.ValueUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成控制器
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Controller
|
||||
@Slf4j
|
||||
public class GeneratorController {
|
||||
@Autowired
|
||||
private ValueUtil valueUtil;
|
||||
|
||||
@Autowired
|
||||
private GeneratorService generatorService;
|
||||
|
||||
@GetMapping("/")
|
||||
public ModelAndView defaultPage() {
|
||||
return new ModelAndView("newui2").addObject("value",valueUtil);
|
||||
}
|
||||
@GetMapping("/index")
|
||||
public ModelAndView indexPage() {
|
||||
return new ModelAndView("newui2").addObject("value",valueUtil);
|
||||
}
|
||||
@GetMapping("/newui2")
|
||||
public ModelAndView newui2() {
|
||||
return new ModelAndView("newui2").addObject("value",valueUtil);
|
||||
}
|
||||
@GetMapping("/main")
|
||||
public ModelAndView mainPage() {
|
||||
return new ModelAndView("main").addObject("value",valueUtil);
|
||||
}
|
||||
|
||||
@RequestMapping("/template/all")
|
||||
@ResponseBody
|
||||
public ReturnT getAllTemplates() throws Exception {
|
||||
String templates = generatorService.getTemplateConfig();
|
||||
return ReturnT.ok().put("templates", JSONArray.parseArray(templates));
|
||||
}
|
||||
@PostMapping("/code/generate")
|
||||
@ResponseBody
|
||||
public ReturnT generateCode(@RequestBody ParamInfo paramInfo) throws Exception {
|
||||
//log.info(JSON.toJSONString(paramInfo.getOptions()));
|
||||
if (StringUtils.isEmpty(paramInfo.getTableSql())) {
|
||||
return ReturnT.error("表结构信息为空");
|
||||
}
|
||||
//1.Parse Table Structure 表结构解析
|
||||
ClassInfo classInfo = null;
|
||||
String dataType = MapUtil.getString(paramInfo.getOptions(),"dataType");
|
||||
switch (dataType) {
|
||||
case "sql":
|
||||
//默认模式:parse DDL table structure from sql
|
||||
classInfo = generatorService.processTableIntoClassInfo(paramInfo);
|
||||
break;
|
||||
case "json":
|
||||
//JSON模式:parse field from json string
|
||||
classInfo = generatorService.processJsonToClassInfo(paramInfo);
|
||||
break;
|
||||
case "insert-sql":
|
||||
//INSERT SQL模式:parse field from insert sql
|
||||
classInfo = generatorService.processInsertSqlToClassInfo(paramInfo);
|
||||
break;
|
||||
case "sql-regex":
|
||||
//正则表达式模式(非完善版本):parse sql by regex
|
||||
classInfo = generatorService.processTableToClassInfoByRegex(paramInfo);
|
||||
break;
|
||||
case "select-sql":
|
||||
//SelectSqlBySQLPraser模式:parse select sql by JSqlParser
|
||||
classInfo = generatorService.generateSelectSqlBySQLPraser(paramInfo);
|
||||
break;
|
||||
default:
|
||||
//默认模式:parse DDL table structure from sql
|
||||
classInfo = generatorService.processTableIntoClassInfo(paramInfo);
|
||||
break;
|
||||
}
|
||||
//2.Set the params 设置表格参数
|
||||
paramInfo.getOptions().put("classInfo", classInfo);
|
||||
paramInfo.getOptions().put("tableName", classInfo == null ? System.currentTimeMillis() : classInfo.getTableName());
|
||||
|
||||
//log the generated table and filed size记录解析了什么表,有多少个字段
|
||||
//log.info("generated table :{} , size :{}",classInfo.getTableName(),(classInfo.getFieldList() == null ? "" : classInfo.getFieldList().size()));
|
||||
|
||||
//3.generate the code by freemarker templates with parameters . Freemarker根据参数和模板生成代码
|
||||
Map<String, String> result = generatorService.getResultByParams(paramInfo.getOptions());
|
||||
// log.info("result {}",result);
|
||||
log.info("table:{} - time:{} ", MapUtil.getString(result,"tableName"),new Date());
|
||||
return ReturnT.ok().put("outputJson",result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.softdev.system.generator.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* common returnT:公共返回封装类
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ReturnT extends HashMap<String, Object> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ReturnT() {
|
||||
put("code", 0);
|
||||
put("msg", "success");
|
||||
}
|
||||
|
||||
public static ReturnT error() {
|
||||
return error(500, "未知异常,请联系管理员");
|
||||
}
|
||||
|
||||
public static ReturnT error(String msg) {
|
||||
return error(500, msg);
|
||||
}
|
||||
|
||||
public static ReturnT error(int code, String msg) {
|
||||
ReturnT r = new ReturnT();
|
||||
r.put("code", code);
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
public static ReturnT define(int code, String msg) {
|
||||
ReturnT r = new ReturnT();
|
||||
r.put("code", code);
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
public static ReturnT ok(String msg) {
|
||||
ReturnT r = new ReturnT();
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static ReturnT ok(Map<String, Object> map) {
|
||||
ReturnT r = new ReturnT();
|
||||
r.putAll(map);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static ReturnT ok() {
|
||||
return new ReturnT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.softdev.system.generator.service;
|
||||
|
||||
import com.softdev.system.generator.entity.ClassInfo;
|
||||
import com.softdev.system.generator.entity.ParamInfo;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* GeneratorService
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface GeneratorService {
|
||||
|
||||
String getTemplateConfig() throws IOException;
|
||||
|
||||
Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException;
|
||||
/**
|
||||
* 解析Select-SQL生成类信息(JSQLPraser版本)
|
||||
* @auther: zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
ClassInfo generateSelectSqlBySQLPraser(ParamInfo paramInfo) throws Exception;
|
||||
/**
|
||||
* 解析DDL-SQL生成类信息
|
||||
* @auther: zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
ClassInfo processTableIntoClassInfo(ParamInfo paramInfo) throws Exception;
|
||||
/**
|
||||
* 解析JSON生成类信息
|
||||
* @auther: zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
ClassInfo processJsonToClassInfo(ParamInfo paramInfo);
|
||||
/**
|
||||
* 解析DDL SQL生成类信息-正则表达式版本
|
||||
* @auther: zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo);
|
||||
/**
|
||||
* 解析INSERT-SQL生成类信息-正则表达式版本
|
||||
* @auther: zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.softdev.system.generator.util;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.softdev.system.generator.entity.ClassInfo;
|
||||
import com.softdev.system.generator.entity.FieldInfo;
|
||||
import com.softdev.system.generator.entity.NonCaseString;
|
||||
import com.softdev.system.generator.entity.ParamInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 表格解析Util
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public class TableParseUtil {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
//iframe自适应
|
||||
$(window).on('resize', function() {
|
||||
const $content = $('.content');
|
||||
$content.height($(this).height() - 154);
|
||||
$content.find('iframe').each(function() {
|
||||
$(this).height($content.height());
|
||||
});
|
||||
}).resize();
|
||||
|
||||
const vm = new Vue({
|
||||
el: '#rrapp',
|
||||
data: {
|
||||
main: "main",
|
||||
},
|
||||
methods: {
|
||||
donate: function () {
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
|
||||
},
|
||||
updated: function () {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$.inputArea = undefined;
|
||||
$.outputArea = undefined;
|
||||
|
||||
$(function(){
|
||||
//powered by zhengkai.blog.csdn.net
|
||||
|
||||
//init input code area
|
||||
$.inputArea = CodeMirror.fromTextArea(document.getElementById("inputArea"), {
|
||||
mode: "text/x-sql", // SQL
|
||||
theme: "idea", // IDEA主题
|
||||
lineNumbers: true, //显示行号
|
||||
smartIndent: true, // 自动缩进
|
||||
autoCloseBrackets: true// 自动补全括号
|
||||
});
|
||||
$.inputArea.setSize('auto','auto');
|
||||
|
||||
// init output code area
|
||||
$.outputArea = CodeMirror.fromTextArea(document.getElementById("outputArea"), {
|
||||
mode: "text/x-java", // JAV
|
||||
theme: "idea", // IDEA主题
|
||||
lineNumbers: true, //显示行号
|
||||
smartIndent: true, // 自动缩进
|
||||
autoCloseBrackets: true// 自动补全括号
|
||||
});
|
||||
$.outputArea.setSize('auto','auto');
|
||||
|
||||
});
|
||||
|
||||
|
||||
const vm = new Vue({
|
||||
el: '#rrapp',
|
||||
data: {
|
||||
formData: {
|
||||
tableSql: "CREATE TABLE 'sys_user_info' (\n" +
|
||||
" 'user_id' int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',\n" +
|
||||
" 'user_name' varchar(255) NOT NULL COMMENT '用户名',\n" +
|
||||
" 'status' tinyint(1) NOT NULL COMMENT '状态',\n" +
|
||||
" 'create_time' datetime NOT NULL COMMENT '创建时间',\n" +
|
||||
//下面可以留着方便开发调试时打开
|
||||
// " `updateTime` datetime NOT NULL COMMENT '更新时间',\n" +
|
||||
// " ABc_under_Line-Hypen-CamelCase varchar comment '乱七八糟的命名风格',\n" +
|
||||
" PRIMARY KEY ('user_id')\n" +
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息'",
|
||||
options: {
|
||||
dataType: "sql",
|
||||
|
||||
authorName: "${(value.author)!!}",
|
||||
packageName: "${(value.packageName)!!}",
|
||||
returnUtilSuccess: "${(value.returnUtilSuccess)!!}",
|
||||
returnUtilFailure: "${(value.returnUtilFailure)!!}",
|
||||
|
||||
isPackageType: true,
|
||||
isSwagger: false,
|
||||
isAutoImport: false,
|
||||
isWithPackage: false,
|
||||
isComment: true,
|
||||
isLombok: true,
|
||||
|
||||
ignorePrefix:"sys_",
|
||||
tinyintTransType: "int",
|
||||
nameCaseType: "CamelCase",
|
||||
timeTransType: "Date"
|
||||
}
|
||||
},
|
||||
templates:[{}],
|
||||
historicalData:[],
|
||||
currentSelect:'plusentity',
|
||||
outputStr: "${(value.outputStr)!!}",
|
||||
outputJson: {}
|
||||
},
|
||||
methods: {
|
||||
//set the template for output 选择页面输出的模板类型
|
||||
setOutputModel: function (event) {
|
||||
const targetModel = event.target.innerText.trim();
|
||||
console.log(targetModel);
|
||||
vm.currentSelect = targetModel ;
|
||||
if(vm.outputStr.length>30){
|
||||
vm.outputStr=vm.outputJson[targetModel];
|
||||
$.outputArea.setValue(vm.outputStr.trim());
|
||||
//console.log(vm.outputStr);
|
||||
$.outputArea.setSize('auto', 'auto');
|
||||
}
|
||||
},
|
||||
//switch HistoricalData
|
||||
switchHistoricalData: function (event) {
|
||||
const tableName = event.target.innerText.trim();
|
||||
console.log(tableName);
|
||||
if (window.sessionStorage){
|
||||
const valueSession = sessionStorage.getItem(tableName);
|
||||
vm.outputJson = JSON.parse(valueSession);
|
||||
console.log(valueSession);
|
||||
alert("切换历史记录成功:"+tableName);
|
||||
}else{
|
||||
alert("浏览器不支持sessionStorage");
|
||||
}
|
||||
vm.outputStr=vm.outputJson[vm.currentSelect].trim();
|
||||
$.outputArea.setValue(vm.outputStr);
|
||||
//console.log(vm.outputStr);
|
||||
$.outputArea.setSize('auto', 'auto');
|
||||
},
|
||||
setHistoricalData : function (tableName){
|
||||
//add new table only
|
||||
if(vm.historicalData.indexOf(tableName)<0){
|
||||
vm.historicalData.unshift(tableName);
|
||||
}
|
||||
//remove last record , if more than N
|
||||
if(vm.historicalData.length>9){
|
||||
vm.historicalData.splice(9,1);
|
||||
}
|
||||
//get and set to session data
|
||||
const valueSession = sessionStorage.getItem(tableName);
|
||||
//remove if exists
|
||||
if(valueSession!==undefined && valueSession!=null){
|
||||
sessionStorage.removeItem(tableName);
|
||||
}
|
||||
//set data to session
|
||||
sessionStorage.setItem(tableName,JSON.stringify(vm.outputJson));
|
||||
//console.log(vm.historicalData);
|
||||
},
|
||||
//request with formData to generate the code 根据参数生成代码
|
||||
generate : function(){
|
||||
//get value from codemirror
|
||||
vm.formData.tableSql=$.inputArea.getValue();
|
||||
axios.post(basePath+"/code/generate",vm.formData).then(function(res){
|
||||
if(res.code===500){
|
||||
error("生成失败,请检查SQL语句!!!");
|
||||
return;
|
||||
}
|
||||
setAllCookie();
|
||||
//console.log(res.outputJson);
|
||||
//兼容后端返回数据格式
|
||||
if(res.data){
|
||||
vm.outputJson = res.data.outputJson;
|
||||
}else {
|
||||
vm.outputJson = res.outputJson;
|
||||
}
|
||||
|
||||
// console.log(vm.outputJson["bootstrap-ui"]);
|
||||
vm.outputStr=vm.outputJson[vm.currentSelect].trim();
|
||||
//console.log(vm.outputJson["bootstrap-ui"]);
|
||||
//console.log(vm.outputStr);
|
||||
$.outputArea.setValue(vm.outputStr);
|
||||
$.outputArea.setSize('auto', 'auto');
|
||||
//add to historicalData
|
||||
vm.setHistoricalData(vm.outputJson.tableName);
|
||||
alert("生成成功");
|
||||
});
|
||||
},
|
||||
copy : function (){
|
||||
navigator.clipboard.writeText(vm.outputStr.trim()).then(r => {alert("已复制")});
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
//load all templates for selections 加载所有模板供选择
|
||||
axios.post(basePath+"/template/all",{
|
||||
id:1234
|
||||
}).then(function(res){
|
||||
//console.log(res.templates);
|
||||
// vm.templates = JSON.parse(res.templates);
|
||||
// console.log(res);
|
||||
//兼容后端返回数据格式
|
||||
if(res.data){
|
||||
vm.templates = res.data.templates;
|
||||
}else {
|
||||
vm.templates = res.templates;
|
||||
}
|
||||
});
|
||||
},
|
||||
updated: function () {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 将所有 需要 保留历史纪录的字段写入Cookie中
|
||||
*/
|
||||
function setAllCookie() {
|
||||
var arr = list_key_need_load();
|
||||
for (var str of arr){
|
||||
setOneCookie(str);
|
||||
}
|
||||
}
|
||||
|
||||
function setOneCookie(key) {
|
||||
setCookie(key, vm.formData.options[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有 历史纪录 重加载回页面
|
||||
*/
|
||||
function loadAllCookie() {
|
||||
//console.log(vm);
|
||||
var arr = list_key_need_load();
|
||||
for (var str of arr){
|
||||
loadOneCookie(str);
|
||||
}
|
||||
}
|
||||
|
||||
function loadOneCookie(key) {
|
||||
if (getCookie(key)!==""){
|
||||
vm.formData.options[key] = getCookie(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 所有 需要 纪录的 字段写入数组
|
||||
* @returns {[string]}
|
||||
*/
|
||||
function list_key_need_load() {
|
||||
return ["authorName","packageName","returnUtilSuccess","returnUtilFailure","ignorePrefix","tinyintTransType","timeTransType"];
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
[{
|
||||
"group": "ui",
|
||||
"templates": [{
|
||||
"id": "10",
|
||||
"name": "swagger-ui",
|
||||
"description": "swagger-ui"
|
||||
},
|
||||
{
|
||||
"id": "11",
|
||||
"name": "element-ui",
|
||||
"description": "element-ui"
|
||||
},
|
||||
{
|
||||
"id": "12",
|
||||
"name": "bootstrap-ui",
|
||||
"description": "bootstrap-ui"
|
||||
},
|
||||
{
|
||||
"id": "13",
|
||||
"name": "layui-edit",
|
||||
"description": "layui-edit"
|
||||
},
|
||||
{
|
||||
"id": "14",
|
||||
"name": "layui-list",
|
||||
"description": "layui-list"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "mybatis",
|
||||
"templates": [{
|
||||
"id": "20",
|
||||
"name": "controller",
|
||||
"description": "controller"
|
||||
},
|
||||
{
|
||||
"id": "21",
|
||||
"name": "service",
|
||||
"description": "service"
|
||||
},
|
||||
{
|
||||
"id": "22",
|
||||
"name": "service_impl",
|
||||
"description": "service_impl"
|
||||
},
|
||||
{
|
||||
"id": "23",
|
||||
"name": "mapper",
|
||||
"description": "mapper"
|
||||
},
|
||||
{
|
||||
"id": "24",
|
||||
"name": "mybatis",
|
||||
"description": "mybatis"
|
||||
},
|
||||
{
|
||||
"id": "25",
|
||||
"name": "model",
|
||||
"description": "model"
|
||||
},
|
||||
{
|
||||
"id": "26",
|
||||
"name": "mapper2",
|
||||
"description": "mapper annotation"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "jpa",
|
||||
"templates": [{
|
||||
"id": "30",
|
||||
"name": "entity",
|
||||
"description": "entity"
|
||||
},
|
||||
{
|
||||
"id": "31",
|
||||
"name": "repository",
|
||||
"description": "repository"
|
||||
},
|
||||
{
|
||||
"id": "32",
|
||||
"name": "jpacontroller",
|
||||
"description": "jpacontroller"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "jdbc-template",
|
||||
"templates": [{
|
||||
"id": "40",
|
||||
"name": "jtdao",
|
||||
"description": "jtdao"
|
||||
},
|
||||
{
|
||||
"id": "41",
|
||||
"name": "jtdaoimpl",
|
||||
"description": "jtdaoimpl"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "beetlsql",
|
||||
"templates": [{
|
||||
"id": "50",
|
||||
"name": "beetlmd",
|
||||
"description": "beetlmd"
|
||||
},
|
||||
{
|
||||
"id": "51",
|
||||
"name": "beetlentity",
|
||||
"description": "beetlentity"
|
||||
},
|
||||
{
|
||||
"id": "52",
|
||||
"name": "beetlcontroller",
|
||||
"description": "beetlcontroller"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "mybatis-plus",
|
||||
"templates": [{
|
||||
"id": "60",
|
||||
"name": "pluscontroller",
|
||||
"description": "pluscontroller"
|
||||
},
|
||||
{
|
||||
"id": "61",
|
||||
"name": "plusservice",
|
||||
"description": "plusservice"
|
||||
},
|
||||
{
|
||||
"id": "62",
|
||||
"name": "plusmapper",
|
||||
"description": "plusmapper"
|
||||
},
|
||||
{
|
||||
"id": "63",
|
||||
"name": "plusentity",
|
||||
"description": "plusentity"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "util",
|
||||
"templates": [{
|
||||
"id": "70",
|
||||
"name": "beanutil",
|
||||
"description": "beanutil"
|
||||
},
|
||||
{
|
||||
"id": "71",
|
||||
"name": "json",
|
||||
"description": "json"
|
||||
},
|
||||
{
|
||||
"id": "72",
|
||||
"name": "xml",
|
||||
"description": "xml"
|
||||
},
|
||||
{
|
||||
"id": "73",
|
||||
"name": "sql",
|
||||
"description": "sql"
|
||||
},
|
||||
{
|
||||
"id": "74",
|
||||
"name": "swagger-yml",
|
||||
"description": "swagger-yml"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "common-mapper",
|
||||
"templates": [{
|
||||
"id": "81",
|
||||
"name": "tkentity",
|
||||
"description": "tkentity"
|
||||
},
|
||||
{
|
||||
"id": "82",
|
||||
"name": "tkmapper",
|
||||
"description": "tkmapper"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"group": "renren-fast",
|
||||
"templates": [{
|
||||
"id": "91",
|
||||
"name": "menu-sql",
|
||||
"description": "menu-sql"
|
||||
},
|
||||
{
|
||||
"id": "92",
|
||||
"name": "vue-list",
|
||||
"description": "vue-list"
|
||||
},
|
||||
{
|
||||
"id": "93",
|
||||
"name": "vue-edit",
|
||||
"description": "vue-edit"
|
||||
},
|
||||
{
|
||||
"id": "94",
|
||||
"name": "rr-controller",
|
||||
"description": "rr-controller"
|
||||
},
|
||||
{
|
||||
"id": "95",
|
||||
"name": "rr-dao",
|
||||
"description": "rr-dao"
|
||||
},
|
||||
{
|
||||
"id": "96",
|
||||
"name": "rr-daoxml",
|
||||
"description": "rr-daoxml"
|
||||
},
|
||||
{
|
||||
"id": "97",
|
||||
"name": "rr-service",
|
||||
"description": "rr-service"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "jpa-starp",
|
||||
"templates": [{
|
||||
"id": "101",
|
||||
"name": "starp-entity",
|
||||
"description": "entity"
|
||||
},
|
||||
{
|
||||
"id": "102",
|
||||
"name": "starp-repository",
|
||||
"description": "repository"
|
||||
},
|
||||
{
|
||||
"id": "103",
|
||||
"name": "starp-jpa-controller",
|
||||
"description": "jpacontroller"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "bi",
|
||||
"templates": [{
|
||||
"id": "201",
|
||||
"name": "qliksense",
|
||||
"description": "qlik sense"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"group": "cloud",
|
||||
"templates": [
|
||||
{
|
||||
"id": "301",
|
||||
"name": "bigquery",
|
||||
"description": "GCP BigQuery"
|
||||
},
|
||||
{
|
||||
"id": "302",
|
||||
"name": "dataflowjjs",
|
||||
"description": "GCP Dataflow JJS"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "tk-mybatis",
|
||||
"templates": [
|
||||
{
|
||||
"id": "401",
|
||||
"name": "tk-entity",
|
||||
"description": "tk-entity"
|
||||
},
|
||||
{
|
||||
"id": "402",
|
||||
"name": "tk-mapper",
|
||||
"description": "tk-mapper"
|
||||
},
|
||||
{
|
||||
"id": "403",
|
||||
"name": "tk-controller",
|
||||
"description": "tk-controller"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,38 +0,0 @@
|
||||
<#if isWithPackage?exists && isWithPackage==true>package ${packageName}.mapper;</#if>
|
||||
<#if isAutoImport?exists && isAutoImport==true>
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import ${packageName}.entity.${classInfo.className};
|
||||
import java.util.List;
|
||||
</#if>
|
||||
/**
|
||||
* @description ${classInfo.classComment}Mapper
|
||||
* @author ${authorName}
|
||||
* @date ${.now?string('yyyy-MM-dd')}
|
||||
*/
|
||||
@Mapper
|
||||
public interface ${classInfo.className}Mapper extends BaseMapper<${classInfo.className}> {
|
||||
|
||||
@Select(
|
||||
"<script>select t0.* from ${classInfo.tableName} t0 " +
|
||||
//add here if need left join
|
||||
"where 1=1" +
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
"<when test='${fieldItem.fieldName}!=null and ${fieldItem.fieldName}!='' '> and t0.${fieldItem.columnName}=井{${fieldItem.fieldName}}</when> " +
|
||||
</#list>
|
||||
//add here if need page limit
|
||||
//" limit ¥{page},¥{limit} " +
|
||||
" </script>")
|
||||
List<${classInfo.className}> pageAll(${classInfo.className} queryParamDTO,int page,int limit);
|
||||
|
||||
@Select("<script>select count(1) from ${classInfo.tableName} t0 " +
|
||||
//add here if need left join
|
||||
"where 1=1" +
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
"<when test='${fieldItem.fieldName}!=null and ${fieldItem.fieldName}!='' '> and t0.${fieldItem.columnName}=井{${fieldItem.fieldName}}</when> " +
|
||||
</#list>
|
||||
" </script>")
|
||||
int countAll(${classInfo.className} queryParamDTO);
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<#if isWithPackage?exists && isWithPackage==true>package ${packageName}.mapper;</#if>
|
||||
<#if isAutoImport?exists && isAutoImport==true>
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
</#if>
|
||||
/**
|
||||
* @description ${classInfo.classComment}Mapper
|
||||
* @author ${authorName}
|
||||
* @date ${.now?string('yyyy-MM-dd')}
|
||||
*/
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface ${classInfo.className}Mapper {
|
||||
|
||||
@Select("select * from ${classInfo.tableName} where ${classInfo.tableName}_id=井{id}")
|
||||
public ${classInfo.className} getById(Integer id);
|
||||
|
||||
@Options(useGeneratedKeys=true,keyProperty="${classInfo.className?uncap_first}Id")
|
||||
@Insert("insert into ${classInfo.tableName}" +
|
||||
" (<#list classInfo.fieldList as fieldItem >${fieldItem.columnName}<#if fieldItem_has_next>,</#if></#list>)" +
|
||||
" values(<#list classInfo.fieldList as fieldItem >${fieldItem.fieldName}<#if fieldItem_has_next>,<#else>)</#if></#list>")
|
||||
public Integer insert(${classInfo.className} ${classInfo.className?uncap_first});
|
||||
|
||||
@Delete(value = "delete from ${classInfo.tableName} where ${classInfo.tableName}_id=井{${classInfo.className?uncap_first}Id}")
|
||||
boolean delete(Integer id);
|
||||
|
||||
@Update(value = "update ${classInfo.tableName} set "
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
<#if fieldItem.columnName != "id">+" ${fieldItem.columnName}=井{${fieldItem.fieldName}}<#if fieldItem_has_next>,</#if>"</#if>
|
||||
</#list>
|
||||
+" where ${classInfo.tableName}_id=井{${classInfo.className?uncap_first}Id} ")
|
||||
boolean update(${classInfo.className} ${classInfo.className?uncap_first});
|
||||
|
||||
|
||||
@Results(value = {
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
@Result(property = "${fieldItem.fieldName}", column = "${fieldItem.columnName}")<#if fieldItem_has_next>,</#if>
|
||||
</#list>
|
||||
})
|
||||
@Select(value = "select * from ${classInfo.tableName} where ${classInfo.tableName}_id=井{queryParam}")
|
||||
${classInfo.className} selectOne(String queryParam);
|
||||
|
||||
@Results(value = {
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
@Result(property = "${fieldItem.fieldName}", column = "${fieldItem.columnName}")<#if fieldItem_has_next>,</#if>
|
||||
</#list>
|
||||
})
|
||||
@Select(value = "select * from ${classInfo.tableName} where "
|
||||
<#list classInfo.fieldList as fieldItem >
|
||||
+" ${fieldItem.columnName}=井{${fieldItem.fieldName}}<#if fieldItem_has_next> or </#if>"
|
||||
</#list>
|
||||
)
|
||||
List<${classInfo.className}> selectList(${classInfo.className} ${classInfo.className?uncap_first});
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<!--###################################################-->
|
||||
<!--### CDN version : by https://cdn.bytedance.com/ -->
|
||||
<!--###################################################-->
|
||||
|
||||
<!--jquery | vue | element-ui | axios-->
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script src="//lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js"></script>
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js"></script>
|
||||
<script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/index.min.js"></script>
|
||||
<link href="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/theme-chalk/index.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!-- bootstrap -->
|
||||
<script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/js/bootstrap.bundle.min.js" type="application/javascript"></script>
|
||||
<link href="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
|
||||
<!-- 引入 Bootstrap Icons CSS -->
|
||||
<link href="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!--common.js-->
|
||||
<script src="${request.contextPath}/statics/js/common.js"></script>
|
||||
<!-- <link rel="stylesheet" href="${request.contextPath}/statics/css/main.css"> -->
|
||||
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/toastr.js/2.1.4/toastr.min.js"></script>
|
||||
<!-- Toastr CSS -->
|
||||
<link href="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/toastr.js/2.1.4/toastr.min.css" rtype="text/css" rel="stylesheet" >
|
||||
|
||||
<!-- import codemirror -->
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/codemirror.min.js"></script>
|
||||
<script src="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/mode/sql/sql.min.js"></script>
|
||||
<link href="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/codemirror.min.css" type="text/css" rel="stylesheet" >
|
||||
<link href="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/theme/idea.min.css" type="text/css" rel="stylesheet" >
|
||||
@@ -1,31 +0,0 @@
|
||||
<!--###################################################-->
|
||||
<!--### CDN version -->
|
||||
<!--###################################################-->
|
||||
|
||||
<!--jquery | vue | element-ui | axios-->
|
||||
<script src="${request.contextPath}/statics/libs/jquery/jquery.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/vue/vue.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/axios/axios.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/element-ui/index.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/element-ui/index.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!-- bootstrap -->
|
||||
<script src="${request.contextPath}/statics/libs/bootstrap/bootstrap.bundle.min.js" type="application/javascript"></script>
|
||||
<link href="${request.contextPath}/statics/libs/bootstrap/bootstrap.min.css" type="text/css" rel="stylesheet" />
|
||||
<!-- 引入 Bootstrap Icons CSS -->
|
||||
<link href="${request.contextPath}/statics/libs/bootstrap-icons/bootstrap-icons.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!--common.js-->
|
||||
<script src="${request.contextPath}/statics/js/common.js"></script>
|
||||
<!-- <link rel="stylesheet" href="${request.contextPath}/statics/css/main.css"> -->
|
||||
|
||||
<script src="${request.contextPath}/statics/libs/toastr.js/toastr.min.js"></script>
|
||||
<!-- Toastr CSS -->
|
||||
<link href="${request.contextPath}/statics/libs/toastr.js/toastr.min.css" rtype="text/css" rel="stylesheet" >
|
||||
|
||||
<!-- import codemirror -->
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/codemirror.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/codemirror/codemirror.min.css" type="text/css" rel="stylesheet" >
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/clike/clike.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/sql/sql.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/codemirror/theme/idea.min.css" type="text/css" rel="stylesheet" >
|
||||
@@ -1,26 +0,0 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>${(value.title)!!}</title>
|
||||
<meta name="keywords" content="${(value.keywords)!!}">
|
||||
|
||||
<script>
|
||||
/*统计代码,便于统计流量,请勿移除,谢谢!*/
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?97fd5ca1a4298ac8349c7e0de9029a0f";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
//set base path for fixing the revertProxy forwarding path issue
|
||||
var basePath = "${request.contextPath}";
|
||||
console.log("basePath",basePath)
|
||||
</script>
|
||||
|
||||
<#if value.mode=='local'>
|
||||
<#include "/header-local-v2.html">
|
||||
<#else>
|
||||
<#include "/header-CDN-v2.html">
|
||||
</#if>
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
by https://zhengkai.blog.csdn.net
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<#include "/header.html">
|
||||
<title>${(value.title)!!}</title>
|
||||
</head>
|
||||
<body class="hold-transition layout-top-nav">
|
||||
<div class="wrapper">
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<nav class="main-header navbar navbar-expand-md navbar-light navbar-white">
|
||||
<div class="container">
|
||||
<a href="#" class="navbar-brand">
|
||||
<img src="${request.contextPath}/statics/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-light">${(value.title)!!}</span>
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler order-1" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse order-3" id="navbarCollapse">
|
||||
<i class="fa fa-fw fa-space-shuttle"></i><a>${(value.slogan)!!}</a>
|
||||
</div>
|
||||
|
||||
<!-- 右侧导航栏链接 -->
|
||||
<ul class="order-1 order-md-4 navbar-nav navbar-no-expand ml-auto">
|
||||
<li class="nav-item">
|
||||
<a href="https://github.com/moshowgame/SpringBootCodeGenerator/issues" target="_blank"><i class="fa fa-fw fa-share-square"></i>Raise Issue</a>
|
||||
<a href="https://github.com/moshowgame/SpringBootCodeGenerator" target="_blank"><i class="fa fa-fw fa-star"></i>Github </a>
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- /.navbar -->
|
||||
|
||||
<!-- Content Wrapper. 包含页面内容 -->
|
||||
<div class="content-wrapper">
|
||||
|
||||
|
||||
<!-- 主体内容 -->
|
||||
<div class="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<!-- /.col-md-6 -->
|
||||
<div class="col-lg-12">
|
||||
|
||||
<blockquote class="quote-secondary">
|
||||
${(value.description)!!}
|
||||
</blockquote>
|
||||
|
||||
<!-- <div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">输入SQL</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<textarea id="inputArea" placeholder="请输入表结构信息..." style="height: 250px;line-height : 10px;" v-model="formData.tableSql"></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">生成设置</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">特殊标题处理</h6>
|
||||
|
||||
<p class="card-text">支持引入其他额外内容。</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">输出代码</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<textarea id="outputArea" placeholder="请输入表结构信息..." style="height: 250px;" v-model="outputStr"></textarea>
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
<#include "/main-v2.html">
|
||||
</div>
|
||||
<!-- /.col-md-6 -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</div>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
|
||||
<!-- Control Sidebar -->
|
||||
<aside class="control-sidebar control-sidebar-dark">
|
||||
<!-- 控制侧边栏内容在这里 -->
|
||||
</aside>
|
||||
<!-- /.control-sidebar -->
|
||||
|
||||
<!-- Main Footer -->
|
||||
<footer class="main-footer">
|
||||
<!-- To the right -->
|
||||
<div class="float-right d-none d-sm-inline">
|
||||
Version ${(value.version)!!}
|
||||
</div>
|
||||
<!-- Default to the left -->
|
||||
<strong>${(value.copyright)!!} <a href="https://zhengkai.blog.csdn.net" target="_blank"><i class="fa fa-fw fa-thumbs-up"></i>zhengkai.blog.csdn.net</a> <a href="https://github.com/moshowgame/SpringBootCodeGenerator/blob/master/donate.png?raw=true" target="_blank"><i class="fa fa-fw fa-credit-card"></i>打赏</a>
|
||||
</footer>
|
||||
</div>
|
||||
<!-- ./wrapper -->
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<#include "/header.html">
|
||||
<style>
|
||||
/* .el-form-item__content{
|
||||
line-height : 10px;
|
||||
} */
|
||||
/*.el-form-item--mini .el-form-item__content, .el-form-item--mini .el-form-item__label{
|
||||
line-height : 10px;
|
||||
}*/
|
||||
/* .el-button-group-top {
|
||||
padding-top: 5px;
|
||||
} */
|
||||
.el-button--primary.is-plain.is-disabled, .el-button--primary.is-plain.is-disabled:active, .el-button--primary.is-plain.is-disabled:focus, .el-button--primary.is-plain.is-disabled:hover {
|
||||
color: #f9faff;
|
||||
background-color: #91979d;
|
||||
border-color: #d9ecff;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="rrapp" v-cloak>
|
||||
<div>
|
||||
<el-form ref="form" :inline="true" :model="formData" label-width="100px">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">输入SQL</h5>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="折叠">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<!-- <button type="button" class="btn btn-tool" data-card-widget="remove" title="移除">
|
||||
<i class="fas fa-times"></i>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- <textarea id="inputArea" placeholder="请输入表结构信息..." style="height: 250px;line-height : 10px;" v-model="formData.tableSql"></textarea> -->
|
||||
<!-- input area-->
|
||||
<textarea id="inputArea" placeholder="请输入表结构信息..." style="height: 250px;line-height : 10px;" v-model="formData.tableSql"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">生成设置</h5>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="折叠">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<!-- <button type="button" class="btn btn-tool" data-card-widget="remove" title="移除">
|
||||
<i class="fas fa-times"></i>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<!-- setting area-->
|
||||
<el-form-item label="作者">
|
||||
<el-input v-model="formData.options.authorName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="包名">
|
||||
<el-input v-model="formData.options.packageName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回(成功)">
|
||||
<el-input v-model="formData.options.returnUtilSuccess"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回(失败)">
|
||||
<el-input v-model="formData.options.returnUtilFailure"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="忽略前缀">
|
||||
<el-input v-model="formData.options.ignorePrefix"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="输入类型">
|
||||
<el-select v-model="formData.options.dataType" >
|
||||
<el-option label="DDL SQL" value="sql"></el-option>
|
||||
<el-option label="JSON" value="json"></el-option>
|
||||
<el-option label="INSERT SQL" value="insert-sql">
|
||||
<el-option label="SELECT SQL by SQL Parser" value="select-sql">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="TinyInt转换">
|
||||
<el-select v-model="formData.options.tinyintTransType">
|
||||
<el-option value="boolean" label="boolean"></el-option>
|
||||
<el-option value="Boolean" label="Boolean"></el-option>
|
||||
<el-option value="Integer" label="Integer"></el-option>
|
||||
<el-option value="int" label="int"></el-option>
|
||||
<el-option value="String" label="String"></el-option>
|
||||
<el-option value="Short" label="Short"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间类型">
|
||||
<el-select v-model="formData.options.timeTransType">
|
||||
<el-option value="Date" label="Date"></el-option>
|
||||
<el-option value="DateTime" label="DateTime"></el-option>
|
||||
<el-option value="Time" label="Time"></el-option>
|
||||
<el-option value="Timestamp" label="Timestamp"></el-option>
|
||||
<el-option value="Calendar" label="Calendar"></el-option>
|
||||
<el-option value="LocalDate" label="LocalDate"></el-option>
|
||||
<el-option value="LocalDateTime" label="LocalDateTime"></el-option>
|
||||
<el-option value="LocalTime" label="LocalTime"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="命名类型">
|
||||
<el-select v-model="formData.options.nameCaseType">
|
||||
<el-option label="驼峰" value="CamelCase"></el-option>
|
||||
<el-option label="下划线" value="UnderScoreCase"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装类型">
|
||||
<el-switch v-model="formData.options.isPackageType"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="swaggerUI">
|
||||
<el-switch v-model="formData.options.isSwagger"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段注释">
|
||||
<el-switch v-model="formData.options.isComment"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动引包">
|
||||
<el-switch v-model="formData.options.isAutoImport"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="带包路径">
|
||||
<el-switch v-model="formData.options.isWithPackage"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="Lombok">
|
||||
<el-switch v-model="formData.options.isLombok"></el-switch>
|
||||
</el-form-item>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<!-- <h5 class="card-title m-0">输出代码</h5> -->
|
||||
<el-button type="primary" icon="el-icon-caret-right" @click="generate">生成</el-button>
|
||||
<el-button type="primary" icon="el-icon-document-copy" @click="copy" plain>复制</el-button>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="折叠">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<!-- <button type="button" class="btn btn-tool" data-card-widget="remove" title="移除">
|
||||
<i class="fas fa-times"></i>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!--generate button-->
|
||||
|
||||
<span v-if="historicalData.length>0" >
|
||||
<el-button-group>
|
||||
<el-button type="primary" plain disabled round>历史记录</el-button>
|
||||
<span v-for="(item, index) in historicalData" :key="index">
|
||||
<el-button @click="switchHistoricalData" >{{item}}</el-button>
|
||||
</span>
|
||||
</el-button-group>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">模板选择</h5>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="折叠">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<!-- <button type="button" class="btn btn-tool" data-card-widget="remove" title="移除">
|
||||
<i class="fas fa-times"></i>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!--templates area-->
|
||||
<el-form ref="form" :inline="true" :model="formData" label-width="100px" size="mini">
|
||||
<div v-for="(item, index) in templates" :key="index">
|
||||
<el-button-group >
|
||||
<el-button type="primary" plain disabled>{{item.group}}</el-button>
|
||||
<span v-for="(childItem, index) in item.templates" :key="index">
|
||||
<el-button @click="setOutputModel">{{childItem.name}}</el-button>
|
||||
</span>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<!-- <el-button-group>
|
||||
<el-button type="primary" plain disabled>MybatisPlus</el-button>
|
||||
<el-button @click="setOutputModel">Controller</el-button>
|
||||
<el-button @click="setOutputModel">Mapper</el-button>
|
||||
</el-button-group>-->
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title m-0">输出代码</h5>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse" title="折叠">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<!-- <button type="button" class="btn btn-tool" data-card-widget="remove" title="移除">
|
||||
<i class="fas fa-times"></i>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<textarea id="outputArea" placeholder="请输入表结构信息..." style="height: 250px;" v-model="outputStr"></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="${request.contextPath}/statics/js/main.js"></script>
|
||||
<script>
|
||||
//console.log(vm);
|
||||
vm.formData.options.authorName="${(value.author)!!}";
|
||||
vm.formData.options.packageName="${(value.packageName)!!}";
|
||||
vm.formData.options.returnUtilSuccess="${(value.returnUtilSuccess)!!}";
|
||||
vm.formData.options.returnUtilFailure="${(value.returnUtilFailure)!!}";
|
||||
vm.outputStr="${(value.outputStr)!!}";
|
||||
loadAllCookie()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,31 +0,0 @@
|
||||
<!--###################################################-->
|
||||
<!--### CDN version : by https://cdn.bytedance.com/ -->
|
||||
<!--###################################################-->
|
||||
|
||||
<!--jquery | vue | element-ui | axios-->
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script src="//lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js"></script>
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js"></script>
|
||||
<script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/index.min.js"></script>
|
||||
<link href="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/theme-chalk/index.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!-- bootstrap -->
|
||||
<script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/js/bootstrap.bundle.min.js" type="application/javascript"></script>
|
||||
<link href="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
|
||||
<!-- 引入 Bootstrap Icons CSS -->
|
||||
<link href="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!--common.js-->
|
||||
<script src="${request.contextPath}/statics/js/common.js"></script>
|
||||
<!-- <link rel="stylesheet" href="${request.contextPath}/statics/css/main.css"> -->
|
||||
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/toastr.js/2.1.4/toastr.min.js"></script>
|
||||
<!-- Toastr CSS -->
|
||||
<link href="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/toastr.js/2.1.4/toastr.min.css" rtype="text/css" rel="stylesheet" >
|
||||
|
||||
<!-- import codemirror -->
|
||||
<script src="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/codemirror.min.js"></script>
|
||||
<script src="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/mode/sql/sql.min.js"></script>
|
||||
<script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/codemirror/5.65.2/mode/clike/clike.min.js" type="application/javascript"></script>
|
||||
<link href="//lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/codemirror.min.css" type="text/css" rel="stylesheet" >
|
||||
<link href="//lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/codemirror/5.65.2/theme/idea.min.css" type="text/css" rel="stylesheet" >
|
||||
@@ -1,104 +0,0 @@
|
||||
package com.softdev.system.generator.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
public class StringUtilsPlusTest {
|
||||
|
||||
@Test
|
||||
public void toLowerCamel() {
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("hello_world"));
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("HELLO_WO-RLD-IK"));
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("HELLO_WORLD-IKabc"));
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("HELLO-WORLD-IKabc"));
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("HELLO-123WORLD-IKabc"));
|
||||
System.out.println(StringUtilsPlus.toLowerCamel("helloWorldOKla"));
|
||||
assertEquals("helloWorldChina", StringUtilsPlus.toLowerCamel("hello_-_world-cHina"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upperCaseFirstShouldReturnStringWithFirstLetterCapitalized() {
|
||||
assertEquals("Hello", StringUtilsPlus.upperCaseFirst("hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upperCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
|
||||
assertEquals("", StringUtilsPlus.upperCaseFirst(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowerCaseFirstShouldReturnStringWithFirstLetterLowercased() {
|
||||
assertEquals("hello", StringUtilsPlus.lowerCaseFirst("Hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowerCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
|
||||
assertEquals("", StringUtilsPlus.lowerCaseFirst(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void underlineToCamelCaseShouldReturnCamelCaseString() {
|
||||
assertEquals("helloWorld", StringUtilsPlus.underlineToCamelCase("hello_world"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void underlineToCamelCaseShouldReturnEmptyStringWhenInputIsEmpty() {
|
||||
assertEquals("", StringUtilsPlus.underlineToCamelCase(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toUnderlineShouldReturnUnderlinedString() {
|
||||
assertEquals("hello_world", StringUtilsPlus.toUnderline("helloWorld", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toUnderlineShouldReturnEmptyStringWhenInputIsEmpty() {
|
||||
assertEquals("", StringUtilsPlus.toUnderline("", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toCamelShouldReturnCamelCaseString() {
|
||||
assertEquals("helloWorld", StringUtilsPlus.toLowerCamel("hello_world"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toCamelShouldReturnEmptyStringWhenInputIsEmpty() {
|
||||
assertEquals("", StringUtilsPlus.toLowerCamel(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotNullShouldReturnTrueWhenStringIsNotEmpty() {
|
||||
assertTrue(StringUtilsPlus.isNotNull("hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotNullShouldReturnFalseWhenStringIsEmpty() {
|
||||
assertFalse(StringUtilsPlus.isNotNull(""));
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// String updateTime = StringUtils.underlineToCamelCase("updateTime");
|
||||
// System.out.println(updateTime);
|
||||
|
||||
|
||||
// System.out.println(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "userName"));
|
||||
// System.out.println(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "userNAme-UUU"));
|
||||
|
||||
System.out.println(StringUtilsPlus.toUnderline("userName",false));
|
||||
System.out.println(StringUtilsPlus.toUnderline("UserName",false));
|
||||
System.out.println(StringUtilsPlus.toUnderline("user_NameGgg_x-UUU",false));
|
||||
System.out.println(StringUtilsPlus.toUnderline("username",false));
|
||||
|
||||
System.out.println(StringUtilsPlus.toUnderline("userName",true));
|
||||
System.out.println(StringUtilsPlus.toUnderline("UserName",true));
|
||||
System.out.println(StringUtilsPlus.toUnderline("user_NameGgg_x-UUU",true));
|
||||
System.out.println(StringUtilsPlus.toUnderline("username",true));
|
||||
|
||||
System.out.println(StringUtilsPlus.underlineToCamelCase("CREATE_TIME"));
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 228 KiB |
185
pom.xml
185
pom.xml
@@ -5,25 +5,28 @@
|
||||
|
||||
<groupId>com.softdev.system</groupId>
|
||||
<artifactId>SpringBootCodeGenerator</artifactId>
|
||||
<version>2023</version>
|
||||
<packaging>pom</packaging>
|
||||
<version>2025</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.8</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>generator-web</module>
|
||||
</modules>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>alimaven</id>
|
||||
<name>aliyun maven</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<!-- 指定编码 -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- 指定jdk版本 -->
|
||||
<java.version>11</java.version>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -32,8 +35,44 @@
|
||||
<dependency>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
<version>5.0</version>
|
||||
<version>5.3</version>
|
||||
</dependency>
|
||||
<!-- JUnit 5 -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito for JUnit 5 -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -63,27 +102,21 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.53</version>
|
||||
<version>2.0.60</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-extension</artifactId>
|
||||
<version>2.0.53</version>
|
||||
<version>2.0.60</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension-spring6 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-extension-spring6</artifactId>
|
||||
<version>2.0.53</version>
|
||||
<version>2.0.59</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 支持 @ConfigurationProperties 注解 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -110,7 +143,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.36</version>
|
||||
<version>1.18.42</version>
|
||||
</dependency>
|
||||
|
||||
<!-- freemarker -->
|
||||
@@ -129,7 +162,7 @@
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>4.0.2</version>
|
||||
<version>4.0.4</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -137,13 +170,13 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.17.0</version>
|
||||
<version>3.18.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.18.0</version>
|
||||
<version>2.20.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
@@ -156,15 +189,107 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- Maven Surefire Plugin for JUnit 5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- JaCoCo Maven Plugin for Code Coverage -->
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.11</version>
|
||||
<executions>
|
||||
<!-- 准备JaCoCo代理,用于收集覆盖率数据 -->
|
||||
<execution>
|
||||
<id>prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<!-- 生成覆盖率报告 -->
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<!-- 检查覆盖率阈值 -->
|
||||
<execution>
|
||||
<id>check</id>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<rule>
|
||||
<element>BUNDLE</element>
|
||||
<limits>
|
||||
<!-- 指令覆盖率最低要求 -->
|
||||
<limit>
|
||||
<counter>INSTRUCTION</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.00</minimum>
|
||||
</limit>
|
||||
<!-- 分支覆盖率最低要求 -->
|
||||
<limit>
|
||||
<counter>BRANCH</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.00</minimum>
|
||||
</limit>
|
||||
<!-- 类覆盖率最低要求 -->
|
||||
<limit>
|
||||
<counter>CLASS</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.00</minimum>
|
||||
</limit>
|
||||
<!-- 方法覆盖率最低要求 -->
|
||||
<limit>
|
||||
<counter>METHOD</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.00</minimum>
|
||||
</limit>
|
||||
<!-- 行覆盖率最低要求 -->
|
||||
<limit>
|
||||
<counter>LINE</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.00</minimum>
|
||||
</limit>
|
||||
</limits>
|
||||
</rule>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!-- 排除不需要生成覆盖率报告的类 -->
|
||||
<excludes>
|
||||
<exclude>**/Application.class</exclude>
|
||||
<exclude>**/config/**</exclude>
|
||||
<exclude>**/dto/**</exclude>
|
||||
<exclude>**/vo/**</exclude>
|
||||
<exclude>**/entity/**</exclude>
|
||||
<exclude>**/util/exception/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>alimaven</id>
|
||||
<name>aliyun maven</name>
|
||||
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
/**
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(scanBasePackages = "com.softdev.system.generator")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.softdev.system.generator.config;
|
||||
|
||||
import com.softdev.system.generator.entity.ReturnT;
|
||||
import com.softdev.system.generator.entity.vo.ResultVo;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@@ -15,9 +14,9 @@ public class GlobalDefaultExceptionHandler {
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
public ReturnT defaultExceptionHandler(HttpServletRequest req, Exception e) {
|
||||
public ResultVo defaultExceptionHandler(HttpServletRequest req, Exception e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.error("代码生成失败:"+e.getMessage());
|
||||
return ResultVo.error("代码生成失败:"+e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,16 @@
|
||||
package com.softdev.system.generator.config;
|
||||
|
||||
|
||||
// import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
// import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import com.alibaba.fastjson2.JSONReader;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.alibaba.fastjson2.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
/**
|
||||
@@ -32,16 +23,16 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/statics/**").addResourceLocations("classpath:/statics/");
|
||||
}
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new XssFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("xssFilter");
|
||||
registration.setOrder(Integer.MAX_VALUE);
|
||||
return registration;
|
||||
}
|
||||
// @Bean
|
||||
// public FilterRegistrationBean xssFilterRegistration() {
|
||||
// FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
// registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
// registration.setFilter(new XssFilter());
|
||||
// registration.addUrlPatterns("/*");
|
||||
// registration.setName("xssFilter");
|
||||
// registration.setOrder(Integer.MAX_VALUE);
|
||||
// return registration;
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
@@ -74,8 +65,20 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
//自定义配置...
|
||||
FastJsonConfig config = new FastJsonConfig();
|
||||
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
config.setReaderFeatures(JSONReader.Feature.FieldBased, JSONReader.Feature.SupportArrayToBean);
|
||||
config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue, JSONWriter.Feature.PrettyFormat);
|
||||
|
||||
// 添加更多解析特性以提高容错性
|
||||
config.setReaderFeatures(
|
||||
JSONReader.Feature.FieldBased,
|
||||
JSONReader.Feature.SupportArrayToBean,
|
||||
// JSONReader.Feature.IgnoreNoneFieldGetter,
|
||||
JSONReader.Feature.InitStringFieldAsEmpty
|
||||
);
|
||||
|
||||
config.setWriterFeatures(
|
||||
JSONWriter.Feature.WriteMapNullValue,
|
||||
JSONWriter.Feature.PrettyFormat
|
||||
);
|
||||
|
||||
converter.setFastJsonConfig(config);
|
||||
converter.setDefaultCharset(StandardCharsets.UTF_8);
|
||||
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.softdev.system.generator.controller;
|
||||
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.CodeGenResult;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
import com.softdev.system.generator.entity.vo.ResultVo;
|
||||
import com.softdev.system.generator.service.CodeGenService;
|
||||
import com.softdev.system.generator.service.ZipService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成控制器
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/code")
|
||||
public class CodeGenController {
|
||||
|
||||
private final CodeGenService codeGenService;
|
||||
private final ZipService zipService;
|
||||
|
||||
@PostMapping("/generate")
|
||||
public ResultVo generateCode(@RequestBody ParamInfo paramInfo) throws Exception {
|
||||
return codeGenService.generateCode(paramInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键 ZIP 打包下载:将生成的全部代码打成 ZIP 流返回
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return ZIP 字节流
|
||||
*/
|
||||
@PostMapping(value = "/generate-zip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> generateCodeAsZip(@RequestBody ParamInfo paramInfo) throws Exception {
|
||||
log.info("收到 ZIP 下载请求");
|
||||
if (paramInfo == null || paramInfo.getTableSql() == null || paramInfo.getTableSql().isEmpty()) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
CodeGenResult result = codeGenService.getResultByParams(prepareOptions(paramInfo));
|
||||
|
||||
String zipName = (result.getClassName() != null && !result.getClassName().isEmpty())
|
||||
? result.getClassName()
|
||||
: (result.getTableName() != null && !result.getTableName().isEmpty())
|
||||
? result.getTableName()
|
||||
: "code-generator";
|
||||
|
||||
byte[] zipBytes = zipService.buildZip(
|
||||
result.getGeneratedCode(),
|
||||
result.getFileNameTemplates(),
|
||||
result.getGroupByTemplate(),
|
||||
zipName,
|
||||
buildContext(result)
|
||||
);
|
||||
|
||||
String encoded = URLEncoder.encode(zipName + ".zip", StandardCharsets.UTF_8)
|
||||
.replace("+", "%20");
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/zip"));
|
||||
// 注意:只设置一次 Content-Disposition,同时携带 ASCII 与 RFC 5987 UTF-8 形式,
|
||||
// 避免 ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION 错误
|
||||
headers.set("Content-Disposition",
|
||||
"attachment; filename=\"" + zipName + ".zip\"; filename*=UTF-8''" + encoded);
|
||||
headers.setContentLength(zipBytes.length);
|
||||
return new ResponseEntity<>(zipBytes, headers, org.springframework.http.HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与 generateCode 共享参数准备逻辑:解析、塞入 options
|
||||
*/
|
||||
private Map<String, Object> prepareOptions(ParamInfo paramInfo) throws Exception {
|
||||
Map<String, Object> options = paramInfo.getOptions() == null ? new HashMap<>() : paramInfo.getOptions();
|
||||
paramInfo.setOptions(options);
|
||||
|
||||
ClassInfo classInfo = codeGenService.parseTableStructure(paramInfo);
|
||||
options.put("classInfo", classInfo);
|
||||
options.put("tableName", classInfo == null ? System.currentTimeMillis() + "" : classInfo.getTableName());
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 ZIP 解析占位符所需的上下文
|
||||
*/
|
||||
private Map<String, Object> buildContext(CodeGenResult result) {
|
||||
Map<String, Object> ctx = new HashMap<>();
|
||||
ctx.put("className", result.getClassName() == null ? "" : result.getClassName());
|
||||
ctx.put("tableName", result.getTableName() == null ? "" : result.getTableName());
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.softdev.system.generator.controller;
|
||||
|
||||
import com.softdev.system.generator.util.ValueUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* 页面控制器
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class PageController {
|
||||
|
||||
private final ValueUtil valueUtil;
|
||||
|
||||
@GetMapping("/")
|
||||
public ModelAndView defaultPage() {
|
||||
return new ModelAndView("newui2").addObject("value", valueUtil);
|
||||
}
|
||||
|
||||
@GetMapping("/index")
|
||||
public ModelAndView indexPage() {
|
||||
return new ModelAndView("newui2").addObject("value", valueUtil);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.softdev.system.generator.controller;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.softdev.system.generator.entity.vo.ResultVo;
|
||||
import com.softdev.system.generator.service.TemplateService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 模板管理控制器
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/template")
|
||||
public class TemplateController {
|
||||
|
||||
private final TemplateService templateService;
|
||||
|
||||
@PostMapping("/all")
|
||||
public ResultVo getAllTemplates() throws Exception {
|
||||
return ResultVo.ok(templateService.getAllTemplates());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.softdev.system.generator.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 类信息
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Data
|
||||
public class ClassInfo {
|
||||
|
||||
private String tableName;
|
||||
private String originTableName;
|
||||
private String className;
|
||||
private String classComment;
|
||||
private List<FieldInfo> fieldList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.softdev.system.generator.entity.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成结果封装
|
||||
* <p>
|
||||
* 携带:渲染后的代码、模板 fileName 模板、模板分组,供 ZIP 打包 / 单文件下载等场景使用。
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CodeGenResult {
|
||||
|
||||
/** 表名(原始或处理后) */
|
||||
private String tableName;
|
||||
|
||||
/** 类名 */
|
||||
private String className;
|
||||
|
||||
/** 渲染结果:key=template.name, value=渲染后的内容 */
|
||||
private Map<String, String> generatedCode;
|
||||
|
||||
/** 模板 fileName 配置:key=template.name, value=fileName 模板(可含 ${className} 占位符) */
|
||||
private Map<String, String> fileNameTemplates;
|
||||
|
||||
/** 模板分组:key=template.name, value=group */
|
||||
private Map<String, String> groupByTemplate;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.softdev.system.generator.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 字段信息
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Data
|
||||
public class FieldInfo {
|
||||
|
||||
private String columnName;
|
||||
private String fieldName;
|
||||
private String fieldClass;
|
||||
private String swaggerClass;
|
||||
private String fieldComment;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.softdev.system.generator.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 请求参数信息
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Data
|
||||
public class ParamInfo {
|
||||
|
||||
private String tableSql;
|
||||
private Map<String, Object> options;
|
||||
|
||||
@Data
|
||||
public static class NameCaseType {
|
||||
public static final String CAMEL_CASE = "CamelCase";
|
||||
public static final String UNDER_SCORE_CASE = "UnderScoreCase";
|
||||
public static final String UPPER_UNDER_SCORE_CASE = "UpperUnderScoreCase";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.softdev.system.generator.entity.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 解析类型枚举
|
||||
*/
|
||||
@Getter
|
||||
public enum ParserTypeEnum {
|
||||
|
||||
/**
|
||||
* SQL解析类型
|
||||
*/
|
||||
SQL("sql", "默认SQL解析"),
|
||||
JSON("json", "JSON解析"),
|
||||
INSERT_SQL("insert-sql", "INSERT SQL解析"),
|
||||
SQL_REGEX("sql-regex", "正则表达式SQL解析"),
|
||||
SELECT_SQL("select-sql", "SELECT SQL解析"),
|
||||
CREATE_SQL("create-sql", "CREATE SQL解析");
|
||||
|
||||
private final String value;
|
||||
private final String description;
|
||||
|
||||
ParserTypeEnum(String value, String description) {
|
||||
this.value = value;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public static ParserTypeEnum fromValue(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return SQL;
|
||||
}
|
||||
|
||||
String trimmedValue = value.trim();
|
||||
|
||||
// 首先尝试精确匹配枚举值
|
||||
for (ParserTypeEnum type : ParserTypeEnum.values()) {
|
||||
if (type.getValue().equals(trimmedValue)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果精确匹配失败,尝试忽略大小写匹配
|
||||
for (ParserTypeEnum type : ParserTypeEnum.values()) {
|
||||
if (type.getValue().equalsIgnoreCase(trimmedValue)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试匹配枚举名称
|
||||
for (ParserTypeEnum type : ParserTypeEnum.values()) {
|
||||
if (type.name().equalsIgnoreCase(trimmedValue)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// 默认返回SQL类型
|
||||
return SQL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.softdev.system.generator.entity.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一返回结果VO
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Data
|
||||
public class ResultVo extends HashMap<String, Object> {
|
||||
|
||||
public ResultVo() {
|
||||
put("code", 200);
|
||||
put("msg", "success");
|
||||
}
|
||||
|
||||
public static ResultVo ok() {
|
||||
return new ResultVo();
|
||||
}
|
||||
|
||||
public static ResultVo ok(Object data) {
|
||||
ResultVo resultVo = new ResultVo();
|
||||
resultVo.put("data", data);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
public static ResultVo error(String msg) {
|
||||
ResultVo resultVo = new ResultVo();
|
||||
resultVo.put("code", 500);
|
||||
resultVo.put("msg", msg);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
public static ResultVo error(int code, String msg) {
|
||||
ResultVo resultVo = new ResultVo();
|
||||
resultVo.put("code", code);
|
||||
resultVo.put("msg", msg);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultVo put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.softdev.system.generator.service;
|
||||
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.CodeGenResult;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
import com.softdev.system.generator.entity.vo.ResultVo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成服务接口
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface CodeGenService {
|
||||
|
||||
/**
|
||||
* 生成代码(前端在线预览版本)
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 生成的代码映射(key=模板名, value=渲染内容)
|
||||
* @throws Exception 生成过程中的异常
|
||||
*/
|
||||
ResultVo generateCode(ParamInfo paramInfo) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析表结构(仅解析,不生成)
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
ClassInfo parseTableStructure(ParamInfo paramInfo) throws Exception;
|
||||
|
||||
/**
|
||||
* 根据参数获取结果(富信息版本,包含模板分组与 fileName 配置)
|
||||
*
|
||||
* @param params 参数映射(含 classInfo、tableName 等)
|
||||
* @return CodeGenResult
|
||||
* @throws Exception 处理过程中的异常
|
||||
*/
|
||||
CodeGenResult getResultByParams(Map<String, Object> params) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.softdev.system.generator.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 模板服务接口
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface TemplateService {
|
||||
|
||||
/**
|
||||
* 获取所有模板配置
|
||||
*
|
||||
* @return 模板配置字符串
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
JSONArray getAllTemplates() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.softdev.system.generator.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ZIP 打包服务接口
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface ZipService {
|
||||
|
||||
/**
|
||||
* 将已生成的代码结果(key=模板名, value=渲染后内容)打包为 ZIP
|
||||
*
|
||||
* @param generatedCode 模板渲染结果(key=template.name, value=内容)
|
||||
* @param fileNameTemplates 模板元数据(key=template.name, value=fileName 模板,可含 ${className} 占位符,可为 null)
|
||||
* @param groupByTemplate 模板元数据(key=template.name, value=group 名称)
|
||||
* @param zipFileName 最终 zip 文件名(不含后缀)
|
||||
* @param context 解析占位符的上下文(至少含 className、tableName)
|
||||
* @return zip 字节数组
|
||||
*/
|
||||
byte[] buildZip(Map<String, String> generatedCode,
|
||||
Map<String, String> fileNameTemplates,
|
||||
Map<String, String> groupByTemplate,
|
||||
String zipFileName,
|
||||
Map<String, Object> context);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.softdev.system.generator.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.CodeGenResult;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
import com.softdev.system.generator.entity.enums.ParserTypeEnum;
|
||||
import com.softdev.system.generator.entity.vo.ResultVo;
|
||||
import com.softdev.system.generator.service.CodeGenService;
|
||||
import com.softdev.system.generator.service.TemplateService;
|
||||
import com.softdev.system.generator.service.parser.JsonParserService;
|
||||
import com.softdev.system.generator.service.parser.SqlParserService;
|
||||
import com.softdev.system.generator.util.FreemarkerUtil;
|
||||
import com.softdev.system.generator.util.MapUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成服务实现类
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CodeGenServiceImpl implements CodeGenService {
|
||||
|
||||
private final TemplateService templateService;
|
||||
private final SqlParserService sqlParserService;
|
||||
private final JsonParserService jsonParserService;
|
||||
|
||||
@Override
|
||||
public ResultVo generateCode(ParamInfo paramInfo) throws Exception {
|
||||
if (paramInfo.getTableSql() == null || paramInfo.getTableSql().isEmpty()) {
|
||||
return ResultVo.error("表结构信息为空");
|
||||
}
|
||||
|
||||
try {
|
||||
CodeGenResult result = doGenerate(paramInfo);
|
||||
Map<String, String> generatedCode = result.getGeneratedCode();
|
||||
generatedCode.put("tableName", result.getTableName());
|
||||
log.info("table:{} - time:{} ", result.getTableName(), System.currentTimeMillis());
|
||||
return ResultVo.ok(generatedCode);
|
||||
} catch (Exception e) {
|
||||
log.error("代码生成失败", e);
|
||||
return ResultVo.error("代码生成失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo parseTableStructure(ParamInfo paramInfo) throws Exception {
|
||||
if (paramInfo.getTableSql() == null || paramInfo.getTableSql().isEmpty()) {
|
||||
throw new IllegalArgumentException("表结构信息为空");
|
||||
}
|
||||
return parseByType(paramInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeGenResult getResultByParams(Map<String, Object> params) throws Exception {
|
||||
CodeGenResult.CodeGenResultBuilder builder = CodeGenResult.builder();
|
||||
|
||||
Map<String, String> generatedCode = new LinkedHashMap<>();
|
||||
Map<String, String> fileNameTemplates = new LinkedHashMap<>();
|
||||
Map<String, String> groupByTemplate = new LinkedHashMap<>();
|
||||
|
||||
generatedCode.put("tableName", MapUtil.getString(params, "tableName"));
|
||||
|
||||
JSONArray parentTemplates = templateService.getAllTemplates();
|
||||
for (int i = 0; i < parentTemplates.size(); i++) {
|
||||
JSONObject parentTemplateObj = parentTemplates.getJSONObject(i);
|
||||
String group = parentTemplateObj.getString("group");
|
||||
JSONArray childTemplates = parentTemplateObj.getJSONArray("templates");
|
||||
if (childTemplates != null) {
|
||||
for (int x = 0; x < childTemplates.size(); x++) {
|
||||
JSONObject childTemplate = childTemplates.getJSONObject(x);
|
||||
String templateName = childTemplate.getString("name");
|
||||
String templatePath = group + "/" + templateName + ".ftl";
|
||||
String generatedText = FreemarkerUtil.processString(templatePath, params);
|
||||
generatedCode.put(templateName, generatedText);
|
||||
fileNameTemplates.put(templateName, childTemplate.getString("fileName"));
|
||||
groupByTemplate.put(templateName, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object classInfo = params.get("classInfo");
|
||||
String className = null;
|
||||
if (classInfo instanceof ClassInfo) {
|
||||
className = ((ClassInfo) classInfo).getClassName();
|
||||
}
|
||||
if (className == null) {
|
||||
className = MapUtil.getString(params, "tableName");
|
||||
}
|
||||
return builder
|
||||
.tableName(MapUtil.getString(params, "tableName"))
|
||||
.className(className)
|
||||
.generatedCode(generatedCode)
|
||||
.fileNameTemplates(fileNameTemplates)
|
||||
.groupByTemplate(groupByTemplate)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 共享的生成逻辑:先解析,再调用 getResultByParams
|
||||
*/
|
||||
private CodeGenResult doGenerate(ParamInfo paramInfo) throws Exception {
|
||||
ClassInfo classInfo = parseByType(paramInfo);
|
||||
|
||||
paramInfo.getOptions().put("classInfo", classInfo);
|
||||
paramInfo.getOptions().put("tableName", classInfo == null ? System.currentTimeMillis() + "" : classInfo.getTableName());
|
||||
|
||||
return getResultByParams(paramInfo.getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据不同的解析类型解析表结构
|
||||
*/
|
||||
private ClassInfo parseByType(ParamInfo paramInfo) throws Exception {
|
||||
String dataType = MapUtil.getString(paramInfo.getOptions(), "dataType");
|
||||
ParserTypeEnum parserType = ParserTypeEnum.fromValue(dataType);
|
||||
log.debug("解析数据类型: {}, 解析结果: {}", dataType, parserType);
|
||||
|
||||
switch (parserType) {
|
||||
case SQL:
|
||||
return sqlParserService.processTableIntoClassInfo(paramInfo);
|
||||
case JSON:
|
||||
return jsonParserService.processJsonToClassInfo(paramInfo);
|
||||
case INSERT_SQL:
|
||||
return sqlParserService.processInsertSqlToClassInfo(paramInfo);
|
||||
case SQL_REGEX:
|
||||
return sqlParserService.processTableToClassInfoByRegex(paramInfo);
|
||||
case SELECT_SQL:
|
||||
return sqlParserService.generateSelectSqlBySQLPraser(paramInfo);
|
||||
case CREATE_SQL:
|
||||
return sqlParserService.generateCreateSqlBySQLPraser(paramInfo);
|
||||
default:
|
||||
return sqlParserService.processTableIntoClassInfo(paramInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.softdev.system.generator.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.softdev.system.generator.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 模板服务实现类
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TemplateServiceImpl implements TemplateService {
|
||||
|
||||
private String templateConfig = null;
|
||||
|
||||
@Override
|
||||
public JSONArray getAllTemplates() throws IOException {
|
||||
if (templateConfig == null) {
|
||||
ClassPathResource resource = new ClassPathResource("template.json");
|
||||
try (InputStream inputStream = resource.getInputStream()) {
|
||||
templateConfig = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
return JSONArray.parseArray(templateConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.softdev.system.generator.service.impl;
|
||||
|
||||
import com.softdev.system.generator.service.ZipService;
|
||||
import com.softdev.system.generator.util.ZipFileNameResolver;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* ZIP 打包服务实现类
|
||||
* <p>
|
||||
* 使用 JDK 自带 ZipOutputStream 打包,零依赖。
|
||||
* <p>
|
||||
* 目录结构:{group}/{fileName},同名文件自动加序号去重。
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ZipServiceImpl implements ZipService {
|
||||
|
||||
@Override
|
||||
public byte[] buildZip(Map<String, String> generatedCode,
|
||||
Map<String, String> fileNameTemplates,
|
||||
Map<String, String> groupByTemplate,
|
||||
String zipFileName,
|
||||
Map<String, Object> context) {
|
||||
if (generatedCode == null || generatedCode.isEmpty()) {
|
||||
throw new IllegalArgumentException("没有可打包的生成内容");
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(64 * 1024);
|
||||
Set<String> usedPaths = new HashSet<>();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
zos.setLevel(java.util.zip.Deflater.BEST_SPEED);
|
||||
for (Map.Entry<String, String> entry : generatedCode.entrySet()) {
|
||||
String templateName = entry.getKey();
|
||||
String content = entry.getValue();
|
||||
if (content == null) {
|
||||
continue;
|
||||
}
|
||||
String fileNameTpl = fileNameTemplates == null ? null : fileNameTemplates.get(templateName);
|
||||
String group = groupByTemplate == null ? "generated" : groupByTemplate.getOrDefault(templateName, "generated");
|
||||
String fileName = ZipFileNameResolver.resolve(fileNameTpl, templateName, group, context);
|
||||
String entryPath = uniquePath(group, fileName, usedPaths);
|
||||
writeEntry(zos, entryPath, content);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("ZIP 打包失败: zipFileName={}", zipFileName, e);
|
||||
throw new RuntimeException("ZIP 打包失败: " + e.getMessage(), e);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
private void writeEntry(ZipOutputStream zos, String entryPath, String content) throws IOException {
|
||||
ZipEntry zipEntry = new ZipEntry(entryPath);
|
||||
zipEntry.setSize(content.getBytes(StandardCharsets.UTF_8).length);
|
||||
zos.putNextEntry(zipEntry);
|
||||
zos.write(content.getBytes(StandardCharsets.UTF_8));
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 entry 路径;遇到重名时加 _1 / _2 ...
|
||||
*/
|
||||
private String uniquePath(String group, String fileName, Set<String> used) {
|
||||
String base = sanitizeGroup(group) + "/" + fileName;
|
||||
if (used.add(base)) {
|
||||
return base;
|
||||
}
|
||||
int dot = fileName.lastIndexOf('.');
|
||||
String prefix = dot < 0 ? fileName : fileName.substring(0, dot);
|
||||
String suffix = dot < 0 ? "" : fileName.substring(dot);
|
||||
for (int i = 1; i < 1000; i++) {
|
||||
String candidate = sanitizeGroup(group) + "/" + prefix + "_" + i + suffix;
|
||||
if (used.add(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return sanitizeGroup(group) + "/" + System.nanoTime() + "_" + fileName;
|
||||
}
|
||||
|
||||
private String sanitizeGroup(String group) {
|
||||
if (group == null || group.trim().isEmpty()) {
|
||||
return "generated";
|
||||
}
|
||||
return group.trim().replaceAll("[\\\\/:*?\"<>|\\r\\n\\t]", "_");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.softdev.system.generator.service.impl.parser;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.FieldInfo;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
import com.softdev.system.generator.service.parser.JsonParserService;
|
||||
import com.softdev.system.generator.util.exception.CodeGenException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* JSON解析服务实现类
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Service
|
||||
public class JsonParserServiceImpl implements JsonParserService {
|
||||
|
||||
@Override
|
||||
public ClassInfo processJsonToClassInfo(ParamInfo paramInfo) {
|
||||
ClassInfo codeJavaInfo = new ClassInfo();
|
||||
codeJavaInfo.setTableName("JsonDto");
|
||||
codeJavaInfo.setClassName("JsonDto");
|
||||
codeJavaInfo.setClassComment("JsonDto");
|
||||
|
||||
//support children json if forget to add '{' in front of json
|
||||
if (paramInfo.getTableSql().trim().startsWith("\"")) {
|
||||
paramInfo.setTableSql("{" + paramInfo.getTableSql());
|
||||
}
|
||||
try {
|
||||
if (paramInfo.getTableSql().trim().startsWith("{")) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(paramInfo.getTableSql().trim());
|
||||
//parse FieldList by JSONObject
|
||||
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonObject));
|
||||
} else if (paramInfo.getTableSql().trim().startsWith("[")) {
|
||||
JSONArray jsonArray = JSONArray.parseArray(paramInfo.getTableSql().trim());
|
||||
//parse FieldList by JSONObject
|
||||
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonArray.getJSONObject(0)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// JSON解析失败,抛出自定义异常
|
||||
throw new CodeGenException("JSON格式不正确: " + e.getMessage());
|
||||
}
|
||||
|
||||
return codeJavaInfo;
|
||||
}
|
||||
|
||||
public List<FieldInfo> processJsonObjectToFieldList(JSONObject jsonObject) {
|
||||
// field List
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
for (String jsonField : jsonObject.keySet()) {
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
fieldInfo.setFieldName(jsonField);
|
||||
fieldInfo.setColumnName(jsonField);
|
||||
fieldInfo.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo.setFieldComment("father:" + jsonField);
|
||||
fieldList.add(fieldInfo);
|
||||
if (jsonObject.get(jsonField) instanceof JSONArray) {
|
||||
JSONArray jsonArray = jsonObject.getJSONArray(jsonField);
|
||||
for (Object arrayObject : jsonArray) {
|
||||
FieldInfo fieldInfo2 = new FieldInfo();
|
||||
fieldInfo2.setFieldName(arrayObject.toString());
|
||||
fieldInfo2.setColumnName(arrayObject.toString());
|
||||
fieldInfo2.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
|
||||
fieldList.add(fieldInfo2);
|
||||
}
|
||||
} else if (jsonObject.get(jsonField) instanceof JSONObject) {
|
||||
JSONObject subJsonObject = jsonObject.getJSONObject(jsonField);
|
||||
for (String arrayObject : subJsonObject.keySet()) {
|
||||
FieldInfo fieldInfo2 = new FieldInfo();
|
||||
fieldInfo2.setFieldName(arrayObject.toString());
|
||||
fieldInfo2.setColumnName(arrayObject.toString());
|
||||
fieldInfo2.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
|
||||
fieldList.add(fieldInfo2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fieldList.size() < 1) {
|
||||
throw new CodeGenException("JSON解析失败");
|
||||
}
|
||||
return fieldList;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +1,82 @@
|
||||
package com.softdev.system.generator.service;
|
||||
package com.softdev.system.generator.service.impl.parser;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.softdev.system.generator.entity.*;
|
||||
import com.softdev.system.generator.util.*;
|
||||
import freemarker.template.TemplateException;
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.FieldInfo;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
import com.softdev.system.generator.service.parser.SqlParserService;
|
||||
import com.softdev.system.generator.util.MapUtil;
|
||||
import com.softdev.system.generator.util.StringUtilsPlus;
|
||||
import com.softdev.system.generator.util.exception.SqlParseException;
|
||||
import com.softdev.system.generator.util.mysqlJavaTypeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserManager;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
|
||||
import net.sf.jsqlparser.statement.create.table.CreateTable;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.SelectItem;
|
||||
import net.sf.jsqlparser.util.TablesNamesFinder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* GeneratorService
|
||||
* SQL解析服务实现类
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class GeneratorServiceImpl implements GeneratorService {
|
||||
public class SqlParserServiceImpl implements SqlParserService {
|
||||
|
||||
String templateCpnfig = null;
|
||||
|
||||
/**
|
||||
* 从项目中的JSON文件读取String
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Override
|
||||
public String getTemplateConfig() throws IOException {
|
||||
templateCpnfig = null;
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template.json");
|
||||
templateCpnfig = new BufferedReader(new InputStreamReader(inputStream))
|
||||
.lines().collect(Collectors.joining(System.lineSeparator()));
|
||||
inputStream.close();
|
||||
//log.info(JSON.toJSONString(templateCpnfig));
|
||||
return templateCpnfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置的Template模板进行遍历解析,得到生成好的String
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException {
|
||||
Map<String, String> result = new HashMap<>(32);
|
||||
result.put("tableName", MapUtil.getString(params,"tableName"));
|
||||
JSONArray parentTemplates = JSONArray.parseArray(getTemplateConfig());
|
||||
for (int i = 0; i <parentTemplates.size() ; i++) {
|
||||
JSONObject parentTemplateObj = parentTemplates.getJSONObject(i);
|
||||
for (int x = 0; x <parentTemplateObj.getJSONArray("templates").size() ; x++) {
|
||||
JSONObject childTemplate = parentTemplateObj.getJSONArray("templates").getJSONObject(x);
|
||||
result.put(childTemplate.getString("name"), FreemarkerUtil.processString(parentTemplateObj.getString("group") + "/" +childTemplate.getString("name")+ ".ftl", params));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据SQL解析器解析表结构
|
||||
* @author zhengkai.blog.csdn.net
|
||||
* @param paramInfo
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public ClassInfo generateSelectSqlBySQLPraser(ParamInfo paramInfo) throws Exception {
|
||||
ClassInfo classInfo = new ClassInfo();
|
||||
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(paramInfo.getTableSql());
|
||||
List<SelectItem<?>> columnNameList = select.getSelectItems();
|
||||
log.info("tableName:{}", select.getFromItem().toString());
|
||||
String processedSql = paramInfo.getTableSql().trim()
|
||||
.replaceAll("'", "`") // 将单引号替换为反引号
|
||||
.replaceAll("\"", "`") // 将双引号替换为反引号
|
||||
.replaceAll(",", ","); // 将中文逗号替换为英文逗号
|
||||
|
||||
Statement statement = null;
|
||||
CCJSqlParserManager parserManager = new CCJSqlParserManager();
|
||||
statement = parserManager.parse(new StringReader(processedSql));
|
||||
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); // 创建表名发现者对象
|
||||
List<String> tableNameList = tablesNamesFinder.getTableList(statement); // 获取到表名列表
|
||||
//一般这里应该只解析到一个表名,除非多个表名,取第一个
|
||||
if (!CollectionUtils.isEmpty(tableNameList)) {
|
||||
String tableName = tableNameList.get(0).trim();
|
||||
classInfo.setTableName(tableName);
|
||||
classInfo.setOriginTableName(tableName);
|
||||
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName)).replaceAll("`", "");
|
||||
if (className.contains("_")) {
|
||||
className = className.replaceAll("_", "");
|
||||
}
|
||||
classInfo.setClassName(className);
|
||||
classInfo.setClassComment(paramInfo.getTableSql());
|
||||
}
|
||||
//解析查询元素
|
||||
Select select = null;
|
||||
select = (Select) CCJSqlParserUtil.parse(paramInfo.getTableSql());
|
||||
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
|
||||
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
|
||||
|
||||
// field List
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
columnNameList.forEach(t->{
|
||||
selectItems.forEach(t->{
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
String fieldName = ((Column)t.getExpression()).getColumnName();
|
||||
String fieldName = ((Column)t.getExpression()).getColumnName().replaceAll("`", "");
|
||||
String aliasName = t.getAlias() != null ? t.getAlias().getName() : ((Column)t.getExpression()).getColumnName();
|
||||
//存储原始字段名
|
||||
fieldInfo.setFieldComment(aliasName);fieldInfo.setColumnName(aliasName);
|
||||
@@ -96,21 +84,15 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
fieldName=fieldName.contains(".")?fieldName.substring(fieldName.indexOf(".")+1):fieldName;
|
||||
//转换前
|
||||
fieldInfo.setColumnName(fieldName);
|
||||
switch ((String) paramInfo.getOptions().get("nameCaseType")) {
|
||||
case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE:
|
||||
fieldName = switch ((String) paramInfo.getOptions().get("nameCaseType")) {
|
||||
case ParamInfo.NameCaseType.CAMEL_CASE ->
|
||||
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
|
||||
fieldName = StringUtilsPlus.toLowerCamel(aliasName);
|
||||
break;
|
||||
case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE:
|
||||
fieldName = StringUtilsPlus.toUnderline(aliasName, false);
|
||||
break;
|
||||
case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE:
|
||||
fieldName = StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true);
|
||||
break;
|
||||
default:
|
||||
fieldName = aliasName;
|
||||
break;
|
||||
}
|
||||
StringUtilsPlus.toLowerCamel(aliasName);
|
||||
case ParamInfo.NameCaseType.UNDER_SCORE_CASE -> StringUtilsPlus.toUnderline(aliasName, false);
|
||||
case ParamInfo.NameCaseType.UPPER_UNDER_SCORE_CASE ->
|
||||
StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true);
|
||||
default -> aliasName;
|
||||
};
|
||||
//转换后
|
||||
fieldInfo.setFieldName(fieldName);
|
||||
|
||||
@@ -119,35 +101,85 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
fieldList.add(fieldInfo);
|
||||
});
|
||||
classInfo.setFieldList(fieldList);
|
||||
String tableName = select.getFromItem().toString();
|
||||
classInfo.setTableName(tableName);
|
||||
//如果表名有空格,取空格前的第一个单词作为类名
|
||||
if(tableName.indexOf(" ")>0){
|
||||
classInfo.setClassName(StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName.substring(0,tableName.indexOf(" ")))));
|
||||
}else{
|
||||
classInfo.setClassName(StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName)));
|
||||
}
|
||||
log.info("classInfo:{}", JSON.toJSONString(classInfo));
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析DDL SQL生成类信息(默认模式|核心模式)
|
||||
*
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
|
||||
throws IOException {
|
||||
public ClassInfo generateCreateSqlBySQLPraser(ParamInfo paramInfo) throws Exception {
|
||||
ClassInfo classInfo = new ClassInfo();
|
||||
Statement statement = null;
|
||||
// 对SQL进行预处理,以提高解析成功率
|
||||
String processedSql = paramInfo.getTableSql().trim()
|
||||
.replaceAll("'", "`") // 将单引号替换为反引号
|
||||
.replaceAll("\"", "`") // 将双引号替换为反引号
|
||||
.replaceAll(",", ","); // 将中文逗号替换为英文逗号
|
||||
|
||||
try {
|
||||
statement = CCJSqlParserUtil.parse(processedSql);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SqlParseException("SQL语法错误:"+e.getMessage());
|
||||
}
|
||||
|
||||
// 确保是CREATE TABLE语句
|
||||
if (!(statement instanceof CreateTable createTable)) {
|
||||
throw new SqlParseException("检测到SQL语句不是DLL CREATE TABLE语句");
|
||||
}
|
||||
|
||||
// 提取表名
|
||||
String tableName = createTable.getTable().getName().replaceAll("`", "");
|
||||
classInfo.setTableName(tableName);
|
||||
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName));
|
||||
if (className.contains("_")) {
|
||||
className = className.replaceAll("_", "");
|
||||
}
|
||||
classInfo.setClassName(className);
|
||||
classInfo.setOriginTableName(tableName);
|
||||
classInfo.setClassComment(paramInfo.getTableSql());
|
||||
|
||||
// 提取字段信息
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();
|
||||
|
||||
if (columnDefinitions != null) {
|
||||
for (ColumnDefinition columnDefinition : columnDefinitions) {
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
String columnName = columnDefinition.getColumnName().replaceAll("`", "");
|
||||
fieldInfo.setColumnName(columnName);
|
||||
fieldInfo.setFieldComment(columnDefinition.toString());
|
||||
|
||||
// 根据命名规则转换字段名
|
||||
String fieldName = switch ((String) paramInfo.getOptions().get("nameCaseType")) {
|
||||
case ParamInfo.NameCaseType.CAMEL_CASE -> StringUtilsPlus.toLowerCamel(columnName);
|
||||
case ParamInfo.NameCaseType.UNDER_SCORE_CASE -> StringUtilsPlus.toUnderline(columnName, false);
|
||||
case ParamInfo.NameCaseType.UPPER_UNDER_SCORE_CASE ->
|
||||
StringUtilsPlus.toUnderline(columnName.toUpperCase(), true);
|
||||
default -> columnName;
|
||||
};
|
||||
fieldInfo.setFieldName(fieldName);
|
||||
|
||||
// 设置字段类型为String(因为无法准确推测类型)
|
||||
fieldInfo.setFieldClass("String");
|
||||
fieldList.add(fieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
classInfo.setFieldList(fieldList);
|
||||
log.info("classInfo:{}", JSON.toJSONString(classInfo));
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo processTableIntoClassInfo(ParamInfo paramInfo) throws Exception {
|
||||
//process the param
|
||||
NonCaseString tableSql = NonCaseString.of(paramInfo.getTableSql());
|
||||
String tableSql = paramInfo.getTableSql();
|
||||
String nameCaseType = MapUtil.getString(paramInfo.getOptions(),"nameCaseType");
|
||||
Boolean isPackageType = MapUtil.getBoolean(paramInfo.getOptions(),"isPackageType");
|
||||
String isPackageType = MapUtil.getString(paramInfo.getOptions(),"isPackageType");
|
||||
|
||||
//更新空值处理
|
||||
if (StringUtils.isBlank(tableSql)) {
|
||||
throw new CodeGenerateException("Table structure can not be empty. 表结构不能为空。");
|
||||
throw new Exception("Table structure can not be empty. 表结构不能为空。");
|
||||
}
|
||||
//deal with special character
|
||||
tableSql = tableSql.trim()
|
||||
@@ -163,9 +195,9 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
String tableName = null;
|
||||
int tableKwIx = tableSql.indexOf("TABLE"); // 包含判断和位置一次搞定
|
||||
if (tableKwIx > -1 && tableSql.contains("(")) {
|
||||
tableName = tableSql.substring(tableKwIx + 5, tableSql.indexOf("(")).get();
|
||||
tableName = tableSql.substring(tableKwIx + 5, tableSql.indexOf("("));
|
||||
} else {
|
||||
throw new CodeGenerateException("Table structure incorrect.表结构不正确。");
|
||||
throw new Exception("Table structure incorrect.表结构不正确。");
|
||||
}
|
||||
|
||||
//新增处理create table if not exists members情况
|
||||
@@ -201,11 +233,11 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
String classComment = null;
|
||||
//mysql是comment=,pgsql/oracle是comment on table,
|
||||
//2020-05-25 优化表备注的获取逻辑
|
||||
if (tableSql.containsAny("comment=", "comment on table")) {
|
||||
int ix = tableSql.lastIndexOf("comment=");
|
||||
if (tableSql.toLowerCase().contains("comment=") || tableSql.toLowerCase().contains("comment on table")) {
|
||||
int ix = tableSql.toLowerCase().lastIndexOf("comment=");
|
||||
String classCommentTmp = (ix > -1) ?
|
||||
tableSql.substring(ix + 8).trim().get() :
|
||||
tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim().get();
|
||||
tableSql.substring(ix + 8).trim() :
|
||||
tableSql.substring(tableSql.toLowerCase().lastIndexOf("comment on table") + 17).trim();
|
||||
if (classCommentTmp.contains("`")) {
|
||||
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf("`") + 1);
|
||||
classCommentTmp = classCommentTmp.substring(0, classCommentTmp.indexOf("`"));
|
||||
@@ -224,11 +256,11 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
|
||||
// 正常( ) 内的一定是字段相关的定义。
|
||||
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).get();
|
||||
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).trim();
|
||||
|
||||
// 匹配 comment,替换备注里的小逗号, 防止不小心被当成切割符号切割
|
||||
String commentPattenStr1 = "comment `(.*?)\\`";
|
||||
Matcher matcher1 = Pattern.compile(commentPattenStr1).matcher(fieldListTmp);
|
||||
Matcher matcher1 = Pattern.compile(commentPattenStr1).matcher(fieldListTmp.toLowerCase());
|
||||
while (matcher1.find()) {
|
||||
|
||||
String commentTmp = matcher1.group();
|
||||
@@ -265,17 +297,29 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
int i = 0;
|
||||
//i为了解决primary key关键字出现的地方,出现在前3行,一般和id有关
|
||||
for (String columnLine0 : fieldLineList) {
|
||||
NonCaseString columnLine = NonCaseString.of(columnLine0);
|
||||
i++;
|
||||
columnLine = columnLine.replaceAll("\n", "").replaceAll("\t", "").trim();
|
||||
String columnLine = columnLine0.replaceAll("\n", "").replaceAll("\t", "").trim();
|
||||
// `userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
|
||||
// 2018-9-18 zhengk 修改为contains,提升匹配率和匹配不按照规矩出牌的语句
|
||||
// 2018-11-8 zhengkai 修复tornadoorz反馈的KEY FK_permission_id (permission_id),KEY FK_role_id (role_id)情况
|
||||
// 2019-2-22 zhengkai 要在条件中使用复杂的表达式
|
||||
// 2019-4-29 zhengkai 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 )
|
||||
// 2020-10-20 zhengkai 优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)
|
||||
// 2023-8-27 L&J 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
|
||||
boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
|
||||
// 2025-12-07 zhengkai 修复对primary key的处理
|
||||
boolean notSpecialFlag = (
|
||||
!columnLine.contains("key ")
|
||||
&& !columnLine.toLowerCase().contains("constraint")
|
||||
&& !columnLine.toLowerCase().contains(" using ")
|
||||
&& !columnLine.toLowerCase().contains("unique ")
|
||||
&& !columnLine.toLowerCase().contains("fulltext ")
|
||||
&& !columnLine.toLowerCase().contains("index ")
|
||||
&& !columnLine.toLowerCase().contains("pctincrease")
|
||||
&& !columnLine.toLowerCase().contains("buffer_pool")
|
||||
&& !columnLine.toLowerCase().contains("tablespace")
|
||||
&& !(columnLine.toLowerCase().contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
|
||||
&& !(columnLine.toLowerCase().contains("primary ") && i > 3)
|
||||
&& !columnLine.toLowerCase().contains("primary key")
|
||||
);
|
||||
|
||||
if (notSpecialFlag) {
|
||||
//如果是oracle的number(x,x),可能出现最后分割残留的,x),这里做排除处理
|
||||
@@ -287,7 +331,7 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
columnLine = columnLine.replaceAll("`", " ").replaceAll("\"", " ").replaceAll("'", "").replaceAll(" ", " ").trim();
|
||||
//如果遇到username varchar(65) default '' not null,这种情况,判断第一个空格是否比第一个引号前
|
||||
try {
|
||||
columnName = columnLine.substring(0, columnLine.indexOf(" ")).get();
|
||||
columnName = columnLine.substring(0, columnLine.indexOf(" "));
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
System.out.println("err happened: " + columnLine);
|
||||
throw e;
|
||||
@@ -297,19 +341,22 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
|
||||
// 2023-8-27 L&J 支持原始列名任意命名风格, 不依赖用户是否输入下划线
|
||||
String fieldName = null;
|
||||
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
|
||||
if (ParamInfo.NameCaseType.CAMEL_CASE.equals(nameCaseType)) {
|
||||
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
|
||||
fieldName = StringUtilsPlus.toLowerCamel(columnName);
|
||||
} else if (ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)) {
|
||||
} else if (ParamInfo.NameCaseType.UNDER_SCORE_CASE.equals(nameCaseType)) {
|
||||
fieldName = StringUtilsPlus.toUnderline(columnName, false);
|
||||
} else if (ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
|
||||
} else if (ParamInfo.NameCaseType.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
|
||||
fieldName = StringUtilsPlus.toUnderline(columnName.toUpperCase(), true);
|
||||
} else {
|
||||
fieldName = columnName;
|
||||
}
|
||||
columnLine = columnLine.substring(columnLine.indexOf("`") + 1).trim();
|
||||
// 修复Oracle字段名不带引号的情况
|
||||
if (columnLine.contains("`")) {
|
||||
columnLine = columnLine.substring(columnLine.indexOf("`") + 1).trim();
|
||||
}
|
||||
//2025-03-16 修复由于类型大写导致无法转换的问题
|
||||
String mysqlType = columnLine.split("\\s+")[1].toLowerCase(Locale.ROOT);
|
||||
String mysqlType = columnLine.split("\\s+")[1].toLowerCase();
|
||||
if(mysqlType.contains("(")){
|
||||
mysqlType = mysqlType.substring(0, mysqlType.indexOf("("));
|
||||
}
|
||||
@@ -330,23 +377,23 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
}
|
||||
// field comment,MySQL的一般位于field行,而pgsql和oralce多位于后面。
|
||||
String fieldComment = null;
|
||||
if (tableSql.contains("comment on column") && (tableSql.contains("." + columnName + " is ") || tableSql.contains(".`" + columnName + "` is"))) {
|
||||
if (tableSql.toLowerCase().contains("comment on column") && (tableSql.toLowerCase().contains("." + columnName + " is ") || tableSql.toLowerCase().contains(".`" + columnName + "` is"))) {
|
||||
//新增对pgsql/oracle的字段备注支持
|
||||
//COMMENT ON COLUMN public.check_info.check_name IS '检查者名称';
|
||||
//2018-11-22 lshz0088 正则表达式的点号前面应该加上两个反斜杠,否则会认为是任意字符
|
||||
//2019-4-29 zhengkai 优化对oracle注释comment on column的支持(@liukex)
|
||||
tableSql = tableSql.replaceAll(".`" + columnName + "` is", "." + columnName + " is");
|
||||
Matcher columnCommentMatcher = Pattern.compile("\\." + columnName + " is `").matcher(tableSql);
|
||||
tableSql = tableSql.toLowerCase().replaceAll(".`" + columnName + "` is", "." + columnName + " is");
|
||||
Matcher columnCommentMatcher = Pattern.compile("\\." + columnName + " is `").matcher(tableSql.toLowerCase());
|
||||
fieldComment = columnName;
|
||||
while (columnCommentMatcher.find()) {
|
||||
String columnCommentTmp = columnCommentMatcher.group();
|
||||
//System.out.println(columnCommentTmp);
|
||||
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim().get();
|
||||
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim();
|
||||
fieldComment = fieldComment.substring(0, fieldComment.indexOf("`")).trim();
|
||||
}
|
||||
} else if (columnLine.contains(" comment")) {
|
||||
} else if (columnLine.toLowerCase().contains(" comment")) {
|
||||
//20200518 zhengkai 修复包含comment关键字的问题
|
||||
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment") + 7).trim().get();
|
||||
String commentTmp = columnLine.toLowerCase().substring(columnLine.toLowerCase().lastIndexOf("comment") + 7).trim();
|
||||
// '用户ID',
|
||||
if (commentTmp.contains("`") || commentTmp.indexOf("`") != commentTmp.lastIndexOf("`")) {
|
||||
commentTmp = commentTmp.substring(commentTmp.indexOf("`") + 1, commentTmp.lastIndexOf("`"));
|
||||
@@ -356,6 +403,9 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
commentTmp = commentTmp.substring(0, commentTmp.lastIndexOf(")") + 1);
|
||||
}
|
||||
fieldComment = commentTmp;
|
||||
} else if (columnLine.contains("--")) {
|
||||
// 支持Oracle风格的注释(--)
|
||||
fieldComment = columnLine.substring(columnLine.indexOf("--") + 2).trim();
|
||||
} else {
|
||||
//修复comment不存在导致报错的问题
|
||||
fieldComment = columnName;
|
||||
@@ -374,10 +424,10 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldList.size() < 1) {
|
||||
throw new CodeGenerateException("表结构分析失败,请检查语句或者提交issue给我");
|
||||
if (fieldList.isEmpty()) {
|
||||
throw new Exception("表结构分析失败,请检查语句或者提交issue给我");
|
||||
}
|
||||
|
||||
//build Class Info
|
||||
ClassInfo codeJavaInfo = new ClassInfo();
|
||||
codeJavaInfo.setTableName(tableName);
|
||||
codeJavaInfo.setClassName(className);
|
||||
@@ -388,63 +438,7 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
return codeJavaInfo;
|
||||
}
|
||||
|
||||
private static boolean isNotSpecialColumnLine(NonCaseString columnLine, int lineSeq) {
|
||||
return (
|
||||
!columnLine.containsAny(
|
||||
"key ",
|
||||
"constraint",
|
||||
" using ",
|
||||
"unique ",
|
||||
"fulltext ",
|
||||
"index ",
|
||||
"pctincrease",
|
||||
"buffer_pool",
|
||||
"tablespace"
|
||||
)
|
||||
&& !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
|
||||
&& !(columnLine.contains("primary ") && lineSeq > 3)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析JSON生成类信息
|
||||
*
|
||||
* @param paramInfo
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ClassInfo processJsonToClassInfo(ParamInfo paramInfo) {
|
||||
ClassInfo codeJavaInfo = new ClassInfo();
|
||||
codeJavaInfo.setTableName("JsonDto");
|
||||
codeJavaInfo.setClassName("JsonDto");
|
||||
codeJavaInfo.setClassComment("JsonDto");
|
||||
|
||||
//support children json if forget to add '{' in front of json
|
||||
if (paramInfo.getTableSql().trim().startsWith("\"")) {
|
||||
paramInfo.setTableSql("{" + paramInfo.getTableSql());
|
||||
}
|
||||
if (JSON.isValid(paramInfo.getTableSql())) {
|
||||
if (paramInfo.getTableSql().trim().startsWith("{")) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(paramInfo.getTableSql().trim());
|
||||
//parse FieldList by JSONObject
|
||||
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonObject));
|
||||
} else if (paramInfo.getTableSql().trim().startsWith("[")) {
|
||||
JSONArray jsonArray = JSONArray.parseArray(paramInfo.getTableSql().trim());
|
||||
//parse FieldList by JSONObject
|
||||
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonArray.getJSONObject(0)));
|
||||
}
|
||||
}
|
||||
|
||||
return codeJavaInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse SQL by regex
|
||||
*
|
||||
* @param paramInfo
|
||||
* @return
|
||||
* @author https://github.com/ydq
|
||||
*/
|
||||
public ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo) {
|
||||
// field List
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
@@ -461,7 +455,7 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
|
||||
Pattern COL_PATTERN = Pattern.compile(COL_PATTERN_STR, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
Matcher matcher = DDL_PATTERN.matcher(paramInfo.getTableSql().trim());
|
||||
Matcher matcher = Pattern.compile(DDL_PATTEN_STR).matcher(paramInfo.getTableSql().trim());
|
||||
if (matcher.find()) {
|
||||
String tableName = matcher.group("tableName");
|
||||
String tableComment = matcher.group("tableComment");
|
||||
@@ -490,42 +484,7 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
return codeJavaInfo;
|
||||
}
|
||||
|
||||
public List<FieldInfo> processJsonObjectToFieldList(JSONObject jsonObject) {
|
||||
// field List
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
jsonObject.keySet().stream().forEach(jsonField -> {
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
fieldInfo.setFieldName(jsonField);
|
||||
fieldInfo.setColumnName(jsonField);
|
||||
fieldInfo.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo.setFieldComment("father:" + jsonField);
|
||||
fieldList.add(fieldInfo);
|
||||
if (jsonObject.get(jsonField) instanceof JSONArray) {
|
||||
jsonObject.getJSONArray(jsonField).stream().forEach(arrayObject -> {
|
||||
FieldInfo fieldInfo2 = new FieldInfo();
|
||||
fieldInfo2.setFieldName(arrayObject.toString());
|
||||
fieldInfo2.setColumnName(arrayObject.toString());
|
||||
fieldInfo2.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
|
||||
fieldList.add(fieldInfo2);
|
||||
});
|
||||
} else if (jsonObject.get(jsonField) instanceof JSONObject) {
|
||||
jsonObject.getJSONObject(jsonField).keySet().stream().forEach(arrayObject -> {
|
||||
FieldInfo fieldInfo2 = new FieldInfo();
|
||||
fieldInfo2.setFieldName(arrayObject.toString());
|
||||
fieldInfo2.setColumnName(arrayObject.toString());
|
||||
fieldInfo2.setFieldClass(String.class.getSimpleName());
|
||||
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
|
||||
fieldList.add(fieldInfo2);
|
||||
});
|
||||
}
|
||||
});
|
||||
if (fieldList.size() < 1) {
|
||||
throw new CodeGenerateException("JSON解析失败");
|
||||
}
|
||||
return fieldList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo) {
|
||||
// field List
|
||||
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
|
||||
@@ -558,12 +517,14 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
|
||||
List<String> valueList = new ArrayList<>();
|
||||
//add values as comment
|
||||
Arrays.stream(valueStr.split(",")).forEach(column -> {
|
||||
String[] values = valueStr.split(",");
|
||||
for (String column : values) {
|
||||
valueList.add(column);
|
||||
});
|
||||
}
|
||||
AtomicInteger n = new AtomicInteger(0);
|
||||
//add column to fleldList
|
||||
Arrays.stream(columnsSQL.replaceAll(" ", "").split(",")).forEach(column -> {
|
||||
String[] columns = columnsSQL.replaceAll(" ", "").split(",");
|
||||
for (String column : columns) {
|
||||
FieldInfo fieldInfo2 = new FieldInfo();
|
||||
fieldInfo2.setFieldName(column);
|
||||
fieldInfo2.setColumnName(column);
|
||||
@@ -573,14 +534,13 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||
}
|
||||
fieldList.add(fieldInfo2);
|
||||
n.getAndIncrement();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
if (fieldList.size() < 1) {
|
||||
throw new CodeGenerateException("INSERT SQL解析失败");
|
||||
throw new RuntimeException("INSERT SQL解析失败");
|
||||
}
|
||||
codeJavaInfo.setFieldList(fieldList);
|
||||
return codeJavaInfo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.softdev.system.generator.service.parser;
|
||||
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
|
||||
/**
|
||||
* JSON解析服务接口
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface JsonParserService {
|
||||
|
||||
/**
|
||||
* 解析JSON生成类信息
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
*/
|
||||
ClassInfo processJsonToClassInfo(ParamInfo paramInfo);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.softdev.system.generator.service.parser;
|
||||
|
||||
import com.softdev.system.generator.entity.dto.ClassInfo;
|
||||
import com.softdev.system.generator.entity.dto.ParamInfo;
|
||||
|
||||
/**
|
||||
* SQL解析服务接口
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public interface SqlParserService {
|
||||
|
||||
/**
|
||||
* 解析Select-SQL生成类信息(JSQLPraser版本)
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
ClassInfo generateSelectSqlBySQLPraser(ParamInfo paramInfo) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析Create-SQL生成类信息(JSQLPraser版本)
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
ClassInfo generateCreateSqlBySQLPraser(ParamInfo paramInfo) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析DDL-SQL生成类信息
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
ClassInfo processTableIntoClassInfo(ParamInfo paramInfo) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析DDL SQL生成类信息-正则表达式版本
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
*/
|
||||
ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo);
|
||||
|
||||
/**
|
||||
* 解析INSERT-SQL生成类信息-正则表达式版本
|
||||
*
|
||||
* @param paramInfo 参数信息
|
||||
* @return 类信息
|
||||
*/
|
||||
ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo);
|
||||
}
|
||||
@@ -22,7 +22,7 @@ public class MapUtil {
|
||||
public static Integer getInteger(Map map,String key){
|
||||
if(map!=null && map.containsKey(key)){
|
||||
try{
|
||||
return (Integer) map.get(key);
|
||||
return Integer.valueOf(map.get(key).toString());
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
@@ -34,7 +34,7 @@ public class MapUtil {
|
||||
public static Boolean getBoolean(Map map,String key){
|
||||
if(map!=null && map.containsKey(key)){
|
||||
try{
|
||||
return (Boolean) map.get(key);
|
||||
return Boolean.parseBoolean(map.get(key).toString()) || "true".equals(map.get(key).toString());
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.softdev.system.generator.util;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2018-05-02 21:10:28
|
||||
*/
|
||||
public class SqlException extends RuntimeException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 42L;
|
||||
|
||||
public SqlException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SqlException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public SqlException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
public SqlException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SqlException(String message, Throwable cause,
|
||||
boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.softdev.system.generator.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 文件名解析器
|
||||
* <p>
|
||||
* 解析模板配置中的 fileName 字段,支持 ${className}、${tableName}、${group}、${name} 占位符。
|
||||
* <p>
|
||||
* 解析规则:
|
||||
* <ul>
|
||||
* <li>若 fileName 中含 ${xxx} 占位符,则按占位符从 context 解析</li>
|
||||
* <li>若 fileName 为空,则根据 template.name + group 自动推断(兜底策略)</li>
|
||||
* <li>自动清理非法字符,确保可作为文件名</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public final class ZipFileNameResolver {
|
||||
|
||||
private static final Pattern PLACEHOLDER = Pattern.compile("\\$\\{([^}]+)\\}");
|
||||
|
||||
private static final Pattern INVALID_FILE_NAME_CHARS = Pattern.compile("[\\\\/:*?\"<>|\\r\\n\\t]");
|
||||
|
||||
private ZipFileNameResolver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文件名
|
||||
*
|
||||
* @param fileNameTemplate 模板配置中的 fileName(可为 null/空)
|
||||
* @param templateName 模板 name(如 controller / model / mapper)
|
||||
* @param group 模板 group(如 mybatis / jpa / ui)
|
||||
* @param context 占位符上下文(至少含 className、tableName)
|
||||
* @return 最终文件名(不含路径)
|
||||
*/
|
||||
public static String resolve(String fileNameTemplate,
|
||||
String templateName,
|
||||
String group,
|
||||
Map<String, Object> context) {
|
||||
String raw = (fileNameTemplate == null || fileNameTemplate.trim().isEmpty())
|
||||
? guessByConvention(templateName, group, context)
|
||||
: fileNameTemplate;
|
||||
|
||||
String resolved = replacePlaceholders(raw, context);
|
||||
return sanitize(resolved, templateName, group, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 兜底策略:根据模板名 + 分组推断文件名
|
||||
*/
|
||||
private static String guessByConvention(String templateName, String group, Map<String, Object> context) {
|
||||
String className = stringOf(context, "className");
|
||||
if (className == null || className.isEmpty()) {
|
||||
className = stringOf(context, "tableName");
|
||||
}
|
||||
if (className == null || className.isEmpty()) {
|
||||
className = "Generated";
|
||||
}
|
||||
String ext = guessExtension(templateName, group);
|
||||
if (ext == null || ext.isEmpty()) {
|
||||
return className + "-" + templateName;
|
||||
}
|
||||
return className + ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 推断文件后缀
|
||||
*/
|
||||
private static String guessExtension(String templateName, String group) {
|
||||
if (group != null) {
|
||||
switch (group.toLowerCase()) {
|
||||
case "ui":
|
||||
case "renren-fast":
|
||||
return "-" + templateName + ".html";
|
||||
case "bi":
|
||||
case "cloud":
|
||||
return "-" + templateName + ".txt";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (templateName == null) {
|
||||
return ".txt";
|
||||
}
|
||||
if (templateName.contains("xml") || templateName.endsWith("-xml")) {
|
||||
return ".xml";
|
||||
}
|
||||
if (templateName.contains("yml") || templateName.contains("yaml")) {
|
||||
return ".yml";
|
||||
}
|
||||
if (templateName.contains("sql")) {
|
||||
return ".sql";
|
||||
}
|
||||
if (templateName.contains("vue")) {
|
||||
return ".vue";
|
||||
}
|
||||
if (templateName.contains("json")) {
|
||||
return ".json";
|
||||
}
|
||||
if (templateName.contains("md")) {
|
||||
return ".md";
|
||||
}
|
||||
return ".java";
|
||||
}
|
||||
|
||||
private static String replacePlaceholders(String input, Map<String, Object> context) {
|
||||
if (input == null || !input.contains("${")) {
|
||||
return input;
|
||||
}
|
||||
Matcher matcher = PLACEHOLDER.matcher(input);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
String key = matcher.group(1);
|
||||
String value = stringOf(context, key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(value));
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理非法字符;如果清理后为空则使用兜底
|
||||
*/
|
||||
private static String sanitize(String fileName, String templateName, String group, Map<String, Object> context) {
|
||||
if (fileName == null) {
|
||||
return guessByConvention(templateName, group, context);
|
||||
}
|
||||
String cleaned = INVALID_FILE_NAME_CHARS.matcher(fileName).replaceAll("_").trim();
|
||||
if (cleaned.isEmpty() || ".".equals(cleaned) || "..".equals(cleaned)) {
|
||||
return guessByConvention(templateName, group, context);
|
||||
}
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
private static String stringOf(Map<String, Object> map, String key) {
|
||||
if (map == null || key == null) {
|
||||
return null;
|
||||
}
|
||||
Object v = map.get(key);
|
||||
return v == null ? null : v.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.softdev.system.generator.util.exception;
|
||||
|
||||
/**
|
||||
* 代码生成异常
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public class CodeGenException extends RuntimeException {
|
||||
|
||||
public CodeGenException() {
|
||||
}
|
||||
|
||||
public CodeGenException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CodeGenException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public CodeGenException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public CodeGenException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.softdev.system.generator.util.exception;
|
||||
|
||||
/**
|
||||
* SQL解析异常
|
||||
*
|
||||
* @author zhengkai.blog.csdn.net
|
||||
*/
|
||||
public class SqlParseException extends CodeGenException {
|
||||
|
||||
public SqlParseException() {
|
||||
}
|
||||
|
||||
public SqlParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SqlParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SqlParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SqlParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public final class mysqlJavaTypeUtil {
|
||||
//字符串
|
||||
mysqlJavaTypeMap.put("char","String");
|
||||
mysqlJavaTypeMap.put("varchar","String");
|
||||
mysqlJavaTypeMap.put("varchar2","String"); // Oracle类型
|
||||
mysqlJavaTypeMap.put("tinytext","String");
|
||||
mysqlJavaTypeMap.put("text","String");
|
||||
mysqlJavaTypeMap.put("mediumtext","String");
|
||||
@@ -35,6 +36,8 @@ public final class mysqlJavaTypeUtil {
|
||||
mysqlJavaTypeMap.put("date","Date");
|
||||
mysqlJavaTypeMap.put("datetime","Date");
|
||||
mysqlJavaTypeMap.put("timestamp","Date");
|
||||
// 数字类型 - Oracle增强
|
||||
mysqlJavaTypeMap.put("number","BigDecimal"); // Oracle的NUMBER类型默认映射为BigDecimal,支持精度
|
||||
|
||||
|
||||
mysqlSwaggerTypeMap.put("bigint","integer");
|
||||
@@ -46,7 +49,10 @@ public final class mysqlJavaTypeUtil {
|
||||
mysqlSwaggerTypeMap.put("boolean","boolean");
|
||||
mysqlSwaggerTypeMap.put("float","number");
|
||||
mysqlSwaggerTypeMap.put("double","number");
|
||||
mysqlSwaggerTypeMap.put("decimal","Double");
|
||||
mysqlSwaggerTypeMap.put("decimal","number");
|
||||
// Oracle类型
|
||||
mysqlSwaggerTypeMap.put("varchar2","string");
|
||||
mysqlSwaggerTypeMap.put("number","number");
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getMysqlJavaTypeMap() {
|
||||
@@ -49,15 +49,15 @@ spring:
|
||||
#mvc:
|
||||
# static-path-pattern: /statics/**
|
||||
OEM:
|
||||
version: 2025 March
|
||||
version: 2025 September
|
||||
header: SQL转Java JPA、MYBATIS实现类代码生成平台
|
||||
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
|
||||
title: JAVA在线代码生成
|
||||
slogan: Release your hands from tedious and repetitive CRUD tasks.
|
||||
description: <p>SpringBootCodeGenerator,又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——从繁琐重复的`CRUD工作`中释放你的双手,可通过DDL SQL语句或Select SQL语句或简单Json -> 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p>
|
||||
slogan: 👐 Free your hands from boring CRUD—let the code write itself! ⚡
|
||||
description: <p>💻 SpringBootCodeGenerator,又名 `大狼狗代码生成器`🐺🐶,支持 SQL 一键转 JAVA/JPA/Mybatis/MybatisPlus 等多种模板,轻松搞定 CRUD,彻底解放双手 ✋!只需提供 DDL、SELECT SQL 或简单 JSON 👉 即可生成 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper 等代码模板。</p><p>🔥🔥🔥 全新 JSqlParser 引擎上线,强力支持 DDL CREATE SQL与 SELECT SQL 解析!欢迎体验 & 反馈 💬!</p><p>👨💻 面向开发者的高效利器,已服务数万工程师,欢迎 Star ⭐、Fork 🍴、提 Issue 💬,一起打造更强大的代码生成平台!</p>
|
||||
author: BEJSON.com
|
||||
packageName: www.bejson.com
|
||||
copyright: Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a> , Might the holy light be with you !
|
||||
copyright: ✨ Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a>➕<a href="https://www.bejson.com/">BeJSON</a> — may the holy light guide your code, your coffee, and your commits! ⚡🧙♂️💻
|
||||
returnUtilSuccess: ResponseUtil.success
|
||||
returnUtilFailure: ResponseUtil.error
|
||||
outputStr: www.bejson.com
|
||||
@@ -47,16 +47,16 @@ spring:
|
||||
#mvc:
|
||||
# static-path-pattern: /statics/**
|
||||
OEM:
|
||||
version: 2025 March
|
||||
version: 2025 September
|
||||
header: SQL转Java JPA、MYBATIS实现类代码生成平台
|
||||
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
|
||||
title: JAVA代码生成平台
|
||||
slogan: Release your hands from tedious and repetitive CRUD tasks.
|
||||
description: <p>SpringBootCodeGenerator,又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——从繁琐重复的`CRUD工作`中释放你的双手,可通过DDL SQL语句或Select SQL语句或简单Json -> 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p>
|
||||
title: 大狼狗代码生成器
|
||||
slogan: 👐 Free your hands from boring CRUD—let the code write itself! ⚡
|
||||
description: <p>💻 SpringBootCodeGenerator,又名 `大狼狗代码生成器`🐺🐶,支持 SQL 一键转 JAVA/JPA/Mybatis/MybatisPlus 等多种模板,轻松搞定 CRUD,彻底解放双手 ✋!只需提供 DDL、SELECT SQL 或简单 JSON 👉 即可生成 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper 等代码模板。</p><p>🔥🔥🔥 全新 JSqlParser 引擎上线,强力支持 DDL CREATE SQL与 SELECT SQL 解析!欢迎体验 & 反馈 💬!</p><p>👨💻 面向开发者的高效利器,已服务数万工程师,欢迎 Star ⭐、Fork 🍴、提 Issue 💬,一起打造更强大的代码生成平台!</p>
|
||||
author: zhengkai.blog.csdn.net
|
||||
packageName: com.software.system
|
||||
copyright: Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a> , Might the holy light be with you !
|
||||
copyright: ✨ Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a> — may the holy light guide your code, your coffee, and your commits! ⚡🧙♂️💻
|
||||
returnUtilSuccess: ResponseUtil.success
|
||||
returnUtilFailure: ResponseUtil.error
|
||||
outputStr: http://zhengkai.blog.csdn.net
|
||||
mode: CDN
|
||||
mode: local
|
||||
64
src/main/resources/application-json.yml
Normal file
64
src/main/resources/application-json.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
server:
|
||||
port: 1235
|
||||
http2:
|
||||
enabled: true
|
||||
servlet:
|
||||
context-path: /generator
|
||||
#tomcat:
|
||||
# remote-ip-header: x-forward-for
|
||||
# uri-encoding: UTF-8
|
||||
# max-threads: 10
|
||||
# background-processor-delay: 30
|
||||
# basedir: ${user.home}/tomcat/
|
||||
undertow:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
|
||||
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
|
||||
io-threads: 4
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程
|
||||
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
|
||||
worker-threads: 64
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
|
||||
buffer-size: 1024
|
||||
# 是否分配的直接内存(NIO直接分配的堆外内存)
|
||||
direct-buffers: true
|
||||
spring:
|
||||
banner:
|
||||
charset: UTF-8
|
||||
web:
|
||||
encoding:
|
||||
force: true
|
||||
charset: UTF-8
|
||||
application:
|
||||
name: spring-boot-code-generator
|
||||
freemarker:
|
||||
request-context-attribute: request
|
||||
suffix: .html
|
||||
content-type: text/html
|
||||
enabled: true
|
||||
cache: false
|
||||
charset: UTF-8
|
||||
allow-request-override: false
|
||||
expose-request-attributes: true
|
||||
expose-session-attributes: true
|
||||
expose-spring-macro-helpers: true
|
||||
settings:
|
||||
number_format: 0.##
|
||||
default_encoding: UTF-8
|
||||
#template_loader: /templates/
|
||||
#mvc:
|
||||
# static-path-pattern: /statics/**
|
||||
OEM:
|
||||
version: 2025 September
|
||||
header: SQL转Java JPA、MYBATIS实现类代码生成平台
|
||||
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
|
||||
title: JAVA在线代码生成
|
||||
slogan: 👐 Free your hands from boring CRUD—let the code write itself! ⚡
|
||||
description: <p>💻 SpringBootCodeGenerator,又名 `大狼狗代码生成器`🐺🐶,支持 SQL 一键转 JAVA/JPA/Mybatis/MybatisPlus 等多种模板,轻松搞定 CRUD,彻底解放双手 ✋!只需提供 DDL、SELECT SQL 或简单 JSON 👉 即可生成 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper 等代码模板。</p><p>🔥🔥🔥 全新 JSqlParser 引擎上线,强力支持 DDL CREATE SQL与 SELECT SQL 解析!欢迎体验 & 反馈 💬!</p><p>👨💻 面向开发者的高效利器,已服务数万工程师,欢迎 Star ⭐、Fork 🍴、提 Issue 💬,一起打造更强大的代码生成平台!</p>
|
||||
author: https://www.json.cn/
|
||||
packageName: www.json.cn
|
||||
copyright: ✨ Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a>➕<a href="https://www.json.cn/">JSON</a> — may the holy light guide your code, your coffee, and your commits! ⚡🧙♂️💻
|
||||
returnUtilSuccess: ResponseUtil.success
|
||||
returnUtilFailure: ResponseUtil.error
|
||||
outputStr: www.json.cn
|
||||
mode: local
|
||||
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
@@ -123,18 +123,20 @@ const vm = new Vue({
|
||||
//get value from codemirror
|
||||
vm.formData.tableSql=$.inputArea.getValue();
|
||||
axios.post(basePath+"/code/generate",vm.formData).then(function(res){
|
||||
if(res.code===500){
|
||||
error("生成失败,请检查SQL语句!!!");
|
||||
if(res.status===500||res.data.code===500){
|
||||
console.log(res);
|
||||
error("生成失败,请检查SQL语句!!!"+res.data.msg);
|
||||
return;
|
||||
}
|
||||
setAllCookie();
|
||||
//console.log(res.outputJson);
|
||||
vm.outputJson = res.data.data;
|
||||
//兼容后端返回数据格式
|
||||
if(res.data){
|
||||
vm.outputJson = res.data.outputJson;
|
||||
}else {
|
||||
vm.outputJson = res.outputJson;
|
||||
}
|
||||
// if(res.data){
|
||||
// vm.outputJson = res.data.outputJson;
|
||||
// }else {
|
||||
// vm.outputJson = res.outputJson;
|
||||
// }
|
||||
|
||||
// console.log(vm.outputJson["bootstrap-ui"]);
|
||||
vm.outputStr=vm.outputJson[vm.currentSelect].trim();
|
||||
@@ -149,6 +151,54 @@ const vm = new Vue({
|
||||
},
|
||||
copy : function (){
|
||||
navigator.clipboard.writeText(vm.outputStr.trim()).then(r => {alert("已复制")});
|
||||
},
|
||||
//download all generated code as ZIP
|
||||
downloadZip : function (){
|
||||
//get value from codemirror
|
||||
vm.formData.tableSql=$.inputArea.getValue();
|
||||
if(!vm.formData.tableSql || vm.formData.tableSql.trim().length<5){
|
||||
error("请先输入 SQL/JSON/INSERT 语句");
|
||||
return;
|
||||
}
|
||||
// 用 axios 发起请求,responseType: 'blob' 让浏览器把响应当作二进制流处理
|
||||
axios.post(basePath+"/code/generate-zip", vm.formData, {responseType: 'blob', timeout: 60000})
|
||||
.then(function(res){
|
||||
if(res.status !== 200){
|
||||
error("下载失败,HTTP 状态码:"+res.status);
|
||||
return;
|
||||
}
|
||||
//尝试从 Content-Disposition 中解析文件名
|
||||
var dispo = res.headers && (res.headers['content-disposition'] || res.headers['Content-Disposition']);
|
||||
var fileName = "code-generator.zip";
|
||||
if(dispo){
|
||||
var matchStar = /filename\*=UTF-8''([^;]+)/i.exec(dispo);
|
||||
var matchQuoted = /filename="?([^";]+)"?/i.exec(dispo);
|
||||
if(matchStar && matchStar[1]){
|
||||
fileName = decodeURIComponent(matchStar[1]);
|
||||
}else if(matchQuoted && matchQuoted[1]){
|
||||
fileName = matchQuoted[1];
|
||||
}
|
||||
}
|
||||
// 创建 Blob 并触发浏览器下载
|
||||
var blob = new Blob([res.data], {type: 'application/zip'});
|
||||
if(window.navigator && window.navigator.msSaveBlob){
|
||||
window.navigator.msSaveBlob(blob, fileName);
|
||||
}else{
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
alert("已下载:"+fileName);
|
||||
})
|
||||
.catch(function(err){
|
||||
console.error(err);
|
||||
error("下载失败:"+(err && err.message ? err.message : '未知错误'));
|
||||
});
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
@@ -158,13 +208,15 @@ const vm = new Vue({
|
||||
}).then(function(res){
|
||||
//console.log(res.templates);
|
||||
// vm.templates = JSON.parse(res.templates);
|
||||
// console.log(res);
|
||||
console.log('origin res',res);
|
||||
vm.templates = res.data.data
|
||||
console.log('templates',vm.templates);
|
||||
//兼容后端返回数据格式
|
||||
if(res.data){
|
||||
vm.templates = res.data.templates;
|
||||
}else {
|
||||
vm.templates = res.templates;
|
||||
}
|
||||
// if(res.data){
|
||||
// vm.templates = res.data.templates;
|
||||
// }else {
|
||||
// vm.templates = res.templates;
|
||||
// }
|
||||
});
|
||||
},
|
||||
updated: function () {
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user