大家好,欢迎来到IT知识分享网。
一、在线地址 https://chat.tool4j.com
Java在线代码生成器:在线访问
二、页面截图
三、核心功能
- 支持Mybatis、MybatisPlus、Jpa代码生成
- 使用 antlr4 解析SQL语句,保证了SQL解析的成功率
- 支持自定义包名、作者名信息
- 支持自定义方法名、接口地址
- 支持自定义选择是否生成某个方法
- 支持选择是否集成Swagger、Lombok、validation等依赖
四、技术介绍
前端: React 16.8.6、Ant-design 4.24.12、Umi 3.5.41
后端: Java 1.8、SpringBoot2.3.4.RELEASE、knife4j(Swagger)2.0.9、Freemarker 2.3.31
五、源码
前端: tool4j-generator-ui
后台: tool4j-generator
部分代码节选:
/ * 代码生成入口类 * * @param params * @return */ public Map<String, Object> generate(JavaCodeConfig params) {
/* 生成代码 */ List<ParserResult> results = execute(params); Map<String, Object> map = new HashMap<>(); map.put("results", results); TreeVO root; root = new TreeVO().setKey(params.getBasePackage()).setTitle(params.getBasePackage()); String basePath = params.getBasePackage().replace(".", "/") + "/"; for (ParserResult parserResult : results) {
String[] dirArr = parserResult.getFileName().replace(basePath, "").split("/"); buildFileTree(root, dirArr, 0); } map.put("fileTree", root); if (CollUtil.isEmpty(results)) {
log.error("SQL解析失败,建议您切换SQL解析器重试,Input = {}", params.getInput()); throw new IllegalArgumentException("SQL解析失败,建议您切换SQL解析器重试"); } if (results.stream().anyMatch(ParserResult::isErrored)) {
List<ParserResult> errors = results.stream().filter(ParserResult::isErrored).collect(Collectors.toList()); log.info(">>>>>>>>>>>>>>> generate code exists error: total={}, error={},Input = {}", results.size(), errors.size(), params.getInput()); } else {
log.info(">>>>>>>>>>>>>>> generate code all succeed."); } return map; }
import React, {
Component } from 'react'; import {
Divider, Input, Modal, Radio, Spin, Switch, Tag } from 'antd'; import styles from './GenerateModal.less'; import MethodSetting from '@/pages/components/MethodSetting'; const ORM_TYPE = {
jpa: {
label: 'JPA', color: '#', }, mybatis: {
label: 'Mybatis', color: '#f6b305', }, mybatisPlus: {
label: 'MybatisPlus', color: '#008585', }, }; class GenerateModal extends Component {
constructor (props) {
super(props); this.state = {
init: false, parserType: 'common', basePackage: 'com.tool4j', author: 'system', apiPathPrefix: '/api', tableNamePrefix: '', restType: 'restful', ormType: 'mybatisPlus', methods: {
findPage: {
label: '分页查询', name: 'findPage', apiPath: '/findPage', enabled: true, }, findList: {
label: '列表查询', name: 'findList', apiPath: '/findList', enabled: true, }, findById: {
label: '查询详情', name: 'findById', apiPath: '/{id}', enabled: true, }, save: {
label: '新增', name: 'insert', apiPath: '', enabled: true, }, update: {
label: '修改', name: 'update', apiPath: '', enabled: true, }, delete: {
label: '删除', name: 'delete', apiPath: '/{id}', enabled: true, }, }, dependencies: ['lombok', 'swagger', 'validator'], }; } cancel = () => {
this.props.cancel(); }; generate = () => {
const {
parserType, basePackage, author, apiPathPrefix, tableNamePrefix, restType, ormType, methods, dependencies, } = this.state; const generateConfig = {
parserType, basePackage, author, apiPathPrefix, tableNamePrefix, restType, ormType, methods, dependencies, }; this.props.submit(generateConfig); }; dependencyChange = (key, checked) => {
let {
dependencies = [] } = this.state; if (checked) {
dependencies.push(key); } else {
dependencies = dependencies.filter(item => item !== key); } this.setState({
dependencies, }); }; formChange = (key, value) => {
this.setState({
[key]: value, }); }; init = () => {
const setting = this.props.setting; if (setting) {
const {
methods } = this.state; if (setting.methods) {
for (let key in methods) {
methods[key] = {
...methods[key], ...setting.methods[key] }; } } this.setState({
...setting, methods, init: true, }); } }; render () {
const {
init, dependencies = [], ormType } = this.state; if (!init) {
this.init(); } let {
templates = [] } = this.props; if (ormType) {
templates = templates.filter(item => item.ormType === ormType); } const templateOptions = []; templates.forEach(template => templateOptions.push({
value: template.ormType, label: <div> <Tag style={
{
marginLeft: '5px' }} color={
ORM_TYPE[template.ormType].color}> {
ORM_TYPE[template.ormType].label} </Tag> </div>, })); return <Modal title={
<div style={
{
display: 'flex', justifyContent: 'space-between', alignItems: 'center', height: '14px', marginRight: '40px', }}> <div> <span>代码生成配置</span> </div> </div> } bodyStyle={
{
padding: '5px' }} open={
this.props.visible} maskClosable={
false} onOk={
this.generate} okText={
'生成'} onCancel={
this.cancel} cancelText={
'取消'} width={
'800px'} > <Spin spinning={
this.props.loading} tip={
'代码生成中,请稍候...'}> <div className={
styles['module']}> <div style={
{
marginBottom: '10px' }}> <Divider type='vertical' className={
styles['divider']} > </Divider> <span style={
{
fontSize: '16px', fontWeight: 600 }}>选择解析器</span> </div> <div style={
{
marginLeft: '20px', display: 'flex' }}> <Radio.Group value={
this.state.parserType} onChange={
e => this.formChange('parserType', e.target.value)}> <Radio.Button value='common'>智能SQL解析器</Radio.Button> <Radio.Button value='mysql'>MySQL 解析器</Radio.Button> <Radio.Button value='postgresql'>Postgresql 解析器</Radio.Button> <Radio.Button value='plsql'>Oracle 解析器</Radio.Button> </Radio.Group> </div> </div> <div className={
styles['module']}> <div style={
{
marginBottom: '10px' }}> <Divider type='vertical' className={
styles['divider']} > </Divider> <span style={
{
fontSize: '16px', fontWeight: 600 }}>基础配置</span> </div> <div style={
{
marginLeft: '20px' }}> <Input placeholder={
'统一包名,如:com.tool4j'} addonBefore={
<div style={
{
width: '100px' }}>包名:</div>} style={
{
marginTop: '5px', width: '60%' }} onChange={
e => this.formChange('basePackage', e.target.value)} value={
this.state.basePackage} /> <Input placeholder={
'作者姓名,如:system'} addonBefore={
<div style={
{
width: '100px' }}>作者:</div>} style={
{
marginTop: '5px', width: '60%' }} onChange={
e => this.formChange('author', e.target.value)} value={
this.state.author} /> <Input placeholder={
'统一的接口前缀,如:/api'} addonBefore={
<div style={
{
width: '100px' }}>接口前缀:</div>} style={
{
marginTop: '5px', width: '60%' }} onChange={
e => this.formChange('apiPathPrefix', e.target.value)} value={
this.state.apiPathPrefix} /> <Input placeholder={
'生成代码时可忽略表的统一前缀,如:t_'} addonBefore={
<div style={
{
width: '100px' }}>忽略表前缀:</div>} style={
{
marginTop: '5px', width: '60%' }} onChange={
e => this.formChange('tableNamePrefix', e.target.value)} value={
this.state.tableNamePrefix} /> </div> </div> <div className={
styles['module']}> <div style={
{
marginBottom: '10px' }}> <Divider type='vertical' className={
styles['divider']} > </Divider> <span style={
{
fontSize: '16px', fontWeight: 600 }}>方法配置</span> </div> <div style={
{
width: '100%' }}> <MethodSetting methods={
this.state.methods} formChange={
this.formChange} /> </div> </div> <div className={
styles['module']}> <div style={
{
marginBottom: '10px' }}> <Divider type='vertical' className={
styles['divider']} > </Divider> <span style={
{
fontSize: '16px', fontWeight: 600 }}>更多选项</span> </div> <div> <div style={
{
margin: '20px', display: 'flex', textAlign: 'left' }}> <div style={
{
width: '120px', fontSize: '15px', fontWeight: 600 }}>ORM框架:</div> <Radio.Group onChange={
e => this.formChange('ormType', e.target.value)} value={
this.state.ormType}> <Radio value={
'mybatisPlus'}>MybatisPlus</Radio> <Radio value={
'mybatis'}>Mybatis</Radio> <Radio value={
'jpa'}>SpringData(JPA)</Radio> </Radio.Group> </div> </div> </div> <div className={
styles['module']}> <div> <div style={
{
marginBottom: '10px' }}> <Divider type='vertical' className={
styles['divider']} > </Divider> <span style={
{
fontSize: '16px', fontWeight: 600 }}>集成依赖</span> </div> <div style={
{
width: '100%', padding: '20px 40px', display: 'flex', justifyContent: 'space-between' }}> <div style={
{
textAlign: 'center' }}> <div style={
{
height: '60px' }}> <img src={
'/icon/swagger.svg'} width={
180} style={
{
margin: '0 5px 5px 5px' }} /> </div> <Switch style={
{
width: '60px', marginTop: '10px' }} checkedChildren='使用' unCheckedChildren='移除' checked={
dependencies.filter(item => item === 'swagger').length > 0} onChange={
checked => this.dependencyChange('swagger', checked)} > </Switch> </div> <div style={
{
textAlign: 'center' }}> <div style={
{
height: '60px', fontSize: '40px', fontFamily: 'Georgia', }}> Lombok </div> <Switch style={
{
width: '60px', marginTop: '10px' }} checkedChildren='使用' unCheckedChildren='移除' checked={
dependencies.filter(item => item === 'lombok').length > 0} onChange={
checked => this.dependencyChange('lombok', checked)} > </Switch> </div> <div style={
{
textAlign: 'center' }}> <div style={
{
width: '100%', height: '60px', display: 'flex', flexDirection: 'column', justifyContent: 'center', }}> <div style={
{
height: '60px', fontSize: '40px', fontFamily: 'Georgia', }}> Validation 校验 </div> </div> <Switch style={
{
width: '60px', marginTop: '10px' }} checkedChildren='使用' unCheckedChildren='移除' checked={
dependencies.filter(item => item === 'validator').length > 0} onChange={
checked => this.dependencyChange('validator', checked)} > </Switch> </div> </div> </div> </div> </Spin> </Modal>; } } export default GenerateModal;
六、本地运行
可直接 clone 该项目到本地,无需修改任何内容即可运行
后端:
- 使用Maven安装依赖
- 运行 Tool4jGeneratorApplication.java
前端:
3. 切换到前端工程根目录
4. 安装依赖: npm i
5. 运行:umi dev
七、结束语
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/128020.html