├── README.MD ├── thtf-generator-ui ├── .babelrc ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── README.md ├── build │ ├── build.js │ ├── check-versions.js │ ├── logo.png │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ └── prod.env.js ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.vue │ ├── assets │ │ ├── languages │ │ │ ├── en_us.json │ │ │ └── zh_cn.json │ │ ├── logo.png │ │ └── user.png │ ├── components │ │ ├── BreadCrumb │ │ │ └── index.vue │ │ ├── FaIconTooltip │ │ │ └── index.vue │ │ ├── Hamburger │ │ │ └── index.vue │ │ ├── LangSelector │ │ │ └── index.vue │ │ ├── MenuTree │ │ │ └── index.vue │ │ ├── PopupTreeInput │ │ │ └── index.vue │ │ ├── SelectTableDiaog │ │ │ └── index.vue │ │ └── ThemePicker │ │ │ └── index.vue │ ├── http │ │ ├── axios.js │ │ ├── config.js │ │ ├── index.js │ │ └── interface.js │ ├── i18n │ │ └── index.js │ ├── main.js │ ├── mock │ │ └── index.js │ ├── router │ │ └── index.js │ ├── store │ │ ├── index.js │ │ └── modules │ │ │ └── app.js │ ├── utils │ │ ├── auth.js │ │ ├── datetime.js │ │ ├── iframe.js │ │ └── validate.js │ └── views │ │ ├── Datasource │ │ └── DatasourceDialog.vue │ │ ├── Error │ │ └── 404.vue │ │ ├── Generate │ │ ├── MasterTable.vue │ │ └── SingleTable.vue │ │ ├── HeadBar │ │ └── HeadBar.vue │ │ ├── Home.vue │ │ ├── Intro │ │ └── Intro.vue │ │ ├── Login.vue │ │ ├── MainContent │ │ └── MainContent.vue │ │ └── NavBar │ │ └── NavBar.vue └── static │ └── .gitkeep └── thtf-generator ├── .gitignore ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── thtf │ │ └── generator │ │ ├── ThtfGeneratorApplication.java │ │ ├── common │ │ ├── constants │ │ │ ├── CommonConstants.java │ │ │ └── DBMSConstants.java │ │ ├── exception │ │ │ ├── CustomException.java │ │ │ ├── DAOException.java │ │ │ ├── QueryDAOException.java │ │ │ └── handler │ │ │ │ └── GlobalExceptionHandler.java │ │ ├── response │ │ │ ├── QueryResult.java │ │ │ ├── Result.java │ │ │ └── ResultCode.java │ │ └── valid │ │ │ ├── EnumValue.java │ │ │ ├── EnumValueValidator.java │ │ │ ├── IP.java │ │ │ └── Phone.java │ │ ├── config │ │ ├── CorsConfig.java │ │ ├── MyBeetlConfig.java │ │ ├── MybatisConfig.java │ │ ├── SwaggerConfig.java │ │ └── WebMvcConfig.java │ │ ├── controller │ │ └── GenerateController.java │ │ ├── converter │ │ ├── CommonMetaDataConverter.java │ │ ├── MySQL5MetaDataConverter.java │ │ └── OracleMetaDataConverter.java │ │ ├── dao │ │ ├── DatabaseDAOFactory.java │ │ ├── IDatabaseDAO.java │ │ ├── IMetaDataConverter.java │ │ ├── impl │ │ │ ├── AbstractDatabasetDAOImpl.java │ │ │ ├── CommonDatabaseDAOImpl.java │ │ │ └── MySql5DatabaseDAO.java │ │ └── sql │ │ │ ├── DatabaseType.java │ │ │ ├── MSSQL.xml │ │ │ ├── MySQL5.xml │ │ │ └── Oracle.xml │ │ ├── model │ │ ├── Column.java │ │ ├── ForeignKey.java │ │ ├── Index.java │ │ ├── PrimaryKey.java │ │ ├── Procedure.java │ │ ├── Table.java │ │ └── Trigger.java │ │ ├── service │ │ ├── DatabaseService.java │ │ ├── GenerateService.java │ │ └── impl │ │ │ ├── DatabaseServiceImpl.java │ │ │ └── GenerateServiceImpl.java │ │ ├── utils │ │ ├── DataTypeUtils.java │ │ ├── Dom4jUtils.java │ │ ├── IOUtils.java │ │ ├── ReflectionUtils.java │ │ ├── SnowflakeId.java │ │ └── StringUtils.java │ │ └── vo │ │ ├── ColumnModel.java │ │ ├── ConnParam.java │ │ ├── GenerateModel.java │ │ ├── RequestParam.java │ │ └── TableModel.java └── resources │ ├── application.yml │ ├── banner.txt │ └── templates │ ├── commonVO.btl │ ├── controller.btl │ ├── listVO.btl │ ├── mapper.btl │ ├── model.btl │ ├── queryConditionVO.btl │ ├── saveOrUpdateVO.btl │ ├── service.btl │ ├── serviceImpl.btl │ ├── sqlMap.btl │ └── view.btl └── test └── java └── com └── thtf └── generator └── ThtfGeneratorApplicationTests.java /thtf-generator-ui/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /thtf-generator-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /thtf-generator-ui/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /thtf-generator-ui/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /thtf-generator-ui/README.md: -------------------------------------------------------------------------------- 1 | # kitty-generator-ui 2 | 3 | > kitty generator ui project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | ``` 20 | 21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 22 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/build/logo.png -------------------------------------------------------------------------------- /thtf-generator-ui/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader', 51 | publicPath: '../../' 52 | }) 53 | } else { 54 | return ['vue-style-loader'].concat(loaders) 55 | } 56 | } 57 | 58 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 59 | return { 60 | css: generateLoaders(), 61 | postcss: generateLoaders(), 62 | less: generateLoaders('less'), 63 | sass: generateLoaders('sass', { indentedSyntax: true }), 64 | scss: generateLoaders('sass'), 65 | stylus: generateLoaders('stylus'), 66 | styl: generateLoaders('stylus') 67 | } 68 | } 69 | 70 | // Generate loaders for standalone style files (outside of .vue) 71 | exports.styleLoaders = function (options) { 72 | const output = [] 73 | const loaders = exports.cssLoaders(options) 74 | 75 | for (const extension in loaders) { 76 | const loader = loaders[extension] 77 | output.push({ 78 | test: new RegExp('\\.' + extension + '$'), 79 | use: loader 80 | }) 81 | } 82 | 83 | return output 84 | } 85 | 86 | exports.createNotifierCallback = () => { 87 | const notifier = require('node-notifier') 88 | 89 | return (severity, errors) => { 90 | if (severity !== 'error') return 91 | 92 | const error = errors[0] 93 | const filename = error.file && error.file.split('!').pop() 94 | 95 | notifier.notify({ 96 | title: packageConfig.name, 97 | message: severity + ': ' + error.name, 98 | subtitle: filename || '', 99 | icon: path.join(__dirname, 'logo.png') 100 | }) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader', 37 | options: vueLoaderConfig 38 | }, 39 | { 40 | test: /\.js$/, 41 | loader: 'babel-loader', 42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 43 | }, 44 | { 45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 46 | loader: 'url-loader', 47 | options: { 48 | limit: 10000, 49 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 50 | } 51 | }, 52 | { 53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 54 | loader: 'url-loader', 55 | options: { 56 | limit: 10000, 57 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 58 | } 59 | }, 60 | { 61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 62 | loader: 'url-loader', 63 | options: { 64 | limit: 10000, 65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 66 | } 67 | }, 68 | { 69 | test: /\.scss$/, 70 | loaders: ['style', 'css', 'sass'] 71 | } 72 | ] 73 | }, 74 | node: { 75 | // prevent webpack from injecting useless setImmediate polyfill because Vue 76 | // source contains it (although only uses it if it's native). 77 | setImmediate: false, 78 | // prevent webpack from injecting mocks to Node native modules 79 | // that does not make sense for the client 80 | dgram: 'empty', 81 | fs: 'empty', 82 | net: 'empty', 83 | tls: 'empty', 84 | child_process: 'empty' 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /thtf-generator-ui/build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 13 | 14 | const env = require('../config/prod.env') 15 | 16 | const webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.build.productionSourceMap, 20 | extract: true, 21 | usePostCSS: true 22 | }) 23 | }, 24 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 25 | output: { 26 | path: config.build.assetsRoot, 27 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 29 | }, 30 | plugins: [ 31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 32 | new webpack.DefinePlugin({ 33 | 'process.env': env 34 | }), 35 | new UglifyJsPlugin({ 36 | uglifyOptions: { 37 | compress: { 38 | warnings: false 39 | } 40 | }, 41 | sourceMap: config.build.productionSourceMap, 42 | parallel: true 43 | }), 44 | // extract css into its own file 45 | new ExtractTextPlugin({ 46 | filename: utils.assetsPath('css/[name].[contenthash].css'), 47 | // Setting the following option to `false` will not extract CSS from codesplit chunks. 48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 51 | allChunks: true, 52 | }), 53 | // Compress extracted CSS. We are using this plugin so that possible 54 | // duplicated CSS from different components can be deduped. 55 | new OptimizeCSSPlugin({ 56 | cssProcessorOptions: config.build.productionSourceMap 57 | ? { safe: true, map: { inline: false } } 58 | : { safe: true } 59 | }), 60 | // generate dist index.html with correct asset hash for caching. 61 | // you can customize output by editing /index.html 62 | // see https://github.com/ampedandwired/html-webpack-plugin 63 | new HtmlWebpackPlugin({ 64 | filename: config.build.index, 65 | template: 'index.html', 66 | inject: true, 67 | minify: { 68 | removeComments: true, 69 | collapseWhitespace: true, 70 | removeAttributeQuotes: true 71 | // more options: 72 | // https://github.com/kangax/html-minifier#options-quick-reference 73 | }, 74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 75 | chunksSortMode: 'dependency' 76 | }), 77 | // keep module.id stable when vendor modules does not change 78 | new webpack.HashedModuleIdsPlugin(), 79 | // enable scope hoisting 80 | new webpack.optimize.ModuleConcatenationPlugin(), 81 | // split vendor js into its own file 82 | new webpack.optimize.CommonsChunkPlugin({ 83 | name: 'vendor', 84 | minChunks (module) { 85 | // any required modules inside node_modules are extracted to vendor 86 | return ( 87 | module.resource && 88 | /\.js$/.test(module.resource) && 89 | module.resource.indexOf( 90 | path.join(__dirname, '../node_modules') 91 | ) === 0 92 | ) 93 | } 94 | }), 95 | // extract webpack runtime and module manifest to its own file in order to 96 | // prevent vendor hash from being updated whenever app bundle is updated 97 | new webpack.optimize.CommonsChunkPlugin({ 98 | name: 'manifest', 99 | minChunks: Infinity 100 | }), 101 | // This instance extracts shared chunks from code splitted chunks and bundles them 102 | // in a separate chunk, similar to the vendor chunk 103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 104 | new webpack.optimize.CommonsChunkPlugin({ 105 | name: 'app', 106 | async: 'vendor-async', 107 | children: true, 108 | minChunks: 3 109 | }), 110 | 111 | // copy custom static assets 112 | new CopyWebpackPlugin([ 113 | { 114 | from: path.resolve(__dirname, '../static'), 115 | to: config.build.assetsSubDirectory, 116 | ignore: ['.*'] 117 | } 118 | ]) 119 | ] 120 | }) 121 | 122 | if (config.build.productionGzip) { 123 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 124 | 125 | webpackConfig.plugins.push( 126 | new CompressionWebpackPlugin({ 127 | asset: '[path].gz[query]', 128 | algorithm: 'gzip', 129 | test: new RegExp( 130 | '\\.(' + 131 | config.build.productionGzipExtensions.join('|') + 132 | ')$' 133 | ), 134 | threshold: 10240, 135 | minRatio: 0.8 136 | }) 137 | ) 138 | } 139 | 140 | if (config.build.bundleAnalyzerReport) { 141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 143 | } 144 | 145 | module.exports = webpackConfig 146 | -------------------------------------------------------------------------------- /thtf-generator-ui/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /thtf-generator-ui/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8888, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: './', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /thtf-generator-ui/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /thtf-generator-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | kitty-generator-ui 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /thtf-generator-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kitty-generator-ui", 3 | "version": "1.0.0", 4 | "description": "kitty generator ui project", 5 | "author": "Louis", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.18.1", 14 | "element-ui": "^2.12.0", 15 | "font-awesome": "^4.7.0", 16 | "js-cookie": "^2.2.1", 17 | "vue": "^2.5.2", 18 | "vue-i18n": "^8.14.1", 19 | "vue-router": "^3.0.1", 20 | "vuex": "^3.1.1" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^7.1.2", 24 | "babel-core": "^6.22.1", 25 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 26 | "babel-loader": "^7.1.1", 27 | "babel-plugin-syntax-jsx": "^6.18.0", 28 | "babel-plugin-transform-runtime": "^6.22.0", 29 | "babel-plugin-transform-vue-jsx": "^3.5.0", 30 | "babel-preset-env": "^1.3.2", 31 | "babel-preset-stage-2": "^6.22.0", 32 | "chalk": "^2.0.1", 33 | "copy-webpack-plugin": "^4.0.1", 34 | "css-loader": "^0.28.11", 35 | "extract-text-webpack-plugin": "^3.0.0", 36 | "file-loader": "^1.1.4", 37 | "friendly-errors-webpack-plugin": "^1.6.1", 38 | "html-webpack-plugin": "^2.30.1", 39 | "mockjs": "^1.0.1-beta3", 40 | "node-notifier": "^5.1.2", 41 | "node-sass": "^4.12.0", 42 | "optimize-css-assets-webpack-plugin": "^3.2.0", 43 | "ora": "^1.2.0", 44 | "portfinder": "^1.0.13", 45 | "postcss-import": "^11.0.0", 46 | "postcss-loader": "^2.0.8", 47 | "postcss-url": "^7.2.1", 48 | "rimraf": "^2.6.0", 49 | "sass-loader": "^7.3.1", 50 | "semver": "^5.3.0", 51 | "shelljs": "^0.7.6", 52 | "uglifyjs-webpack-plugin": "^1.1.1", 53 | "url-loader": "^0.5.8", 54 | "vue-loader": "^13.3.0", 55 | "vue-style-loader": "^3.0.1", 56 | "vue-template-compiler": "^2.5.2", 57 | "webpack": "^3.6.0", 58 | "webpack-bundle-analyzer": "^2.9.0", 59 | "webpack-dev-server": "^2.9.1", 60 | "webpack-merge": "^4.1.0" 61 | }, 62 | "engines": { 63 | "node": ">= 6.0.0", 64 | "npm": ">= 3.0.0" 65 | }, 66 | "browserslist": [ 67 | "> 1%", 68 | "last 2 versions", 69 | "not ie <= 8" 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 27 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/assets/languages/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "common": { 3 | "home": "Home", 4 | "login": "Login", 5 | "logout": "Logout", 6 | "doc": "Document", 7 | "blog": "Blog", 8 | "projectRepo": "Project", 9 | "myMsg": "My Message", 10 | "config": "Config", 11 | "backup": "Backup", 12 | "restore": "Restore", 13 | "datasource": "Datasource", 14 | "versionName": "Version", 15 | "exit": "Exit" 16 | }, 17 | "action": { 18 | "operation": "Operation", 19 | "add": "Add", 20 | "edit": "Edit", 21 | "delete": "Delete", 22 | "batchDelete": "Batch Delete", 23 | "search": "Search", 24 | "loading": "loading", 25 | "submit": "Submit", 26 | "save": "Save", 27 | "test": "test", 28 | "comfirm": "Comfirm", 29 | "cancel": "Cancel", 30 | "reset": "Reset" 31 | }, 32 | "navMenu": { 33 | "singleTable": "single table", 34 | "masterTable": "master table", 35 | "userMng": "User Manage", 36 | "deptMng": "Dept Manage", 37 | "roleMng": "Role Manage", 38 | "menuMng": "Menu Manage", 39 | "logMng": "Log Manage", 40 | "sysMonitor": "System Monitor" 41 | } 42 | } -------------------------------------------------------------------------------- /thtf-generator-ui/src/assets/languages/zh_cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "common": { 3 | "home": "首页", 4 | "login": "登录", 5 | "logout": "退出", 6 | "doc": "文档", 7 | "blog": "博客", 8 | "projectRepo": "项目", 9 | "myMsg": "我的消息", 10 | "config": "系统配置", 11 | "backup": "备份", 12 | "restore": "还原", 13 | "datasource": "数据源 ", 14 | "versionName": "版本名称", 15 | "exit": "退出" 16 | }, 17 | "action": { 18 | "operation": "操作", 19 | "add": "新增", 20 | "edit": "编辑", 21 | "delete": "删除", 22 | "batchDelete": "批量删除", 23 | "search": "查询", 24 | "loading": "拼命加载中", 25 | "submit": "提交", 26 | "save": "保存", 27 | "test": "测试", 28 | "comfirm": "确定", 29 | "cancel": "取消", 30 | "reset": "重置" 31 | 32 | }, 33 | "navMenu": { 34 | "singleTable": "单表查询", 35 | "masterTable": "主从表格", 36 | "userMng": "User Manage", 37 | "deptMng": "Dept Manage", 38 | "roleMng": "Role Manage", 39 | "menuMng": "Menu Manage", 40 | "logMng": "Log Manage", 41 | "sysMonitor": "System Monitor" 42 | } 43 | } -------------------------------------------------------------------------------- /thtf-generator-ui/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/src/assets/logo.png -------------------------------------------------------------------------------- /thtf-generator-ui/src/assets/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/src/assets/user.png -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/BreadCrumb/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/FaIconTooltip/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 29 | 30 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 28 | 29 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/LangSelector/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/MenuTree/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 39 | 40 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/PopupTreeInput/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 58 | 59 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/SelectTableDiaog/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 64 | 65 | 68 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/components/ThemePicker/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 162 | 163 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/http/axios.js: -------------------------------------------------------------------------------- 1 | // 二次封装 axios 模块,包含拦截器等信息。 2 | import axios from 'axios' 3 | import config from './config' 4 | import qs from 'qs' 5 | import router from '@/router' 6 | import { getToken } from '../utils/auth' 7 | 8 | 9 | // 创建axios实例 axiso的一些基础参数配置, 10 | const instance = axios.create({ 11 | baseURL: config.baseURL, 12 | headers: config.headers, 13 | // `transformResponse` 在传递给 then/catch 前,允许修改响应数据 14 | // transformResponse: [function (data) { 15 | // // 对 data 进行任意转换处理 16 | // 17 | // }] 18 | }) 19 | 20 | const tokenKey = config.tokenKey 21 | // request拦截器 22 | instance.interceptors.request.use( 23 | config => { 24 | // 打开loading 25 | // store.commit('CONTROL_LOADING', true) 26 | // if (store.getters.token) { 27 | // config.headers[tokenKey] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改 28 | // } 29 | 30 | return config 31 | }, 32 | 33 | // 请求错误时一般http状态码为两种以4开头,401:超时、404:not found 没找到接口 34 | error => { 35 | console.log('request error:' + error); 36 | // 在调用的那边可以拿到(catch)你想返回的错误信息 37 | return Promise.reject(error) 38 | } 39 | ) 40 | 41 | // 响应拦截器 42 | instance.interceptors.response.use( 43 | 44 | // 如果返回的状态码为200, 45 | res => { 46 | // 请求成功是要做的处理 47 | 48 | // 对响应数据做些事情,把loading 动画关掉 49 | // store.commit('CONTROL_LOADING', false) 50 | 51 | // 对请求成功的值做统一判断 52 | // 1. 判空 53 | if (res.data === '' || res.data.length === 0 || res.data === 'undefined' || res.data === undefined) { 54 | console.log('后台传来的data为空/为undefined') 55 | } 56 | 57 | // 2.错误提示(前提是接口跑通了,只是对里边某些值做下详细判断。要先跟后台商定好,对某个固定的字段进行判断,并且确定固定字段来承接 错误信息,方便展示) 58 | if (res.data.code && res.data.code !== 200) { 59 | console.log(res.data) 60 | } 61 | 62 | return res.data; 63 | }, 64 | // 请求错误时做些事(接口错误、超时等) 65 | error => { 66 | 67 | // 关闭loading 68 | // store.commit('CONTROL_LOADING',false) 69 | console.log(error) // 打开控制台,可以看到error包含了几个对象:message, config, code, request, response,可以拿来请求超时等问题 70 | 71 | // 1. 判断请求超时 72 | if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) { 73 | console.log('根据你设置的timeout/真的请求超时 判断请求现在超时了,你可以在这里加入超时的处理方案') 74 | // return service.request(originalRequest);//例如再重复请求一次 75 | } 76 | 77 | // 2. 需要重定向到错误页面 78 | if (error && error.response) { 79 | switch (error.response.status) { 80 | case 400: error.message = '请求错误(400)'; break; 81 | case 401: error.message = '未授权,请重新登录(401)'; break; 82 | case 403: error.message = '拒绝访问(403)'; break; 83 | case 404: router.push('/404'); break; 84 | case 408: error.message = '请求超时(408)'; break; 85 | case 500: error.message = '服务器错误(500)'; break; 86 | case 501: error.message = '服务未实现(501)'; break; 87 | case 502: error.message = '网络错误(502)'; break; 88 | case 503: error.message = '服务不可用(503)'; break; 89 | case 504: error.message = '网络超时(504)'; break; 90 | case 505: error.message = 'HTTP版本不受支持(505)'; break; 91 | default: error.message = `连接出错(${err.response.status})!`; 92 | } 93 | } else { 94 | error.message = '连接服务器失败!' 95 | } 96 | 97 | return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息 98 | } 99 | ) 100 | 101 | export default instance 102 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/http/config.js: -------------------------------------------------------------------------------- 1 | // axios 默认配置,包含基础路径等信息。 2 | 3 | export default { 4 | method: 'get', 5 | // 基础url前缀 6 | baseURL: 'http://localhost:8899/thtf-generator/v1', 7 | // token 8 | tokenKey: 'Authorization', 9 | // token超时时间 10 | tokenCookieExpires: 2 * 60 * 1000, 11 | // 请求头信息 12 | headers: { 13 | 'Content-Type': 'application/json;charset=UTF-8' 14 | }, 15 | // 参数 16 | data: {}, 17 | // 设置超时时间,单位毫秒 18 | timeout: 10000, 19 | // 携带凭证: axios默认是请求的时候不会带上cookie的,需要通过设置 withCredentials:true来解决 20 | withCredentials: true, 21 | // 返回数据类型 22 | responseType: 'json' 23 | } 24 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/http/index.js: -------------------------------------------------------------------------------- 1 | // 将 axios 封装成插件,按插件方式引入 2 | 3 | import apis from './interface' 4 | 5 | const install = Vue => { 6 | if (install.installed) { 7 | return; 8 | } 9 | 10 | install.installed = true; 11 | 12 | Object.defineProperties(Vue.prototype, { 13 | // 注意,此处挂载在 Vue 原型的 $api 对象上 14 | $api: { 15 | get() { 16 | return apis; 17 | } 18 | } 19 | }) 20 | } 21 | 22 | export default install -------------------------------------------------------------------------------- /thtf-generator-ui/src/http/interface.js: -------------------------------------------------------------------------------- 1 | // 请求接口汇总模块,聚合模块 API。 2 | import axios from './axios' 3 | 4 | export const login = () => { 5 | return axios({ 6 | url: '/login', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | export const getUser = () => { 12 | return axios({ 13 | url:'/user', 14 | method: 'get' 15 | }) 16 | } 17 | 18 | export const testConnection = (params) => { 19 | return axios({ 20 | url:'/testConnection', 21 | method: 'post', 22 | data: params 23 | }) 24 | } 25 | 26 | export const getGenerateModel = (params) => { 27 | return axios({ 28 | url:'/getGenerateModel', 29 | method: 'post', 30 | data: params 31 | }) 32 | } 33 | 34 | export const getTables = (params) => { 35 | return axios({ 36 | url:'/getTables', 37 | method: 'post', 38 | data: params 39 | }) 40 | } 41 | 42 | export const generateModels = (params) => { 43 | return axios({ 44 | url:'/generateModels', 45 | method: 'post', 46 | data: params 47 | }) 48 | } 49 | 50 | 51 | export default { 52 | login, 53 | getUser, 54 | testConnection, 55 | getGenerateModel, 56 | getTables, 57 | generateModels, 58 | } 59 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/i18n/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueI18n from 'vue-i18n' 3 | 4 | Vue.use(VueI18n) 5 | 6 | // 注册i18n实例并引入语言文件,文件格式等下解析 7 | const i18n = new VueI18n({ 8 | locale: 'zh_cn', 9 | messages: { 10 | 'zh_cn': require('@/assets/languages/zh_cn.json'), 11 | 'en_us': require('@/assets/languages/en_us.json') 12 | } 13 | }) 14 | 15 | export default i18n -------------------------------------------------------------------------------- /thtf-generator-ui/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import router from './router' 4 | import store from './store' 5 | import i18n from './i18n' 6 | import ElementUI from 'element-ui' 7 | import 'element-ui/lib/theme-chalk/index.css' 8 | import 'font-awesome/css/font-awesome.min.css' 9 | import api from './http/index' 10 | 11 | 12 | Vue.use(ElementUI) 13 | Vue.use(api) 14 | 15 | Vue.config.productionTip = false 16 | 17 | new Vue({ 18 | el: '#app', 19 | i18n, 20 | router, 21 | store, 22 | render: h => h(App) 23 | }); 24 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs' 2 | 3 | // Mock.mock('http://localhost:9000/getTables', { 4 | // "code": 200, 5 | // "msg": null, 6 | // "data": { 7 | // "connParam": { 8 | // "dbName": "kitty", 9 | // "dbType": "MYSQL", 10 | // "host": "localhost", 11 | // "password": "123456", 12 | // "port": 3306, 13 | // "userName": "root" 14 | // }, 15 | // "tableModels": [ 16 | // { 17 | // "name": "sys_menu", 18 | // "description": "菜单管理", 19 | // "tablespace": null, 20 | // "columns": [] 21 | // }, 22 | // { 23 | // "name": "sys_user", 24 | // "description": "用户", 25 | // "tablespace": null, 26 | // "columns": [] 27 | // } 28 | // ] 29 | // } 30 | // }) -------------------------------------------------------------------------------- /thtf-generator-ui/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | 6 | export default new Router({ 7 | routes: [ 8 | ,{ 9 | path: '/', 10 | name: '首页', 11 | component: () => import('@/views/Home'), 12 | }, 13 | { 14 | path: '/', 15 | name: '首页', 16 | component: () => import('@/views/Home'), 17 | children: [ 18 | { 19 | path: 'intro', name: '系统介绍', component: () => import('@/views/Intro/Intro') 20 | }, 21 | { 22 | path: 'single', 23 | name: '单表查询', 24 | component: () => import('@/views/Generate/SingleTable'), 25 | }, 26 | { 27 | path: 'master', 28 | name: '主从表格', 29 | component: () => import('@/views/Generate/MasterTable') 30 | } 31 | ] 32 | } 33 | ,{ 34 | path: '/404', 35 | name: 'notFound', 36 | component: () => import('@/views/Error/404') 37 | }, 38 | ,{ 39 | path: '/login', 40 | name: 'login', 41 | component: () => import('@/views/Login') 42 | } 43 | ] 44 | }) 45 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import vuex from 'vuex' 3 | 4 | Vue.use(vuex); 5 | 6 | import app from './modules/app' 7 | 8 | const store = new vuex.Store({ 9 | modules: { 10 | app: app 11 | } 12 | }) 13 | 14 | export default store -------------------------------------------------------------------------------- /thtf-generator-ui/src/store/modules/app.js: -------------------------------------------------------------------------------- 1 | export default { 2 | state: { 3 | appName: "THTF Generator", // 应用名称 4 | themeColor: "#14889A", // 主题颜色 5 | oldThemeColor: "#14889A", // 上一次主题颜色 6 | collapse:false, // 导航栏收缩状态 7 | menuRouteLoaded:false // 菜单和路由是否已经加载 8 | }, 9 | getters: { 10 | collapse(state){// 对应着上面state 11 | return state.collapse 12 | } 13 | }, 14 | mutations: { 15 | onCollapse(state){ // 改变收缩状态 16 | state.collapse = !state.collapse 17 | }, 18 | setThemeColor(state, themeColor){ // 改变主题颜色 19 | state.oldThemeColor = state.themeColor 20 | state.themeColor = themeColor 21 | }, 22 | menuRouteLoaded(state, menuRouteLoaded){ // 改变菜单和路由的加载状态 23 | state.menuRouteLoaded = menuRouteLoaded; 24 | } 25 | }, 26 | actions: { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/utils/auth.js: -------------------------------------------------------------------------------- 1 | import cookies from 'js-cookie' 2 | import config from '../http/config' 3 | 4 | const tokenKey = config.tokenKey 5 | 6 | export const getToken = () => { 7 | return cookies.get(tokenKey) 8 | } 9 | 10 | export const setToken = (token, rememberMe) => { 11 | if (rememberMe) { 12 | return cookies.set(TokenKey, token, { expires: config.tokenCookieExpires }) 13 | } else { 14 | return cookies.set(TokenKey, token) 15 | } 16 | } 17 | 18 | export const removeToken = () => { 19 | return cookies.remove(TokenKey) 20 | } 21 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/utils/datetime.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 时间日期相关操作 3 | */ 4 | 5 | 6 | /** 7 | * 时间格式化 8 | * 将 2018-09-23T11:54:16.000+0000 格式化成 2018/09/23 11:54:16 9 | * @param datetime 国际化日期格式 10 | */ 11 | export function format (datetime) { 12 | return formatWithSeperator(datetime, "/", ":"); 13 | } 14 | 15 | /** 16 | * 时间格式化 17 | * 将 2018-09-23T11:54:16.000+0000 格式化成类似 2018/09/23 11:54:16 18 | * 可以指定日期和时间分隔符 19 | * @param datetime 国际化日期格式 20 | */ 21 | export function formatWithSeperator (datetime, dateSeprator, timeSeprator) { 22 | if (datetime != null) { 23 | const dateMat = new Date(datetime); 24 | const year = dateMat.getFullYear(); 25 | const month = dateMat.getMonth() + 1; 26 | const day = dateMat.getDate(); 27 | const hh = dateMat.getHours(); 28 | const mm = dateMat.getMinutes(); 29 | const ss = dateMat.getSeconds(); 30 | const timeFormat = year + dateSeprator + month + dateSeprator + day + " " + hh + timeSeprator + mm + timeSeprator + ss; 31 | return timeFormat; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/utils/iframe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 嵌套页面IFrame模块 3 | */ 4 | 5 | import config from '@/http/config' 6 | 7 | /** 8 | * 嵌套页面URL地址 9 | * @param {*} url 10 | */ 11 | export function getIFramePath (url) { 12 | let iframeUrl = '' 13 | if(/^iframe:.*/.test(url)) { 14 | iframeUrl = url.replace('iframe:', '') 15 | } else if(/^http[s]?:\/\/.*/.test(url)) { 16 | iframeUrl = url.replace('http://', '') 17 | if(iframeUrl.indexOf(":") != -1) { 18 | iframeUrl = iframeUrl.substring(iframeUrl.lastIndexOf(":") + 1) 19 | } 20 | } 21 | return iframeUrl 22 | } 23 | 24 | /** 25 | * 嵌套页面路由路径 26 | * @param {*} url 27 | */ 28 | export function getIFrameUrl (url) { 29 | let iframeUrl = '' 30 | if(/^iframe:.*/.test(url)) { 31 | iframeUrl = config.baseUrl + url.replace('iframe:', '') 32 | } else if(/^http[s]?:\/\/.*/.test(url)) { 33 | iframeUrl = url 34 | } 35 | return iframeUrl 36 | } 37 | 38 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/utils/validate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 邮箱 3 | * @param {*} s 4 | */ 5 | export function isEmail (s) { 6 | return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) 7 | } 8 | 9 | /** 10 | * 手机号码 11 | * @param {*} s 12 | */ 13 | export function isMobile (s) { 14 | return /^1[0-9]{10}$/.test(s) 15 | } 16 | 17 | /** 18 | * 电话号码 19 | * @param {*} s 20 | */ 21 | export function isPhone (s) { 22 | return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s) 23 | } 24 | 25 | /** 26 | * URL地址 27 | * @param {*} s 28 | */ 29 | export function isURL (s) { 30 | return /^http[s]?:\/\/.*/.test(s) 31 | } 32 | 33 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Datasource/DatasourceDialog.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 104 | 105 | 108 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Error/404.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 19 | 20 | 63 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Generate/MasterTable.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/HeadBar/HeadBar.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 103 | 104 | 162 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 24 | 25 | 35 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Intro/Intro.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | 19 | 50 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 57 | 58 | 89 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/MainContent/MainContent.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 45 | -------------------------------------------------------------------------------- /thtf-generator-ui/src/views/NavBar/NavBar.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | 52 | 91 | -------------------------------------------------------------------------------- /thtf-generator-ui/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyygithub/pyy/807f79fe62b93b694be7ff3fa1cc6b2631d84c98/thtf-generator-ui/static/.gitkeep -------------------------------------------------------------------------------- /thtf-generator/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /thtf-generator/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.8.RELEASE 9 | 10 | 11 | com.thtf.generator 12 | springboot-code-generator 13 | 0.0.1-SNAPSHOT 14 | springboot-code-generator 15 | 代码自动生成 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 1.8 21 | 1.2.5 22 | 2.8.0 23 | 11.1.0.6.0 24 | 2.0.2 25 | 1.3.2 26 | 1.2.58 27 | 1.1.68.RELEASE 28 | 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-web 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | 44 | mysql 45 | mysql-connector-java 46 | 47 | 48 | 49 | com.oracle.jdbc 50 | ojdbc6 51 | ${oracle.version} 52 | 53 | 54 | 55 | dom4j 56 | dom4j 57 | 58 | 59 | 60 | org.projectlombok 61 | lombok 62 | true 63 | 64 | 65 | 66 | com.github.pagehelper 67 | pagehelper-spring-boot-starter 68 | ${pagehelper.spring.version} 69 | 70 | 71 | 72 | io.springfox 73 | springfox-swagger2 74 | ${swagger.version} 75 | 76 | 77 | io.springfox 78 | springfox-swagger-ui 79 | ${swagger.version} 80 | 81 | 82 | 83 | tk.mybatis 84 | mapper-spring-boot-starter 85 | ${tk.mybatis.version} 86 | 87 | 88 | 89 | org.mybatis.spring.boot 90 | mybatis-spring-boot-starter 91 | ${mybatis.spring.version} 92 | 93 | 94 | 95 | com.alibaba 96 | fastjson 97 | ${fastjson.version} 98 | 99 | 100 | 101 | com.ibeetl 102 | beetl-framework-starter 103 | ${beetl.version} 104 | 105 | 106 | 107 | org.apache.commons 108 | commons-lang3 109 | 110 | 111 | 112 | dom4j 113 | dom4j 114 | 115 | 116 | 117 | 118 | 119 | 120 | src/main/java 121 | 122 | **/sql*/*.xml 123 | 124 | false 125 | 126 | 127 | src/main/resources 128 | 129 | **/* 130 | 131 | false 132 | 133 | 134 | 135 | 136 | org.springframework.boot 137 | spring-boot-maven-plugin 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/ThtfGeneratorApplication.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ThtfGeneratorApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ThtfGeneratorApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/constants/CommonConstants.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.constants; 2 | 3 | /** 4 | * ======================== 5 | * 公共常量 6 | * Author:pyy 7 | * Date:2019-9-25 16:04:13 8 | * Version: v1.0 9 | * ======================== 10 | */ 11 | public interface CommonConstants { 12 | 13 | // 编码 14 | String ENCODING_UTF8 = "utf-8"; 15 | String ENCODING_GBK = "gbk"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/constants/DBMSConstants.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.constants; 2 | 3 | 4 | /** 5 | * ======================== 6 | * DBMS常量 7 | * Author:pyy 8 | * Date:2019-9-25 16:04:13 9 | * Version: v1.0 10 | * ======================== 11 | */ 12 | public interface DBMSConstants { 13 | 14 | /** DB TYPE, ORACLE */ 15 | public static final String ORACLE = "ORACLE"; 16 | /** DB TYPE, MySQL */ 17 | public static final String MYSQL = "MYSQL"; 18 | /** DB TYPE, DB2 */ 19 | public static final String DB2 = "DB2"; 20 | /** DB TYPE, SQL SERVER */ 21 | public static final String SQL_SERVER = "SQL SERVER"; 22 | /** DB TYPE, SQL SERVER */ 23 | public static final String SQLSERVER = "SQLSERVER"; 24 | /** DB TYPE, SYBASE */ 25 | public static final String SYBASE = "SYBASE"; 26 | /** DB TYPE, PostgreSQL */ 27 | public static final String POSTGRE_SQL = "POSTGRE_SQL"; 28 | /** DB TYPE, HSQLDB */ 29 | public static final String HSQLDB = "HSQLDB"; 30 | /** DB TYPE, Firebird */ 31 | public static final String FIREBIRD = "FIREBIRD"; 32 | /** DB TYPE, Derby */ 33 | public static final String DERBY = "DERBY"; 34 | 35 | /** DBMS Configurations */ 36 | public static final String ELEMENT_DMBS_CONFIGURATIONS = "dbmsConfigurations"; 37 | /** DBMS dbms */ 38 | public static final String ELEMENT_DBMS = "dbms"; 39 | /** DBMS key */ 40 | public static final String ATTRIBUTE_KEY = "key"; 41 | /** DBMS value */ 42 | public static final String ATTRIBUTE_VALUE = "value"; 43 | /** DBMS host */ 44 | public static final String ATTRIBUTE_HOST = "host"; 45 | /** DBMS port */ 46 | public static final String ATTRIBUTE_PORT = "port"; 47 | /** database */ 48 | public static final String ATTRIBUTE_DB = "database"; 49 | /** DBMS userName */ 50 | public static final String ATTRIBUTE_USER = "userName"; 51 | /** DBMS password */ 52 | public static final String ATTRIBUTE_PASSWORD = "password"; 53 | /** DBMS desc */ 54 | public static final String ATTRIBUTE_DESE = "desc"; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/exception/CustomException.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.exception; 2 | 3 | 4 | 5 | import com.thtf.generator.common.response.ResultCode; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import java.text.MessageFormat; 10 | 11 | /** 12 | * 自定义异常类型 13 | * @author pyy 14 | */ 15 | @Setter 16 | @Getter 17 | public class CustomException extends RuntimeException { 18 | 19 | //错误代码 20 | private ResultCode resultCode; 21 | 22 | private int code; 23 | 24 | private String message; 25 | 26 | public CustomException(ResultCode resultCode){ 27 | super(resultCode.message()); 28 | this.resultCode = resultCode; 29 | } 30 | 31 | public CustomException(ResultCode resultCode, Object... args){ 32 | code = resultCode.code(); 33 | message = MessageFormat.format(resultCode.message(), args); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/exception/DAOException.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.exception; 2 | 3 | /** 4 | * DAO操作异常 5 | * @author pyy 6 | */ 7 | public class DAOException extends Exception { 8 | 9 | private static final long serialVersionUID = -1041464715086167865L; 10 | 11 | public static final int OPEN_CONNECTION_EXCEPTION = 1; 12 | public static final int CLOSE_CONNECTION_EXCEPTION = 2; 13 | public static final int CLOSE_JDBC_EXCEPTION = 3; 14 | public static final int QUERY_EXCEPTION = 8; 15 | public static final int QUERY_TABLE_EXCEPTION = 9; 16 | public static final int QUERY_COLUMN_EXCEPTION = 10; 17 | public static final int QUERY_PRIMARY_KEY_EXCEPTION = 11; 18 | public static final int QUERY_FOREIGN_KEY_EXCEPTION = 12; 19 | public static final int QUERY_INDEX_EXCEPTION = 13; 20 | public static final int QUERY_TRIGGER_EXCEPTION = 14; 21 | 22 | private final int type; 23 | 24 | public DAOException(int type, String message, Throwable cause) { 25 | super(message, cause); 26 | this.type = type; 27 | } 28 | 29 | /** 30 | * @return the type 31 | */ 32 | public int getType() { 33 | return type; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | String errorMsg = null; 39 | switch (type) { 40 | case OPEN_CONNECTION_EXCEPTION: 41 | errorMsg = "创建数据库连接失败:"; 42 | break; 43 | case CLOSE_CONNECTION_EXCEPTION: 44 | errorMsg = "关闭数据库连接失败:"; 45 | break; 46 | case CLOSE_JDBC_EXCEPTION: 47 | errorMsg = "关闭jdbc资源出错:"; 48 | break; 49 | default: 50 | errorMsg = "查询出错:"; 51 | } 52 | return errorMsg + getMessage(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/exception/QueryDAOException.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.exception; 2 | 3 | /** 4 | * DAO查询操作异常 5 | * @author pyy 6 | */ 7 | public class QueryDAOException extends DAOException { 8 | 9 | /** 10 | * 11 | */ 12 | private static final long serialVersionUID = 970988278493482388L; 13 | 14 | private final String tableName; 15 | 16 | /** 17 | * @param type 18 | * @param message 19 | * @param cause 20 | */ 21 | public QueryDAOException(String tableName, int type, String message, 22 | Throwable cause) { 23 | super(type, message, cause); 24 | this.tableName = tableName; 25 | } 26 | 27 | /** 28 | * @return the tableName 29 | */ 30 | public String getTableName() { 31 | return tableName; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | String typeStr = getTypeString(); 37 | if (typeStr != null) { 38 | return String.format("表【%s】查询%s信息出错,出错原因是:%s。", tableName, typeStr, getMessage()); 39 | } 40 | 41 | return super.toString(); 42 | } 43 | 44 | private String getTypeString() { 45 | switch (getType()) { 46 | case QUERY_COLUMN_EXCEPTION: 47 | return "字段"; 48 | case QUERY_PRIMARY_KEY_EXCEPTION: 49 | return "主键"; 50 | case QUERY_FOREIGN_KEY_EXCEPTION: 51 | return "外键"; 52 | case QUERY_INDEX_EXCEPTION: 53 | return "索引"; 54 | case QUERY_TRIGGER_EXCEPTION: 55 | return "触发器"; 56 | default: 57 | return null; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/exception/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.exception.handler; 2 | 3 | import com.thtf.generator.common.exception.CustomException; 4 | import com.thtf.generator.common.response.Result; 5 | import com.thtf.generator.common.response.ResultCode; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.validation.BindException; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.validation.FieldError; 12 | import org.springframework.validation.ObjectError; 13 | import org.springframework.web.bind.MethodArgumentNotValidException; 14 | import org.springframework.web.bind.annotation.ExceptionHandler; 15 | import org.springframework.web.bind.annotation.RestControllerAdvice; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 全局异常处理器 21 | * @author pyy 22 | */ 23 | @RestControllerAdvice 24 | public class GlobalExceptionHandler { 25 | 26 | private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); 27 | 28 | /** 29 | * 处理自定义异常 30 | */ 31 | @ExceptionHandler(CustomException.class) 32 | public Result handleException(CustomException e) { 33 | 34 | if (e.getResultCode() != null) { 35 | log.error("### 异常信息:code={}, msg={} ###", e.getResultCode().code(), e.getResultCode().message()); 36 | return new Result(e.getResultCode()); 37 | } else { 38 | log.error("### 异常信息:code={}, msg={} ###", e.getCode(), e.getMessage()); 39 | return new Result(e.getCode(), e.getMessage()); 40 | } 41 | } 42 | 43 | /** 44 | * 参数错误异常 45 | */ 46 | @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class}) 47 | public Result handleException(Exception e) { 48 | StringBuffer errorMsg = new StringBuffer(); 49 | if (e instanceof MethodArgumentNotValidException) { 50 | MethodArgumentNotValidException validException = (MethodArgumentNotValidException) e; 51 | BindingResult result = validException.getBindingResult(); 52 | if (result.hasErrors()) { 53 | List errors = result.getAllErrors(); 54 | errors.forEach(p ->{ 55 | FieldError fieldError = (FieldError) p; 56 | errorMsg.append(fieldError.getDefaultMessage()).append(","); 57 | log.error("### 请求参数错误:{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+ "},errorMessage{"+fieldError.getDefaultMessage()+"} ###"); }); 58 | } 59 | } else if (e instanceof BindException) { 60 | BindException bindException = (BindException)e; 61 | if (bindException.hasErrors()) { 62 | log.error("### 请求参数错误: {} ###", bindException.getAllErrors()); 63 | } 64 | } 65 | 66 | return new Result(ResultCode.PARAM_IS_INVALID.code(), StringUtils.removeEnd(errorMsg.toString(), ",")); 67 | } 68 | 69 | /** 70 | * 处理所有不可知的异常 71 | */ 72 | @ExceptionHandler(Exception.class) 73 | public Result handleOtherException(Exception e){ 74 | //打印异常堆栈信息 75 | e.printStackTrace(); 76 | // 打印异常信息 77 | log.error("### 不可知的异常 e=:{} ###", e.getMessage()); 78 | return new Result(ResultCode.SYSTEM_INNER_ERROR); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/response/QueryResult.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.response; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * ======================== 13 | * 查询结果 14 | * Author:pyy 15 | * Date:2019/6/6 16 | * Time:10:10 17 | * Version: v1.0 18 | * ======================== 19 | */ 20 | @Data 21 | @ApiModel(value = "QueryResult",description = "分页结果") 22 | public class QueryResult { 23 | 24 | @ApiModelProperty("数据列表") 25 | private List list; 26 | 27 | @ApiModelProperty("数据总数") 28 | private long total; 29 | 30 | public QueryResult(List list, long total) { 31 | this.list = list; 32 | this.total = total; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/response/Result.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.response; 2 | 3 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 4 | import lombok.Data; 5 | 6 | /** 7 | * ======================== 8 | * 统一响应结果集 9 | * Author:pyy 10 | * Date:2019/6/6 11 | * Time:10:10 12 | * Version: v1.0 13 | * ======================== 14 | */ 15 | @Data 16 | @JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL) 17 | public class Result { 18 | 19 | //操作代码 20 | int code; 21 | 22 | //提示信息 23 | String msg; 24 | 25 | //结果数据 26 | T data; 27 | 28 | public Result(ResultCode resultCode){ 29 | this.code = resultCode.code(); 30 | this.msg = resultCode.message(); 31 | } 32 | 33 | public Result(int code, String msg){ 34 | this.code = code; 35 | this.msg = msg; 36 | } 37 | 38 | public Result(ResultCode resultCode, T data){ 39 | this.code = resultCode.code(); 40 | this.msg = resultCode.message(); 41 | this.data = data; 42 | } 43 | 44 | public static Result SUCCESS(){ 45 | return new Result(ResultCode.SUCCESS); 46 | } 47 | 48 | public static Result SUCCESS(T data){ 49 | return new Result(ResultCode.SUCCESS, data); 50 | } 51 | 52 | public static Result FAIL(){ 53 | return new Result(ResultCode.FAIL); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/response/ResultCode.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.response; 2 | 3 | 4 | /** 5 | * ======================== 6 | * 通用响应状态 7 | * Author:pyy 8 | * Date:2019/6/6 9 | * Time:10:10 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | public enum ResultCode { 14 | 15 | /* 成功状态码 */ 16 | SUCCESS(200,"SUCCESS"), 17 | 18 | /* 错误状态码 */ 19 | FAIL(500,"ERROR"), 20 | 21 | /* 参数错误:10001-19999 */ 22 | PARAM_IS_INVALID(10001, "参数无效"), 23 | CONNECTION_ERROR(10002, "连接失败,请检查数据库及连接"), 24 | 25 | /* 用户错误:20001-29999*/ 26 | USER_NOT_LOGGED_IN(20001, "用户未登录"), 27 | USER_LOGIN_ERROR(20002, "账号不存在或密码错误"), 28 | USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"), 29 | USER_NOT_EXIST(20004, "用户不存在"), 30 | USER_HAS_EXISTED(20005, "用户已存在"), 31 | 32 | /* 业务错误:30001-39999 */ 33 | //BUSINESS_GROUP_NO_ALLOWED_DEL(30001, "应用分组已经被 {0} 个应用【{1}{2}】使用,不能删除"), 34 | NAME_EXISTED(30001, "{0}名称已存在"), 35 | CODE_EXISTED(30002, "{0}编码已存在"), 36 | BUSINESS_OUTER_DATASOURCE_NO_ALLOWED_DEL(30002, "数据源已经被 {0} 个资源【{1}{2}】使用,不能删除"), 37 | RESOURCE_CATEGORY_EXIST_DEPEND(30003, "当前分类下存在 {0} 个子分类【{1}{2}】,不能删除"), 38 | 39 | 40 | /* 系统错误:40001-49999 */ 41 | SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"), 42 | UPLOAD_ERROR(40002, "系统异常,上传文件失败"), 43 | 44 | /* 数据错误:50001-599999 */ 45 | RESULT_DATA_NONE(50001, "数据未找到"), 46 | DATA_IS_WRONG(50002, "数据有误"), 47 | DATA_ALREADY_EXISTED(50003, "数据已存在"), 48 | 49 | /* 接口错误:60001-69999 */ 50 | INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"), 51 | INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"), 52 | INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"), 53 | INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"), 54 | INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"), 55 | INTERFACE_EXCEED_LOAD(60006, "接口负载过高"), 56 | 57 | 58 | /* 权限错误 */ 59 | PERMISSION_UNAUTHENTICATED(70001,"此操作需要登陆系统!"), 60 | PERMISSION_UNAUTHORISE(70002,"权限不足,无权操作!"), 61 | PERMISSION_EXPIRE(401,"登录状态过期!"), 62 | PERMISSION_LIMIT(70004, "访问次数受限制"); 63 | 64 | //操作代码 65 | int code; 66 | //提示信息 67 | String message; 68 | ResultCode(int code, String message){ 69 | this.code = code; 70 | this.message = message; 71 | } 72 | 73 | public int code() { 74 | return code; 75 | } 76 | 77 | public String message() { 78 | return message; 79 | } 80 | 81 | public void setCode(int code) { 82 | this.code = code; 83 | } 84 | 85 | public void setMessage(String message) { 86 | this.message = message; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/valid/EnumValue.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.valid; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | import static java.lang.annotation.ElementType.*; 10 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 11 | 12 | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) 13 | @Retention(RUNTIME) 14 | @Documented 15 | @Constraint(validatedBy = {EnumValueValidator.class}) 16 | public @interface EnumValue { 17 | 18 | // 默认错误消息 19 | String message() default "必须为指定值"; 20 | 21 | String[] strValues() default {}; 22 | 23 | int[] intValues() default {}; 24 | 25 | //分组 26 | Class[] groups() default {}; 27 | 28 | //负载 29 | Class[] payload() default {}; 30 | 31 | //指定多个时使用 32 | @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE}) 33 | @Retention(RUNTIME) 34 | @Documented 35 | @interface List { 36 | EnumValue[] value(); 37 | } 38 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/valid/EnumValueValidator.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.valid; 2 | 3 | import javax.validation.ConstraintValidator; 4 | import javax.validation.ConstraintValidatorContext; 5 | 6 | /** 7 | * ======================== 8 | * 自定义验证 9 | * Author:pyy 10 | * Date:2019/9/24 17:34 11 | * Version: v1.0 12 | * ======================== 13 | */ 14 | public class EnumValueValidator implements ConstraintValidator< EnumValue, Object> { 15 | private String[] strValues; 16 | private int[] intValues; 17 | 18 | @Override 19 | public void initialize(EnumValue constraintAnnotation) { 20 | strValues = constraintAnnotation.strValues(); 21 | intValues = constraintAnnotation.intValues(); 22 | } 23 | 24 | @Override 25 | public boolean isValid(Object value, ConstraintValidatorContext context ) { 26 | if(value instanceof String) { 27 | for (String s:strValues) { 28 | if(s.equals(value)){ 29 | return true; 30 | } 31 | } 32 | }else if(value instanceof Integer){ 33 | for (Integer s:intValues) { 34 | if(s==value){ 35 | return true; 36 | } 37 | } 38 | } 39 | return false; 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/valid/IP.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.valid; 2 | 3 | import org.hibernate.validator.constraints.CompositionType; 4 | import org.hibernate.validator.constraints.ConstraintComposition; 5 | 6 | import javax.validation.Constraint; 7 | import javax.validation.Payload; 8 | import javax.validation.ReportAsSingleViolation; 9 | import javax.validation.constraints.Null; 10 | import javax.validation.constraints.Pattern; 11 | import java.lang.annotation.Documented; 12 | import java.lang.annotation.Retention; 13 | import java.lang.annotation.Target; 14 | 15 | import static java.lang.annotation.ElementType.*; 16 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 17 | 18 | 19 | /** 20 | * 验证IP 21 | */ 22 | @ConstraintComposition(CompositionType.OR) 23 | @Pattern(regexp = "^(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).)(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).){2}([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))$") 24 | @Null 25 | @Documented 26 | @Constraint(validatedBy = {}) 27 | @Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER }) 28 | @Retention(RUNTIME) 29 | @ReportAsSingleViolation 30 | public @interface IP { 31 | String message() default "IP地址格式错误"; 32 | 33 | Class[] groups() default {}; 34 | 35 | Class[] payload() default {}; 36 | } 37 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/common/valid/Phone.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.common.valid; 2 | 3 | import org.hibernate.validator.constraints.CompositionType; 4 | import org.hibernate.validator.constraints.ConstraintComposition; 5 | import org.hibernate.validator.constraints.Length; 6 | 7 | import javax.validation.Constraint; 8 | import javax.validation.Payload; 9 | import javax.validation.ReportAsSingleViolation; 10 | import javax.validation.constraints.Null; 11 | import javax.validation.constraints.Pattern; 12 | import java.lang.annotation.Documented; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.Target; 15 | 16 | import static java.lang.annotation.ElementType.*; 17 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 18 | 19 | /** 20 | * 验证手机号,空和正确的手机号都能验证通过
21 | * 正确的手机号由11位数字组成,第一位为1 22 | * 第二位为 3、4、5、7、8 23 | * 24 | */ 25 | @ConstraintComposition(CompositionType.OR) 26 | @Pattern(regexp = "1[3|4|5|7|8][0-9]\\d{8}") 27 | @Null 28 | @Length(max = 11) 29 | @Documented 30 | @Constraint(validatedBy = {}) 31 | @Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER }) 32 | @Retention(RUNTIME) 33 | @ReportAsSingleViolation 34 | public @interface Phone { 35 | String message() default "手机号校验错误"; 36 | 37 | Class[] groups() default {}; 38 | 39 | Class[] payload() default {}; 40 | } 41 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * ======================== 9 | * 跨域配置 10 | * Author:pyy 11 | * Date:2019-9-25 16:45:06 12 | * Version: v1.0 13 | * ======================== 14 | */ 15 | @Configuration 16 | public class CorsConfig implements WebMvcConfigurer { 17 | 18 | @Override 19 | public void addCorsMappings(CorsRegistry registry) { 20 | registry.addMapping("/**") // 允许跨域访问的路径 21 | .allowedOrigins("*") // 允许跨域访问的源 22 | .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许请求方法 23 | .maxAge(168000) // 预检间隔时间 24 | .allowedHeaders("*") // 允许头部设置 25 | .allowCredentials(true); // 是否发送cookie 26 | } 27 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/config/MyBeetlConfig.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.config; 2 | 3 | import com.ibeetl.starter.BeetlTemplateCustomize; 4 | import org.beetl.core.GroupTemplate; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * ======================== 10 | * MyBeetl配置 11 | * Author:pyy 12 | * Date:2019-9-25 16:45:06 13 | * Version: v1.0 14 | * ======================== 15 | */ 16 | @Configuration 17 | public class MyBeetlConfig { 18 | 19 | @Bean 20 | public BeetlTemplateCustomize beetlTemplateCustomize(){ 21 | return new BeetlTemplateCustomize(){ 22 | public void customize(GroupTemplate groupTemplate){ 23 | 24 | } 25 | }; 26 | } 27 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/config/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.config; 2 | 3 | import org.apache.ibatis.session.SqlSessionFactory; 4 | import org.mybatis.spring.SqlSessionFactoryBean; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 10 | 11 | import javax.sql.DataSource; 12 | 13 | /** 14 | * ======================== 15 | * Mybatis配置 16 | * Author:pyy 17 | * Date:2019-9-25 16:45:06 18 | * Version: v1.0 19 | * ======================== 20 | */ 21 | @Configuration 22 | @MapperScan("com.thtf.generator.**.dao")// 扫描DAO 23 | public class MybatisConfig { 24 | @Autowired 25 | private DataSource dataSource; 26 | 27 | @Bean 28 | public SqlSessionFactory sqlSessionFactory() throws Exception { 29 | SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 30 | sessionFactory.setDataSource(dataSource); 31 | sessionFactory.setTypeAliasesPackage("com.thtf.generator.**.model"); // 扫描Model 32 | 33 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 34 | sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/mappers/*.xml")); // 扫描映射文件 35 | 36 | return sessionFactory.getObject(); 37 | } 38 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.PathSelectors; 7 | import springfox.documentation.builders.RequestHandlerSelectors; 8 | import springfox.documentation.service.ApiInfo; 9 | import springfox.documentation.spi.DocumentationType; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 12 | 13 | /** 14 | * ======================== 15 | * Swagger配置 16 | * Author:pyy 17 | * Date:2019-9-25 16:45:06 18 | * Version: v1.0 19 | * ======================== 20 | */ 21 | @Configuration 22 | @EnableSwagger2 23 | public class SwaggerConfig { 24 | 25 | @Bean 26 | public Docket createRestApi() { 27 | return new Docket(DocumentationType.SWAGGER_2) 28 | .apiInfo(apiInfo()) 29 | .select() 30 | .apis(RequestHandlerSelectors.basePackage("com.thtf.generator")) 31 | .paths(PathSelectors.any()) 32 | .build(); 33 | } 34 | 35 | private ApiInfo apiInfo() { 36 | return new ApiInfoBuilder() 37 | .title("代码自动生成项目api文档") 38 | .description("代码自动生成项目api文档") 39 | .version("1.0") 40 | .build(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.config; 2 | 3 | import org.apache.ibatis.type.JdbcType; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.context.request.RequestContextListener; 7 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | import tk.mybatis.mapper.autoconfigure.ConfigurationCustomizer; 10 | 11 | @Configuration 12 | public class WebMvcConfig implements WebMvcConfigurer { 13 | 14 | @Override 15 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 16 | registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/"); 17 | registry.addResourceHandler("swagger-ui.html") 18 | .addResourceLocations("classpath:/META-INF/resources/"); 19 | registry.addResourceHandler("/webjars/**") 20 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 21 | } 22 | 23 | /** 24 | * 解决Mybatis通用Mapper updateByPrimarykey()和insert()方法报错,提示jdbctype错误 25 | */ 26 | @Bean 27 | public ConfigurationCustomizer configurationCustomizer(){ 28 | return new MybatisPlusCustomizers(); 29 | } 30 | 31 | class MybatisPlusCustomizers implements ConfigurationCustomizer { 32 | 33 | @Override 34 | public void customize(org.apache.ibatis.session.Configuration configuration) { 35 | configuration.setJdbcTypeForNull(JdbcType.NULL); 36 | } 37 | } 38 | 39 | @Bean 40 | public RequestContextListener requestContextListener(){ 41 | return new RequestContextListener(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/controller/GenerateController.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.controller; 2 | 3 | import com.thtf.generator.common.response.Result; 4 | import com.thtf.generator.common.response.ResultCode; 5 | import com.thtf.generator.service.GenerateService; 6 | import com.thtf.generator.vo.ConnParam; 7 | import com.thtf.generator.vo.GenerateModel; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | 15 | /** 16 | * ======================== 17 | * 代码生成控制器 18 | * Author:pyy 19 | * Date:2019-9-25 17:07:15 20 | * Version: v1.0 21 | * ======================== 22 | */ 23 | @RestController 24 | @RequestMapping("/v1") 25 | public class GenerateController { 26 | 27 | @Autowired 28 | private GenerateService generatorService; 29 | 30 | @PostMapping("/testConnection") 31 | public Result testConnection(@RequestBody ConnParam connParam) { 32 | boolean success = generatorService.testConnection(connParam); 33 | if(success) { 34 | return Result.SUCCESS(); 35 | } 36 | return new Result(ResultCode.CONNECTION_ERROR); 37 | } 38 | 39 | @PostMapping("/getTables") 40 | public Result getTables(@RequestBody ConnParam connParam) { 41 | return Result.SUCCESS(generatorService.getTables(connParam)); 42 | } 43 | 44 | @PostMapping("/getGenerateModel") 45 | public Result getGenerateModel(@RequestBody GenerateModel generateModel) { 46 | return Result.SUCCESS(generatorService.getGenerateModel(generateModel)); 47 | } 48 | 49 | @PostMapping("/generateModels") 50 | public Result generateModels(@RequestBody GenerateModel generateModel) throws Exception { 51 | return Result.SUCCESS(generatorService.generateModels(generateModel)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/converter/CommonMetaDataConverter.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.converter; 2 | 3 | import com.thtf.generator.dao.IMetaDataConverter; 4 | import com.thtf.generator.model.*; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * ======================== 10 | * 通用元数据转换器 11 | * Author:pyy 12 | * Date:2019-9-25 16:07:53 13 | * Version: v1.0 14 | * ======================== 15 | */ 16 | public class CommonMetaDataConverter implements IMetaDataConverter { 17 | 18 | // 查询返回的字段名是全大写,所以在用map获取值时,需要用大写字段名 19 | private static final IMetaDataConverter instance = new CommonMetaDataConverter(); 20 | 21 | public static IMetaDataConverter getInstance() { 22 | return instance; 23 | } 24 | 25 | @Override 26 | public Table convertMap2Table(Map map) { 27 | Table table = new Table(); 28 | table.setName(getValue(map, "TABLE_NAME")); 29 | table.setTablespace(getValue(map, "TABLESPACE")); 30 | table.setDescription(getValue(map, "DESCRIPTION")); 31 | return table; 32 | } 33 | 34 | @Override 35 | public Column convertMap2Column(Map map) { 36 | Column column = new Column(); 37 | column.setName(getValue(map, "COLUMN_NAME")); 38 | column.setTableName(getValue(map, "TABLE_NAME")); 39 | column.setDataType(getValue(map, "DATA_TYPE")); 40 | // Oracle/MySQL,非数值类型字段的DATA_PRECISION的值为null 41 | String dataPrecision = getValue(map, "DATA_PRECISION"); 42 | if (null != dataPrecision) { 43 | column.setLength(dataPrecision); 44 | } else { 45 | column.setLength(getValue(map, "DATA_LENGTH")); 46 | } 47 | // data_scale才是小数位 48 | // column.setPrecision(getValue(map, "PRECISION")); 49 | column.setPrecision(getValue(map, "DATA_SCALE")); 50 | // Column类的isNullable为true表示不允许为空 51 | if("N".equalsIgnoreCase(getValue(map, "NULLABLE")) || "NO".equalsIgnoreCase(getValue(map, "NULLABLE")) 52 | || "NOT".equalsIgnoreCase(getValue(map, "NULLABLE"))) { 53 | column.setNullable(false); 54 | } else { 55 | column.setNullable(true); 56 | } 57 | column.setDescription(getValue(map, "DESCRIPTION")); 58 | column.setDefaultValue(getValue(map, "DEFAULT_VALUE")); 59 | return column; 60 | } 61 | 62 | @Override 63 | public PrimaryKey convertMap2PrimaryKey(Map map) { 64 | PrimaryKey primaryKey = new PrimaryKey(); 65 | primaryKey.setName(getValue(map, "CONSTRAINT_NAME")); 66 | primaryKey.setTableName(getValue(map, "TABLE_NAME")); 67 | primaryKey.setCloumn(getValue(map, "COLUMN_NAME")); 68 | 69 | return primaryKey; 70 | } 71 | 72 | @Override 73 | public ForeignKey convertMap2ForeignKey(Map map) { 74 | ForeignKey fk = new ForeignKey(); 75 | fk.setFkName(getValue(map, "FK_NAME")); 76 | fk.setFkTableName(getValue(map, "FK_TABLE_NAME")); 77 | fk.setFkColumnName(getValue(map, "FK_COLUMN_NAME")); 78 | fk.setPkTableName(getValue(map, "PK_TABLE_NAME")); 79 | fk.setPkColumnName(getValue(map, "PK_COLUMN_NAME")); 80 | return fk; 81 | } 82 | 83 | @Override 84 | public Index convertMap2Index(Map map) { 85 | Index index = new Index(); 86 | index.setName(getValue(map, "INDEX_NAME")); 87 | index.setTableName(getValue(map, "TABLE_NAME")); 88 | index.setIndexType(getValue(map, "INDEX_TYPE")); 89 | index.setUnique(Boolean.valueOf(getValue(map, "IS_UNIQUE"))); 90 | index.getCloumns().add(getValue(map, "COLUMN_NAME")); 91 | return index; 92 | } 93 | 94 | @Override 95 | public Trigger convertMap2Trigger(Map map) { 96 | Trigger trigger = new Trigger(); 97 | trigger.setName(getValue(map, "TRIGGER_NAME")); 98 | trigger.setTriggerType(getValue(map, "TRIGGER_TYPE")); 99 | trigger.setEventType(getValue(map, "EVENT_TYPE")); 100 | trigger.setDefinition(getValue(map, "TRIGGER_BODY")); 101 | trigger.setDescription(getValue(map, "DESCRIPTION")); 102 | 103 | return trigger; 104 | } 105 | 106 | protected String getValue(Map map, String key) { 107 | assert !map.containsKey(key) : map.toString() + "不含有key【" + key + "】"; 108 | return map.get(key); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/converter/MySQL5MetaDataConverter.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.converter; 2 | 3 | import com.thtf.generator.dao.IMetaDataConverter; 4 | import com.thtf.generator.model.Index; 5 | import com.thtf.generator.model.Table; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * ======================== 11 | * 元数据转换器 12 | * Author:pyy 13 | * Date:2019-9-25 16:07:53 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | public class MySQL5MetaDataConverter extends CommonMetaDataConverter { 18 | 19 | private static IMetaDataConverter instance = new MySQL5MetaDataConverter(); 20 | 21 | public static final IMetaDataConverter getInstance() { 22 | return instance; 23 | } 24 | 25 | @Override 26 | public Table convertMap2Table(Map map) { 27 | Table table = super.convertMap2Table(map); 28 | 29 | /** 30 | * MySQL5的information_schema.TABLES表的table_comment字段存储的值是: 31 | * 如果有注释:"表注释; InnoDB free: 4096 kB" 32 | * 如果没有注释,"InnoDB free: 4096 kB"这样存储引擎信息 33 | * 故需要字符串截取 34 | */ 35 | // String desc = table.getDescription(); 36 | // int endIndex = desc.lastIndexOf(";"); 37 | // if (endIndex != -1) { 38 | // desc = desc.substring(0, endIndex); 39 | // } 40 | // table.setDescription(desc); 41 | return table; 42 | } 43 | 44 | @Override 45 | public Index convertMap2Index(Map map) { 46 | Index index = super.convertMap2Index(map); 47 | // MySql5的只有non_unique字段 , 没有IS_UNIQUE。0表示不为空 48 | index.setUnique("0".equals(getValue(map, "NON_UNIQUE"))); 49 | return index; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/converter/OracleMetaDataConverter.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.converter; 2 | 3 | import com.thtf.generator.dao.IMetaDataConverter; 4 | import com.thtf.generator.model.Column; 5 | import com.thtf.generator.model.Index; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * ======================== 11 | * 元数据转换器 12 | * Author:pyy 13 | * Date:2019-9-25 16:07:53 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | public class OracleMetaDataConverter extends CommonMetaDataConverter { 18 | 19 | private static final IMetaDataConverter instance = new OracleMetaDataConverter(); 20 | 21 | public static IMetaDataConverter getInstance() { 22 | return instance; 23 | } 24 | 25 | @Override 26 | public Column convertMap2Column(Map map) { 27 | Column column = super.convertMap2Column(map); 28 | 29 | String charLength = getValue(map, "CHAR_LENGTH"); 30 | if (!"0".equals(charLength) && column.getDataType().contains("CHAR")) { 31 | // String length = getValue(map, "DATA_LENGTH"); 32 | // String.valueOf(Integer.valueOf(charLength).intValue() * 2) 33 | // if (NumberUtils.toInt(length) == NumberUtils.toInt(charLength) * 2) { 34 | // charLength += " char"; 35 | // } 36 | column.setLength(charLength); 37 | // } else { 38 | // // Oracel,非数值精度为null 39 | // String precision = getValue(map, "DATA_PRECISION"); 40 | // if (StringUtils.isNotEmpty(precision) 41 | // && !"0".equals(precision)) { 42 | // column.setLength(precision); 43 | // } else { 44 | // column.setLength(getValue(map, "DATA_LENGTH")); 45 | // } 46 | } 47 | return column; 48 | } 49 | 50 | @Override 51 | public Index convertMap2Index(Map map) { 52 | Index index = super.convertMap2Index(map); 53 | // Oracle的user_indexes的uniqueness字段 as IS_UNIQUE,如果返回的是NONUNIQUE表示可为空 54 | index.setUnique("NONUNIQUE".equals( 55 | getValue(map, "IS_UNIQUE")) ? false : true); 56 | return index; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/DatabaseDAOFactory.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao; 2 | 3 | import com.thtf.generator.common.constants.DBMSConstants; 4 | import com.thtf.generator.dao.impl.CommonDatabaseDAOImpl; 5 | import com.thtf.generator.dao.impl.MySql5DatabaseDAO; 6 | import com.thtf.generator.dao.sql.DatabaseType; 7 | import com.thtf.generator.vo.ConnParam; 8 | 9 | /** 10 | * ======================== 11 | * 查询器生成工厂 12 | * Author:pyy 13 | * Date:2019-9-25 16:22:57 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | public class DatabaseDAOFactory { 18 | 19 | public static IDatabaseDAO getDAO(ConnParam connParam) { 20 | String upperCaseDbName = connParam.getDbType().toUpperCase(); 21 | 22 | if (upperCaseDbName.contains(DBMSConstants.ORACLE)) { 23 | return new CommonDatabaseDAOImpl(connParam, DatabaseType.Oracle); 24 | } else if (upperCaseDbName.contains(DBMSConstants.SQL_SERVER) || upperCaseDbName.contains(DBMSConstants.SQLSERVER)) { 25 | return new CommonDatabaseDAOImpl(connParam, DatabaseType.MSSQLServer); 26 | } else if (upperCaseDbName.contains(DBMSConstants.MYSQL)) { 27 | return new MySql5DatabaseDAO(connParam, DatabaseType.MySql5); 28 | } 29 | return new MySql5DatabaseDAO(connParam, DatabaseType.MySql5); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/IDatabaseDAO.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao; 2 | 3 | import com.thtf.generator.common.exception.DAOException; 4 | import com.thtf.generator.model.*; 5 | 6 | import java.sql.Connection; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * ======================== 12 | * 数据库元信息查询接口 13 | * Author:pyy 14 | * Date:2019-9-25 16:23:28 15 | * Version: v1.0 16 | * ======================== 17 | */ 18 | public interface IDatabaseDAO { 19 | 20 | /** 21 | * 通用查询方法 22 | * @param sql 要查询的sql语句 23 | * @param params 查询条件数组 24 | * @return 25 | * @throws DAOException 26 | */ 27 | List> query(String sql, String[] params) throws DAOException; 28 | 29 | /** 30 | * 查询表集合 31 | * @return 32 | * @throws DAOException 33 | */ 34 | List getTables() throws DAOException; 35 | 36 | /** 37 | * 查询表的字段集 38 | * @param tableName 39 | * @return 40 | * @throws DAOException 41 | */ 42 | List getColumns(String tableName) throws DAOException; 43 | 44 | /** 45 | * 查询主键集 46 | * @param tableName 47 | * @return 48 | * @throws DAOException 49 | */ 50 | List getPrimaryKeys(String tableName) throws DAOException; 51 | 52 | /** 53 | * 查询外键集 54 | * @param tableName 55 | * @return 56 | * @throws DAOException 57 | */ 58 | List getForeignKeys(String tableName) throws DAOException; 59 | 60 | /** 61 | * 查询索引集 62 | * @return 63 | * @throws DAOException 64 | */ 65 | List getIndexes(String tableName) throws DAOException; 66 | 67 | /** 68 | * 查询触发器集 69 | * @param tableName 70 | * @return 71 | * @throws DAOException 72 | */ 73 | List getTriggers(String tableName) throws DAOException; 74 | 75 | /** 76 | * 打开数据库连接 77 | */ 78 | Connection openConnection() throws DAOException; 79 | 80 | /** 81 | * 关闭数据库连接 82 | */ 83 | void closeConnection() throws DAOException; 84 | } 85 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/IMetaDataConverter.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao; 2 | 3 | import com.thtf.generator.model.*; 4 | import java.util.Map; 5 | 6 | /** 7 | * ======================== 8 | * 元数据转换器接口 9 | * Author:pyy 10 | * Date:2019-9-25 16:17:49 11 | * Version: v1.0 12 | * ======================== 13 | */ 14 | public interface IMetaDataConverter { 15 | 16 | /** 17 | * 将map转换为Table 18 | * 19 | * @param map 20 | * @return 21 | */ 22 | Table convertMap2Table(Map map); 23 | 24 | /** 25 | * 将map转换为Column 26 | * 27 | * @param map 28 | * @return 29 | */ 30 | Column convertMap2Column(Map map); 31 | 32 | /** 33 | * 将map转换为PrimaryKey 34 | * 35 | * @param map 36 | * @return 37 | */ 38 | PrimaryKey convertMap2PrimaryKey(Map map); 39 | 40 | /** 41 | * 将map转换为ForeignKey 42 | * 43 | * @param map 44 | * @return 45 | */ 46 | ForeignKey convertMap2ForeignKey(Map map); 47 | 48 | /** 49 | * 将map转换为Index 50 | * 51 | * @param map 52 | * @return 53 | */ 54 | Index convertMap2Index(Map map); 55 | 56 | /** 57 | * 将map转换为Triger 58 | * 59 | * @param map 60 | * @return 61 | */ 62 | Trigger convertMap2Trigger(Map map); 63 | } 64 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/impl/CommonDatabaseDAOImpl.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao.impl; 2 | import com.thtf.generator.common.exception.DAOException; 3 | import com.thtf.generator.dao.sql.DatabaseType; 4 | import com.thtf.generator.utils.Dom4jUtils; 5 | import com.thtf.generator.vo.ConnParam; 6 | import org.dom4j.Document; 7 | import org.dom4j.Element; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * ======================== 17 | * 通用数据库元信息查询类 18 | * Author:pyy 19 | * Date:2019-9-25 16:29:13 20 | * Version: v1.0 21 | * ======================== 22 | */ 23 | public class CommonDatabaseDAOImpl extends AbstractDatabasetDAOImpl { 24 | 25 | private static final String ELEMENT_DRIVER = DRIVER; 26 | private static final String ELEMENT_URL = URL; 27 | private static final String ELEMENT_SELECT = "select"; 28 | private static final String ATTRIBUTE_NAME = "name"; 29 | 30 | private String driver; 31 | private String url; 32 | private Map selectMap = new HashMap(); 33 | 34 | private DatabaseType dbType; 35 | 36 | /** 37 | * @param connParam 38 | */ 39 | public CommonDatabaseDAOImpl(ConnParam connParam, DatabaseType dbType) { 40 | super(connParam); 41 | 42 | setDbType(dbType); 43 | loadSqlXml(dbType); 44 | } 45 | 46 | /** 47 | * @param dbType the dbType to set 48 | */ 49 | public void setDbType(DatabaseType dbType) { 50 | this.dbType = dbType; 51 | setConverter(dbType.getConverter()); 52 | } 53 | 54 | @Override 55 | protected String getDriver() throws DAOException { 56 | return driver; 57 | } 58 | 59 | @Override 60 | protected String getUrl(String host, int port, String dbName) throws DAOException{ 61 | return String.format(url, host, port, dbName); 62 | } 63 | 64 | protected String getQuerySql(String sqlKey) throws DAOException { 65 | if (selectMap.containsKey(sqlKey)) { 66 | return selectMap.get(sqlKey); 67 | } 68 | throw new DAOException(DAOException.QUERY_EXCEPTION, "获取sql查询出错,数据库枚举类型为:" + dbType + ",查询语句为:" + sqlKey, null); 69 | } 70 | 71 | @SuppressWarnings("unchecked") 72 | private void loadSqlXml(DatabaseType dbType) { 73 | InputStream is = this.getClass().getClassLoader().getResourceAsStream( 74 | dbType.getFileName()); 75 | Document doc = Dom4jUtils.getDocument(is); 76 | if (doc != null) { 77 | Element root = doc.getRootElement(); 78 | 79 | driver = root.elementText(ELEMENT_DRIVER); 80 | url = root.elementText(ELEMENT_URL); 81 | 82 | for (Element selectElem : (List) root.elements(ELEMENT_SELECT)) { 83 | selectMap.put(selectElem.attributeValue(ATTRIBUTE_NAME), selectElem.getTextTrim()); 84 | } 85 | } 86 | try { 87 | is.close(); 88 | } catch (IOException e) { 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/impl/MySql5DatabaseDAO.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao.impl; 2 | 3 | import com.thtf.generator.common.exception.DAOException; 4 | import com.thtf.generator.dao.sql.DatabaseType; 5 | import com.thtf.generator.vo.ConnParam; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * MySQL数据库元信息查询 12 | * @author Louis 13 | * @date Nov 10, 2018 14 | */ 15 | public class MySql5DatabaseDAO extends CommonDatabaseDAOImpl { 16 | 17 | public MySql5DatabaseDAO(ConnParam connParam, DatabaseType dbType) { 18 | super(connParam, dbType); 19 | } 20 | 21 | @Override 22 | protected String getQuerySql(String sqlKey) throws DAOException { 23 | return super.getQuerySql(sqlKey); 24 | } 25 | 26 | @Override 27 | public List> query(String sql, String[] params) 28 | throws DAOException { 29 | String[] realParams; 30 | if (params == null) { 31 | realParams = new String[] {connParam.getDbName()}; 32 | } else { 33 | realParams = new String[params.length + 1]; 34 | realParams[0] = connParam.getDbName(); 35 | for (int i = 0; i < params.length; i++) { 36 | realParams[i + 1] = params[i]; 37 | } 38 | } 39 | return super.query(sql, realParams); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/sql/DatabaseType.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.dao.sql; 2 | 3 | 4 | import com.thtf.generator.converter.CommonMetaDataConverter; 5 | import com.thtf.generator.converter.MySQL5MetaDataConverter; 6 | import com.thtf.generator.converter.OracleMetaDataConverter; 7 | import com.thtf.generator.dao.IMetaDataConverter; 8 | 9 | /** 10 | * ======================== 11 | * 数据库查询语句文件 12 | * Author:pyy 13 | * Date:2019-9-25 16:17:49 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | public enum DatabaseType { 18 | 19 | Oracle { 20 | 21 | @Override 22 | public String getFileName() { 23 | return FOLDER + "/Oracle.xml"; 24 | } 25 | 26 | @Override 27 | public IMetaDataConverter getConverter() { 28 | return OracleMetaDataConverter.getInstance(); 29 | } 30 | 31 | }, 32 | 33 | MySql5 { 34 | @Override 35 | public String getFileName() { 36 | return FOLDER + "/MySQL5.xml"; 37 | } 38 | 39 | @Override 40 | public IMetaDataConverter getConverter() { 41 | return MySQL5MetaDataConverter.getInstance(); 42 | } 43 | }, 44 | 45 | MSSQLServer { 46 | @Override 47 | public String getFileName() { 48 | return FOLDER + "/MSSQL.xml"; 49 | } 50 | }; 51 | 52 | private static final String FOLDER = 53 | DatabaseType.class.getPackage().getName().replace('.', '/'); 54 | 55 | abstract public String getFileName(); 56 | 57 | public IMetaDataConverter getConverter() { 58 | return CommonMetaDataConverter.getInstance(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/sql/MSSQL.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.microsoft.sqlserver.jdbc.SQLServerDriver 4 | jdbc:sqlserver://%s:%d;DatabaseName=%s 5 | 16 | 36 | 49 | 64 | 77 | 93 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/sql/MySQL5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.mysql.jdbc.Driver 4 | jdbc:mysql://%s:%d/%s 5 | 16 | 34 | 51 | 71 | 85 | 97 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/dao/sql/Oracle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | oracle.jdbc.driver.OracleDriver 4 | jdbc:oracle:thin:@%s:%d:%s 5 | 15 | 35 | 36 | 48 | 71 | 85 | 97 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/Column.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | 4 | import lombok.Data; 5 | 6 | /** 7 | * ======================== 8 | * 字段 9 | * Author:pyy 10 | * Date:2019-9-25 16:12:59 11 | * Version: v1.0 12 | * ======================== 13 | */ 14 | @Data 15 | public class Column { 16 | 17 | /** 名称 */ 18 | private String name; 19 | /** 表名称 */ 20 | private String tableName; 21 | /** 数据类型 */ 22 | private String dataType; 23 | /** 是否可空 */ 24 | private boolean isNullable; 25 | /** 默认值 */ 26 | private String defaultValue; 27 | /** 长度 */ 28 | private String length; 29 | /** 小数位 */ 30 | private String precision; 31 | /** 描述 */ 32 | private String description; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/ForeignKey.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 外键 8 | * Author:pyy 9 | * Date:2019-9-25 16:12:56 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class ForeignKey { 15 | 16 | /** 外键名称 */ 17 | private String fkName; 18 | 19 | /** 主键表名称 */ 20 | private String pkTableName; 21 | 22 | /** 主键列名称 */ 23 | private String pkColumnName; 24 | 25 | /** 外键表名称 */ 26 | private String fkTableName; 27 | 28 | /** 外键列名称 */ 29 | private String fkColumnName; 30 | } 31 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/Index.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * ======================== 11 | * 索引 12 | * Author:pyy 13 | * Date:2019-9-25 16:12:53 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | @Data 18 | public class Index { 19 | 20 | /** 名称 */ 21 | private String name; 22 | /** 所属类型 */ 23 | private String indexType; 24 | /** 所属表名称 */ 25 | private String tableName; 26 | /** 是否唯一索引 */ 27 | private boolean unique; 28 | /** 字段列表 */ 29 | private List cloumns = new ArrayList(); 30 | 31 | public void addCloumn(String cloumn) { 32 | this.cloumns.add(cloumn); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/PrimaryKey.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 主键 8 | * Author:pyy 9 | * Date:2019-9-25 16:13:37 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class PrimaryKey { 15 | 16 | /** 名称 */ 17 | private String name; 18 | /** 所属表名称 */ 19 | private String tableName; 20 | /** 字段 */ 21 | private String cloumn; 22 | } 23 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/Procedure.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 存储过程 8 | * Author:pyy 9 | * Date:2019-9-25 16:14:08 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class Procedure { 15 | 16 | /** 名称 */ 17 | private String name; 18 | 19 | /** 描述 */ 20 | private String description; 21 | 22 | /** 内容定义 */ 23 | private String definition; 24 | } 25 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/Table.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * ======================== 10 | * 数据表 11 | * Author:pyy 12 | * Date:2019-9-25 16:14:37 13 | * Version: v1.0 14 | * ======================== 15 | */ 16 | @Data 17 | public class Table { 18 | 19 | /** 名称 */ 20 | private String name; 21 | /** 描述 */ 22 | private String description; 23 | /** 表空间 */ 24 | private String tablespace; 25 | /** 索引字段列表 */ 26 | private List columns = new ArrayList(); 27 | } 28 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/model/Trigger.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 触发器 8 | * Author:pyy 9 | * Date:2019-9-25 16:14:58 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class Trigger { 15 | 16 | /** 触发器名称 */ 17 | private String name; 18 | 19 | /** 触发器类型 */ 20 | private String triggerType; 21 | 22 | /** 触发器事件类型 */ 23 | private String eventType; 24 | 25 | /** 触发器事件描述 */ 26 | private String description; 27 | 28 | /** 触发器事件内容定义 */ 29 | private String definition; 30 | } 31 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/service/DatabaseService.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.service; 2 | 3 | import com.thtf.generator.common.exception.DAOException; 4 | import com.thtf.generator.model.*; 5 | import com.thtf.generator.vo.ConnParam; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | 11 | /** 12 | * ======================== 13 | * 数据库元信息查询服务Service接口 14 | * Author:pyy 15 | * Date:2019-9-22 11:37:34 16 | * Version: v1.0 17 | * ======================== 18 | */ 19 | public interface DatabaseService { 20 | 21 | /** 22 | * 通用查询方法 23 | * @param connParam 连接参数 24 | * @param sql 要查询的sql语句 25 | * @param params 查询条件数组 26 | * @return 27 | * @throws DAOException 28 | */ 29 | List> query(ConnParam connParam, String sql, String[] params); 30 | 31 | /** 32 | * 查询表集合 33 | * @param connParam 连接参数 34 | * @return 35 | * @throws DAOException 36 | */ 37 | List
getTables(ConnParam connParam); 38 | 39 | /** 40 | * 查询表的字段集 41 | * @param connParam 连接参数 42 | * @param tableName 43 | * @return 44 | * @throws DAOException 45 | */ 46 | List getColumns(ConnParam connParam, String tableName); 47 | 48 | /** 49 | * 查询主键集 50 | * @param connParam 连接参数 51 | * @param tableName 52 | * @return 53 | * @throws DAOException 54 | */ 55 | List getPrimaryKeys(ConnParam connParam, String tableName); 56 | 57 | /** 58 | * 查询外键集 59 | * @param connParam 连接参数 60 | * @param tableName 61 | * @return 62 | * @throws DAOException 63 | */ 64 | List getForeignKeys(ConnParam connParam, String tableName); 65 | 66 | /** 67 | * 查询索引集 68 | * @param connParam 连接参数 69 | * @return 70 | * @throws DAOException 71 | */ 72 | List getIndexes(ConnParam connParam, String tableName); 73 | 74 | /** 75 | * 查询触发器集 76 | * @param connParam 连接参数 77 | * @param tableName 78 | * @return 79 | * @throws DAOException 80 | */ 81 | List getTriggers(ConnParam connParam, String tableName); 82 | 83 | /** 84 | * 测试数据库是否可以连接 85 | * @param connParam 86 | * @return 87 | */ 88 | boolean canConnect(ConnParam connParam); 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/service/GenerateService.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.service; 2 | 3 | 4 | import com.thtf.generator.model.Table; 5 | import com.thtf.generator.vo.ConnParam; 6 | import com.thtf.generator.vo.GenerateModel; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | 12 | /** 13 | * ======================== 14 | * 代码生成服务service接口 15 | * Author:pyy 16 | * Date:2019-9-28 16:50:17 17 | * Version: v1.0 18 | * ======================== 19 | */ 20 | public interface GenerateService { 21 | 22 | /** 23 | * 是否可以连接 24 | * @param connParam 25 | * @return 26 | */ 27 | boolean testConnection(ConnParam connParam); 28 | 29 | /** 30 | * 反向查找数据表 31 | * @param connParam 32 | * @return 33 | */ 34 | List
getTables(ConnParam connParam); 35 | 36 | /** 37 | * 获取代码生成数据模型 38 | * @param generateModel 39 | * @return 40 | */ 41 | GenerateModel getGenerateModel(GenerateModel generateModel); 42 | 43 | /** 44 | * 生成代码文件 45 | * @param generateModel 46 | * @return 47 | * @throws IOException 48 | */ 49 | boolean generateModels(GenerateModel generateModel) throws Exception; 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/service/impl/DatabaseServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.service.impl; 2 | 3 | import com.thtf.generator.common.exception.DAOException; 4 | import com.thtf.generator.dao.DatabaseDAOFactory; 5 | import com.thtf.generator.dao.IDatabaseDAO; 6 | import com.thtf.generator.model.*; 7 | import com.thtf.generator.service.DatabaseService; 8 | import com.thtf.generator.vo.ConnParam; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | 17 | /** 18 | * ======================== 19 | * 数据库元信息查询服务service实现类 20 | * Author:pyy 21 | * Date:2019-9-25 16:37:34 22 | * Version: v1.0 23 | * ======================== 24 | */ 25 | @Slf4j 26 | @Service 27 | public class DatabaseServiceImpl implements DatabaseService { 28 | 29 | @Override 30 | public List> query(ConnParam connParam, String sql, String[] params) { 31 | List> maps = new ArrayList>(); 32 | if(connParam == null) { 33 | return maps; 34 | } 35 | try { 36 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 37 | long start = System.currentTimeMillis(); 38 | dao.openConnection(); 39 | maps = dao.query(sql, params); 40 | dao.closeConnection(); 41 | long end = System.currentTimeMillis(); 42 | log.info("### 反向获取数据库表信息耗时:{} 毫秒 ###",(end - start)); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | return maps; 47 | } 48 | 49 | @Override 50 | public List
getTables(ConnParam connParam) { 51 | List
tables = new ArrayList
(); 52 | if(connParam == null) { 53 | return tables; 54 | } 55 | try { 56 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 57 | long start = System.currentTimeMillis(); 58 | dao.openConnection(); 59 | tables = dao.getTables(); 60 | dao.closeConnection(); 61 | long end = System.currentTimeMillis(); 62 | log.info("### 反向获取数据库表信息耗时:{} 毫秒 ###",(end - start)); 63 | } catch (Exception e) { 64 | e.printStackTrace(); 65 | } 66 | return tables; 67 | } 68 | 69 | @Override 70 | public List getColumns(ConnParam connParam, String tableName) { 71 | List columns = new ArrayList(); 72 | if(connParam == null) { 73 | return columns; 74 | } 75 | try { 76 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 77 | long start = System.currentTimeMillis(); 78 | dao.openConnection(); 79 | columns = dao.getColumns(tableName); 80 | dao.closeConnection(); 81 | long end = System.currentTimeMillis(); 82 | log.info("### 反向获取数据库表列信息耗时:{} 毫秒 ###",(end - start)); 83 | } catch (Exception e) { 84 | e.printStackTrace(); 85 | } 86 | return columns; 87 | } 88 | 89 | @Override 90 | public List getPrimaryKeys(ConnParam connParam, String tableName) { 91 | List primaryKeys = new ArrayList(); 92 | if(connParam == null) { 93 | return primaryKeys; 94 | } 95 | try { 96 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 97 | long start = System.currentTimeMillis(); 98 | dao.openConnection(); 99 | primaryKeys = dao.getPrimaryKeys(tableName); 100 | dao.closeConnection(); 101 | long end = System.currentTimeMillis(); 102 | log.info("### 反向获取数据库表主键信息耗时:{} 毫秒 ###",(end - start)); 103 | } catch (Exception e) { 104 | e.printStackTrace(); 105 | } 106 | return primaryKeys; 107 | } 108 | 109 | @Override 110 | public List getForeignKeys(ConnParam connParam, String tableName) { 111 | List foreignKeys = new ArrayList(); 112 | if(connParam == null) { 113 | return foreignKeys; 114 | } 115 | try { 116 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 117 | long start = System.currentTimeMillis(); 118 | dao.openConnection(); 119 | foreignKeys = dao.getForeignKeys(tableName); 120 | dao.closeConnection(); 121 | long end = System.currentTimeMillis(); 122 | log.info("### 反向获取数据库表外键信息耗时:{} 毫秒 ###",(end - start)); 123 | } catch (Exception e) { 124 | e.printStackTrace(); 125 | } 126 | return foreignKeys; 127 | } 128 | 129 | @Override 130 | public List getIndexes(ConnParam connParam, String tableName) { 131 | List indexes = new ArrayList(); 132 | if(connParam == null) { 133 | return indexes; 134 | } 135 | try { 136 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 137 | long start = System.currentTimeMillis(); 138 | dao.openConnection(); 139 | indexes = dao.getIndexes(tableName); 140 | long end = System.currentTimeMillis(); 141 | log.info("### 反向获取数据库表索引信息耗时:{} 毫秒 ###",(end - start)); 142 | dao.closeConnection(); 143 | } catch (Exception e) { 144 | e.printStackTrace(); 145 | } 146 | return indexes; 147 | } 148 | 149 | @Override 150 | public List getTriggers(ConnParam connParam, String tableName) { 151 | List trigger = new ArrayList(); 152 | if(connParam == null) { 153 | return trigger; 154 | } 155 | try { 156 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 157 | long start = System.currentTimeMillis(); 158 | dao.openConnection(); 159 | trigger = dao.getTriggers(tableName); 160 | long end = System.currentTimeMillis(); 161 | log.info("### 反向获取数据库表触发器信息耗时:{} 毫秒 ###",(end - start)); 162 | dao.closeConnection(); 163 | } catch (Exception e) { 164 | e.printStackTrace(); 165 | } 166 | return trigger; 167 | } 168 | 169 | @Override 170 | public boolean canConnect(ConnParam connParam) { 171 | IDatabaseDAO dao = DatabaseDAOFactory.getDAO(connParam); 172 | if (dao == null) { 173 | return false; 174 | } 175 | try { 176 | dao.openConnection(); 177 | log.info("### 数据库连接成功! ###"); 178 | return true; 179 | } catch (Exception e) { 180 | log.info("### 数据库连接失败,请检查端口号、用户名或密码 !###"); 181 | } finally { 182 | try { 183 | dao.closeConnection(); 184 | } catch (DAOException e) { 185 | e.printStackTrace(); 186 | } 187 | } 188 | return false; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/utils/DataTypeUtils.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.utils; 2 | 3 | /** 4 | * 数据类型工具类 5 | * @author pyy 6 | */ 7 | public class DataTypeUtils { 8 | 9 | public static final String String = "String"; 10 | public static final String Byte = "Byte"; 11 | public static final String ByteArray = "byte[]"; 12 | public static final String Short = "Short"; 13 | public static final String Integer = "Integer"; 14 | public static final String Long = "Long"; 15 | public static final String Float = "Float"; 16 | public static final String Double = "Double"; 17 | public static final String Character = "Character"; 18 | public static final String Boolean = "Boolean"; 19 | public static final String Date = "java.util.Date"; 20 | public static final String Time = "java.sql.Time"; 21 | public static final String Timestamp = "java.sql.Timestamp"; 22 | public static final String Object = "java.lang.Object"; 23 | 24 | public static final String CHAR = "CHAR"; 25 | public static final String TEXT = "TEXT"; 26 | public static final String BLOB = "BLOB"; 27 | public static final String CLOB = "CLOB"; 28 | public static final String BIT = "BIT"; 29 | public static final String TINYINT = "TINYINT"; 30 | public static final String SMALLINT = "SMALLINT"; 31 | public static final String INT = "INT"; 32 | public static final String INT8 = "INT8"; 33 | public static final String BIGINT = "BIGINT"; 34 | public static final String LONG = "LONG"; 35 | public static final String FLOAT = "FLOAT"; 36 | public static final String NUMBER = "NUMBER"; 37 | public static final String NUMERIC = "NUMERIC"; 38 | public static final String DECIMAL = "DECIMAL"; 39 | public static final String DOUBLE = "DOUBLE"; 40 | public static final String BOOL = "BOOL"; 41 | public static final String BOOLEAN = "BOOLEAN"; 42 | public static final String DATE = "DATE"; 43 | public static final String TIME = "TIME"; 44 | public static final String BINARY = "BINARY"; 45 | public static final String VARBINARY = "VARBINARY"; 46 | public static final String CHAR_FOR_BIT_DATA = "CHAR FOR BIT DATA"; 47 | public static final String RAW = "RAW"; 48 | public static final String IMAGE = "IMAGE"; 49 | public static final String BYTE = "BYTE"; 50 | public static final String DK_CM_BLOB = "DK_CM_BLOB"; 51 | public static final String DK_CM_SMALLINT = "DK_CM_SMALLINT"; 52 | public static final String OBJECT = "OBJECT"; 53 | public static final String LONGVARCHAR = "LONGVARCHAR"; 54 | public static final String INTEGER = "INTEGER"; 55 | public static final String TIMESTAMP = "TIMESTAMP"; 56 | public static final String VARCHAR = "VARCHAR"; 57 | 58 | /** 59 | * 根据数据库类型获取对应的JAVA类型 60 | * @param dataType 61 | * @return 62 | */ 63 | public static String getJavaType(String dataType) { 64 | String javaType = String; 65 | if (dataType != null) { 66 | dataType = dataType.toUpperCase(); 67 | if (dataType.contains(BINARY) || dataType.contains(CHAR_FOR_BIT_DATA) || dataType.contains(RAW) 68 | || dataType.contains(IMAGE) || dataType.contains(BYTE) || dataType.contains(DK_CM_BLOB) 69 | || dataType.contains(BLOB)) { 70 | javaType = ByteArray; 71 | } else if (dataType.contains(BOOLEAN) || dataType.contains(BIT) || dataType.contains(DK_CM_SMALLINT)) { 72 | javaType = Boolean; 73 | } else if (dataType.contains(CHAR) || dataType.contains(TEXT) || dataType.contains(CLOB)) { 74 | javaType = String; 75 | } else if (dataType.contains(LONG) || dataType.contains(BIGINT) || dataType.contains(INT8)) { 76 | javaType = Long; 77 | } else if (dataType.contains(INT)) { 78 | javaType = Integer; 79 | } else if (dataType.contains(FLOAT)) { 80 | javaType = Float; 81 | } else if (dataType.contains(NUMBER) || dataType.contains(DECIMAL) || dataType.contains(DOUBLE)) { 82 | javaType = Double; 83 | } else if (dataType.contains(DATE) || dataType.contains(TIME)) { 84 | javaType = Date; 85 | } else if (dataType.contains(OBJECT)) { 86 | javaType = Object; 87 | } 88 | } 89 | return javaType; 90 | } 91 | 92 | /** 93 | * 根据数据库类型获取对应JdbcType 94 | * @param dataType 95 | * @return 96 | */ 97 | public static String getJdbcType(String dataType) { 98 | String jdbcType = dataType.toUpperCase(); 99 | if (dataType.contains(BINARY) || dataType.contains(CHAR_FOR_BIT_DATA) || dataType.contains(RAW) 100 | || dataType.contains(IMAGE) || dataType.contains(BYTE) || dataType.contains(DK_CM_BLOB)) { 101 | jdbcType = VARBINARY; 102 | } else if (dataType.contains(BLOB)) { 103 | jdbcType = BLOB; 104 | } else if (dataType.contains(CLOB)) { 105 | jdbcType = CLOB; 106 | } else if (dataType.contains(BOOLEAN)) { 107 | jdbcType = BOOLEAN; 108 | } else if (dataType.contains(BIT) || dataType.contains(DK_CM_SMALLINT)) { 109 | jdbcType = BIT; 110 | } else if (jdbcType.equalsIgnoreCase(TINYINT)) { 111 | jdbcType = TINYINT; 112 | } else if (jdbcType.equalsIgnoreCase(SMALLINT)) { 113 | jdbcType = SMALLINT; 114 | } else if (jdbcType.equalsIgnoreCase(INT) || jdbcType.contains(INTEGER)) { 115 | jdbcType = INTEGER; 116 | } else if (jdbcType.equalsIgnoreCase(DATE)) { 117 | jdbcType = DATE; 118 | } else if (jdbcType.equalsIgnoreCase(TIME)) { 119 | jdbcType = TIME; 120 | } else if(jdbcType.contains(DATE) || jdbcType.contains(TIME)) { 121 | jdbcType = TIMESTAMP; 122 | } else if(jdbcType.contains(FLOAT)) { 123 | jdbcType = FLOAT; 124 | } else if(jdbcType.contains(DOUBLE)) { 125 | jdbcType = DOUBLE; 126 | } else if(jdbcType.contains(DECIMAL)) { 127 | jdbcType = DECIMAL; 128 | } else if(jdbcType.contains(NUMBER) || jdbcType.contains(NUMERIC)) { 129 | jdbcType = NUMERIC; 130 | } else if(jdbcType.contains(TEXT) || jdbcType.contains(LONGVARCHAR)) { 131 | jdbcType = LONGVARCHAR; 132 | } else if(jdbcType.contains(VARCHAR)) { 133 | jdbcType = VARCHAR; 134 | } 135 | return jdbcType; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/utils/Dom4jUtils.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.utils; 2 | 3 | import com.thtf.generator.common.constants.CommonConstants; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.dom4j.Document; 6 | import org.dom4j.DocumentFactory; 7 | import org.dom4j.Namespace; 8 | import org.dom4j.io.OutputFormat; 9 | import org.dom4j.io.SAXReader; 10 | import org.dom4j.io.XMLWriter; 11 | 12 | import java.io.*; 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * DOM4J解析框架相关操作方法 20 | * @author pyy 21 | */ 22 | public class Dom4jUtils { 23 | 24 | public static String nameSpacePrefix=null; 25 | private static String nameSpace=null; 26 | 27 | private Dom4jUtils() { 28 | /* 禁止外部实例化 */ 29 | } 30 | 31 | /** 32 | * 根据文件获取对应的Document对象 33 | * @param file 34 | * @return 35 | */ 36 | public static Document getDocument(File file){ 37 | return getDocument(file.getAbsolutePath()); 38 | } 39 | 40 | /** 41 | * 根据文件路径获取对应的Document对象 42 | * @param filePath 43 | * @return 44 | */ 45 | public static Document getDocument(String filePath){ 46 | if (!new File(filePath).exists()) { 47 | System.out.println(filePath + " is not exist!"); 48 | return null; 49 | } 50 | FileInputStream fis = null; 51 | try { 52 | fis = new FileInputStream(filePath); 53 | } catch (FileNotFoundException e) { 54 | System.out.println(e.getMessage()); 55 | } 56 | return getDocument(fis); 57 | } 58 | 59 | /** 60 | * 根据输入流读取对应的Document对象 61 | * @param input 62 | * @return 63 | */ 64 | public static Document getDocument(InputStream input){ 65 | Document document = null; 66 | if (input != null) { 67 | try { 68 | 69 | SAXReader saxReader = new SAXReader(); 70 | saxReader.setEncoding(CommonConstants.ENCODING_UTF8); 71 | DocumentFactory df = new DocumentFactory(); 72 | Map map = new HashMap(); 73 | df.setXPathNamespaceURIs(map); 74 | saxReader.setDocumentFactory(df); 75 | document = saxReader.read(input); 76 | if (document.getRootElement().getNamespace() != Namespace.NO_NAMESPACE) { 77 | nameSpace="nameSpace"; 78 | nameSpacePrefix=nameSpace+":"; 79 | map.put(nameSpace, document.getRootElement().getNamespace().getURI()); 80 | } 81 | } catch (Exception e) { 82 | System.out.println(e.getMessage()); 83 | } finally { 84 | if (input != null) { 85 | try { 86 | input.close(); 87 | } catch (IOException e) { 88 | System.out.println(e.getMessage()); 89 | } 90 | } 91 | } 92 | } 93 | return document; 94 | } 95 | 96 | 97 | /** 98 | * 将文档内容持久化到文件 99 | * @param document 100 | * @param filePath 101 | */ 102 | public static void writeDocument(Document document, String filePath) { 103 | writeDocument(document, new File(filePath)); 104 | } 105 | 106 | /** 107 | * 将文档内容持久化到文件 108 | * @param document 109 | * @param file 110 | */ 111 | public static void writeDocument(Document document, File file) { 112 | try { 113 | OutputFormat format = OutputFormat.createPrettyPrint(); 114 | format.setEncoding(CommonConstants.ENCODING_UTF8); 115 | FileOutputStream fos = new FileOutputStream(file); 116 | XMLWriter output = new XMLWriter(fos, format); 117 | output.write(document); 118 | output.close(); 119 | } catch (IOException e) { 120 | e.printStackTrace(); 121 | } 122 | } 123 | 124 | /** 125 | * 根据XPath获取查询结果列表集合 126 | * @param file 127 | * @param xpath 128 | * @return List 129 | */ 130 | @SuppressWarnings("rawtypes") 131 | public static List selectNodes(String file, String xpath) { 132 | return selectNodes(new File(file), xpath); 133 | } 134 | 135 | /** 136 | * 根据XPath获取查询结果列表集合 137 | * @param file 138 | * @param xpath 139 | * @return List 140 | */ 141 | @SuppressWarnings("rawtypes") 142 | public static List selectNodes(File file, String xpath) { 143 | List nodeList = new ArrayList(); 144 | if (file.exists()) { 145 | Document document = getDocument(file); 146 | xpath=translateXPath(xpath); 147 | if (document != null) { 148 | nodeList =document.selectNodes(xpath); 149 | } 150 | } 151 | return nodeList; 152 | } 153 | /**转换成带有命名空间前缀的路径**/ 154 | public static String translateXPath(String xPath){ 155 | String newXPath=""; 156 | if(!StringUtils.isEmpty(nameSpace)){ 157 | int i=xPath.lastIndexOf("/"); 158 | while(xPath.length()>1){ 159 | newXPath="/"+nameSpace+":"+xPath.substring(i+1,xPath.length())+newXPath; 160 | xPath=xPath.substring(0, i); 161 | i=xPath.lastIndexOf("/"); 162 | } 163 | }else{ 164 | newXPath=xPath; 165 | } 166 | 167 | return newXPath; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/utils/IOUtils.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.utils; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | 6 | /** 7 | * IO相关工具类 8 | * @author Louis 9 | * @date Oct 29, 2018 10 | */ 11 | public class IOUtils { 12 | 13 | /** 14 | * 关闭对象,连接 15 | * @param closeable 16 | */ 17 | public static void closeQuietly(final Closeable closeable) { 18 | try { 19 | if (closeable != null) { 20 | closeable.close(); 21 | } 22 | } catch (final IOException ioe) { 23 | // ignore 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/utils/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.utils; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * 反射相关辅助方法 8 | * @author pyy 9 | */ 10 | public class ReflectionUtils { 11 | 12 | 13 | /** 14 | * 根据方法名调用指定对象的方法 15 | * @param object 要调用方法的对象 16 | * @param method 要调用的方法名 17 | * @param args 参数对象数组 18 | * @return 19 | */ 20 | public static Object invoke(Object object, String method, Object... args) { 21 | Object result = null; 22 | Class clazz = object.getClass(); 23 | Method queryMethod = getMethod(clazz, method, args); 24 | if(queryMethod != null) { 25 | try { 26 | result = queryMethod.invoke(object, args); 27 | } catch (IllegalAccessException e) { 28 | e.printStackTrace(); 29 | } catch (IllegalArgumentException e) { 30 | e.printStackTrace(); 31 | } catch (InvocationTargetException e) { 32 | e.printStackTrace(); 33 | } 34 | } else { 35 | try { 36 | throw new NoSuchMethodException(clazz.getName() + " 类中没有找到 " + method + " 方法。"); 37 | } catch (NoSuchMethodException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | return result; 42 | } 43 | 44 | /** 45 | * 根据方法名和参数对象查找方法 46 | * @param clazz 47 | * @param name 48 | * @param args 参数实例数据 49 | * @return 50 | */ 51 | public static Method getMethod(Class clazz, String name, Object[] args) { 52 | Method queryMethod = null; 53 | Method[] methods = clazz.getMethods(); 54 | for(Method method:methods) { 55 | if(method.getName().equals(name)) { 56 | Class[] parameterTypes = method.getParameterTypes(); 57 | if(parameterTypes.length == args.length) { 58 | boolean isSameMethod = true; 59 | for(int i=0; i 7 | * SnowFlake的结构如下(每部分用-分开):
8 | * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
9 | * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
10 | * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) 11 | * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
12 | * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
13 | * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
14 | * 加起来刚好64位,为一个Long型。
15 | * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 16 | * @author : pyy 17 | * @createTime : 2019-05-27 10:49:27 18 | */ 19 | public class SnowflakeId { 20 | 21 | // ==============================Fields=========================================== 22 | /** 23 | * 开始时间截 (2015-01-01) 24 | */ 25 | private static final long TWEPOCH = 1420041600000L; 26 | 27 | /** 28 | * 机器id所占的位数 29 | */ 30 | private static final long WORKER_ID_BITS = 5L; 31 | 32 | /** 33 | * 数据标识id所占的位数 34 | */ 35 | private static final long DATA_CENTER_ID_BITS = 5L; 36 | 37 | /** 38 | * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) 39 | */ 40 | private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS); 41 | 42 | /** 43 | * 支持的最大数据标识id,结果是31 44 | */ 45 | private static final long MAX_DATA_CENTER_ID = -1L ^ (-1L << DATA_CENTER_ID_BITS); 46 | 47 | /** 48 | * 序列在id中占的位数 49 | */ 50 | private static final long SEQUENCE_BITS = 12L; 51 | 52 | /** 53 | * 机器ID向左移12位 54 | */ 55 | private static final long WORKER_ID_SHIFT = SEQUENCE_BITS; 56 | 57 | /** 58 | * 数据标识id向左移17位(12+5) 59 | */ 60 | private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; 61 | 62 | /** 63 | * 时间截向左移22位(5+5+12) 64 | */ 65 | private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS; 66 | 67 | /** 68 | * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) 69 | */ 70 | private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS); 71 | 72 | /** 73 | * 工作机器ID(0~31) 74 | */ 75 | private static long workerId; 76 | 77 | /** 78 | * 数据中心ID(0~31) 79 | */ 80 | private static long datacenterId; 81 | 82 | /** 83 | * 毫秒内序列(0~4095) 84 | */ 85 | private static long sequence = 0L; 86 | 87 | /** 88 | * 上次生成ID的时间截 89 | */ 90 | private static long lastTimestamp = -1L; 91 | 92 | //==============================Constructors===================================== 93 | 94 | public SnowflakeId() { 95 | } 96 | 97 | 98 | public static SnowflakeId getInstance(){ 99 | int workerId=new Random().nextInt(30); 100 | int datacenterId=new Random().nextInt(30); 101 | return new SnowflakeId(workerId,datacenterId); 102 | } 103 | 104 | 105 | /** 106 | * 构造函数 107 | * 108 | * @param workerId 工作ID (0~31) 109 | * @param datacenterId 数据中心ID (0~31) 110 | */ 111 | private SnowflakeId(long workerId, long datacenterId) { 112 | if (workerId > MAX_WORKER_ID || workerId < 0) { 113 | throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID)); 114 | } 115 | if (datacenterId > MAX_DATA_CENTER_ID || datacenterId < 0) { 116 | throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", MAX_DATA_CENTER_ID)); 117 | } 118 | SnowflakeId.workerId = workerId; 119 | SnowflakeId.datacenterId = datacenterId; 120 | } 121 | 122 | // ==============================Methods========================================== 123 | 124 | /** 125 | * 获得下一个ID (该方法是线程安全的) 126 | * 127 | * @return SnowflakeId 128 | */ 129 | public static synchronized long getId() { 130 | long timestamp = timeGen(); 131 | 132 | //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 133 | if (timestamp < lastTimestamp) { 134 | throw new RuntimeException( 135 | String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 136 | } 137 | 138 | //如果是同一时间生成的,则进行毫秒内序列 139 | if (lastTimestamp == timestamp) { 140 | sequence = (sequence + 1) & SEQUENCE_MASK; 141 | //毫秒内序列溢出 142 | if (sequence == 0) { 143 | //阻塞到下一个毫秒,获得新的时间戳 144 | timestamp = tilNextMillis(lastTimestamp); 145 | } 146 | } 147 | //时间戳改变,毫秒内序列重置 148 | else { 149 | sequence = 0L; 150 | } 151 | 152 | //上次生成ID的时间截 153 | lastTimestamp = timestamp; 154 | 155 | //移位并通过或运算拼到一起组成64位的ID 156 | return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) 157 | | (datacenterId << DATA_CENTER_ID_SHIFT) 158 | | (workerId << WORKER_ID_SHIFT) 159 | | sequence; 160 | } 161 | 162 | /** 163 | * 阻塞到下一个毫秒,直到获得新的时间戳 164 | * 165 | * @param lastTimestamp 上次生成ID的时间截 166 | * @return 当前时间戳 167 | */ 168 | protected static long tilNextMillis(long lastTimestamp) { 169 | long timestamp = timeGen(); 170 | while (timestamp <= lastTimestamp) { 171 | timestamp = timeGen(); 172 | } 173 | return timestamp; 174 | } 175 | 176 | /** 177 | * 返回以毫秒为单位的当前时间 178 | * 179 | * @return 当前时间(毫秒) 180 | */ 181 | protected static long timeGen() { 182 | return System.currentTimeMillis(); 183 | } 184 | 185 | public static void main(String[] args) { 186 | Long i = getId(); 187 | 188 | System.out.println(i); 189 | } 190 | 191 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.utils; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * 字符串工具类 8 | * 9 | * @author Louis 10 | * @date Nov 10, 2018 11 | */ 12 | public class StringUtils extends org.apache.commons.lang3.StringUtils{ 13 | 14 | private static Pattern linePattern = Pattern.compile("_(\\w)"); 15 | private static Pattern humpPattern = Pattern.compile("[A-Z]"); 16 | 17 | /** 18 | * 判空操作 19 | * 20 | * @param value 21 | * @return 22 | */ 23 | public static boolean isEmpty(String value) { 24 | return value == null || "".equals(value) || "null".equals(value) || "undefined".equals(value); 25 | } 26 | 27 | /** 28 | * 下划线转驼峰 29 | * 30 | * @param str 31 | * @return 32 | */ 33 | public static String lineToHump(String str) { 34 | str = str.toLowerCase(); 35 | Matcher matcher = linePattern.matcher(str); 36 | StringBuffer sb = new StringBuffer(); 37 | while (matcher.find()) { 38 | matcher.appendReplacement(sb, matcher.group(1).toUpperCase()); 39 | } 40 | matcher.appendTail(sb); 41 | return sb.toString(); 42 | } 43 | 44 | /** 45 | * 驼峰转下划线,效率比上面高 46 | * 47 | * @param str 48 | * @return 49 | */ 50 | public static String humpToLine(String str) { 51 | Matcher matcher = humpPattern.matcher(str); 52 | StringBuffer sb = new StringBuffer(); 53 | while (matcher.find()) { 54 | matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase()); 55 | } 56 | matcher.appendTail(sb); 57 | return sb.toString(); 58 | } 59 | 60 | /** 61 | * 首字母转小写 62 | * @param str 63 | * @return 64 | */ 65 | public static String uncapitalize(String str) { 66 | if (Character.isLowerCase(str.charAt(0))) 67 | return str; 68 | else 69 | return (new StringBuilder()).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString(); 70 | } 71 | 72 | /** 73 | * 首字母转大写 74 | * @param str 75 | * @return 76 | */ 77 | public static String capitalize(String str) { 78 | if (Character.isUpperCase(str.charAt(0))) 79 | return str; 80 | else 81 | return (new StringBuilder()).append(Character.toUpperCase(str.charAt(0))).append(str.substring(1)).toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/vo/ColumnModel.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 代码生成模型-字段 8 | * Author:pyy 9 | * Date:2019-9-26 09:39:40 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class ColumnModel { 15 | 16 | /** 属性名 */ 17 | private String fieldName; 18 | /** Java类型 */ 19 | private String javaType; 20 | /** jdbc类型 */ 21 | private String jdbcType; 22 | /** 是否主键 */ 23 | private boolean isPrimaryKey; 24 | /** getter名称 */ 25 | private String getter; 26 | /** setter名称 */ 27 | private String setter; 28 | /** 字段名 */ 29 | private String name; 30 | /** 表名称 */ 31 | private String tableName; 32 | /** 数据类型 */ 33 | private String dataType; 34 | /** 是否可空 */ 35 | private boolean isNullable; 36 | /** 默认值 */ 37 | private String defaultValue; 38 | /** 长度 */ 39 | private String length; 40 | /** 小数位 */ 41 | private String precision; 42 | /** 描述 */ 43 | private String description; 44 | } 45 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/vo/ConnParam.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * ======================== 9 | * 数据库连接参数封装 10 | * Author:pyy 11 | * Date:2019-9-25 16:07:53 12 | * Version: v1.0 13 | * ======================== 14 | */ 15 | @Data 16 | public class ConnParam implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | /** 21 | * 数据库类型 22 | */ 23 | private String dbType; 24 | /** 25 | * 数据库地址 26 | */ 27 | private String host; 28 | /** 29 | * 数据库端口 30 | */ 31 | private int port; 32 | /** 33 | * 数据库实例名 34 | */ 35 | private String dbName; 36 | /** 37 | * 用户名 38 | */ 39 | private String userName; 40 | /** 41 | * 密码 42 | */ 43 | private String password; 44 | 45 | 46 | public ConnParam() {} 47 | 48 | /** 49 | * @param host 50 | * @param port 51 | * @param dbName 52 | * @param userName 53 | * @param password 54 | */ 55 | public ConnParam(String dbType, String host, int port, String dbName, String userName, String password) { 56 | super(); 57 | this.dbType = dbType; 58 | this.host = host; 59 | this.port = port; 60 | this.dbName = dbName; 61 | this.userName = userName; 62 | this.password = password; 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/vo/GenerateModel.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * ======================== 10 | * 代码生成数据模型 11 | * Author:pyy 12 | * Date:2019-9-26 09:40:12 13 | * Version: v1.0 14 | * ======================== 15 | */ 16 | @Data 17 | public class GenerateModel { 18 | 19 | private String author; 20 | private String outPutFolderPath; 21 | private String basePackage = "com.thtf.output"; 22 | private ConnParam connParam; 23 | private List tableModels = new ArrayList<>(); 24 | } 25 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/vo/RequestParam.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * ======================== 7 | * 查询参数封装 8 | * Author:pyy 9 | * Date:2019-9-25 16:22:22 10 | * Version: v1.0 11 | * ======================== 12 | */ 13 | @Data 14 | public class RequestParam extends ConnParam { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private String tableName; 19 | } 20 | -------------------------------------------------------------------------------- /thtf-generator/src/main/java/com/thtf/generator/vo/TableModel.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * ======================== 11 | * 代码生成模型-表 12 | * Author:pyy 13 | * Date:2019-9-26 09:41:06 14 | * Version: v1.0 15 | * ======================== 16 | */ 17 | @Data 18 | public class TableModel { 19 | 20 | /** 作者 */ 21 | private String author; 22 | /** Model包名 */ 23 | private String modelPackageName; 24 | /** VO包名 */ 25 | private String voPackageName; 26 | /** Dao包名 */ 27 | private String daoPackageName; 28 | /** SqlMap xml包名 */ 29 | private String sqlMapPackageName; 30 | /** Servcie包名 */ 31 | private String servicePackageName; 32 | /** ServcieImpl包名 */ 33 | private String serviceImplPackageName; 34 | /** Controller包名 */ 35 | private String controllerPackageName; 36 | /** View目录名 */ 37 | private String viewPackageName; 38 | /** 类名 */ 39 | private String className; 40 | /** 实例名 */ 41 | private String objectName; 42 | /** 主键列 */ 43 | private ColumnModel primaryKey; 44 | 45 | /** 表名 */ 46 | private String name; 47 | /** 描述 */ 48 | private String description; 49 | /** 表空间 */ 50 | private String tablespace; 51 | /** 索引字段列表 */ 52 | private List columns = new ArrayList(); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 8899 4 | servlet: 5 | context-path: /thtf-generator 6 | spring: 7 | application: 8 | name: thtf-generator 9 | datasource: 10 | driver-class-name: com.mysql.jdbc.Driver 11 | url: jdbc:mysql://localhost:3306/pyy_auth?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8 12 | username: root 13 | password: 123456 14 | beetl: 15 | templatesPath: templates 16 | logging: 17 | level: 18 | com.louis: debug 19 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _____ _____ _____ _____ 2 | /\ \ /\ \ /\ \ /\ \ 3 | /::\ \ /::\____\ /::\ \ /::\ \ 4 | \:::\ \ /:::/ / \:::\ \ /::::\ \ 5 | \:::\ \ /:::/ / \:::\ \ /::::::\ \ 6 | \:::\ \ /:::/ / \:::\ \ /:::/\:::\ \ 7 | \:::\ \ /:::/____/ \:::\ \ /:::/__\:::\ \ 8 | /::::\ \ /::::\ \ /::::\ \ /::::\ \:::\ \ 9 | /::::::\ \ /::::::\ \ _____ /::::::\ \ /::::::\ \:::\ \ 10 | /:::/\:::\ \ /:::/\:::\ \ /\ \ /:::/\:::\ \ /:::/\:::\ \:::\ \ 11 | /:::/ \:::\____\/:::/ \:::\ /::\____\ /:::/ \:::\____\/:::/ \:::\ \:::\____\ 12 | /:::/ \::/ /\::/ \:::\ /:::/ / /:::/ \::/ /\::/ \:::\ \::/ / 13 | /:::/ / \/____/ \/____/ \:::\/:::/ / /:::/ / \/____/ \/____/ \:::\ \/____/ 14 | /:::/ / \::::::/ / /:::/ / \:::\ \ 15 | /:::/ / \::::/ / /:::/ / \:::\____\ 16 | \::/ / /:::/ / \::/ / \::/ / 17 | \/____/ /:::/ / \/____/ \/____/ 18 | /:::/ / 19 | /:::/ / 20 | \::/ / 21 | \/____/ -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/commonVO.btl: -------------------------------------------------------------------------------- 1 | package ${table.modelPackageName}; 2 | 3 | import io.swagger.annotations.ApiModelProperty; 4 | import lombok.Data; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * --------------------------- 10 | * 公共VO字段 11 | * --------------------------- 12 | * 作者: ${table.author} 13 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 14 | * 版本: v1.0 15 | * --------------------------- 16 | */ 17 | @Data 18 | @ApiModel(value = "CommonVO",description = "通用VO类") 19 | public class CommonVO { 20 | 21 | @ApiModelProperty("创建人ID") 22 | private String createId; 23 | 24 | @ApiModelProperty("创建人名称") 25 | private String createName; 26 | 27 | @ApiModelProperty("创建时间") 28 | private Date createTime; 29 | 30 | @ApiModelProperty("修改人ID") 31 | private String updateId; 32 | 33 | @ApiModelProperty("修改人名称") 34 | private String updateName; 35 | 36 | @ApiModelProperty("修改时间") 37 | private Date updateTime; 38 | 39 | @ApiModelProperty("删除标记: 1删除 0未删除") 40 | private Integer isDeleted; 41 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/controller.btl: -------------------------------------------------------------------------------- 1 | package ${table.controllerPackageName}; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import com.louis.kitty.core.http.HttpResult; 14 | import com.louis.kitty.core.page.PageRequest; 15 | import org.springframework.http.MediaType; 16 | import io.swagger.annotations.Api; 17 | import io.swagger.annotations.ApiImplicitParam; 18 | import io.swagger.annotations.ApiImplicitParams; 19 | import io.swagger.annotations.ApiOperation; 20 | import javax.validation.Valid; 21 | import javax.validation.constraints.NotBlank; 22 | import ${table.modelPackageName}.${table.className}; 23 | import ${table.servicePackageName}.${table.className}Service; 24 | 25 | /** 26 | * --------------------------- 27 | * ${table.description} (${table.className}Controller) 28 | * --------------------------- 29 | * 作者: ${table.author} 30 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 31 | * 版本: v1.0 32 | * --------------------------- 33 | */ 34 | @Api(tags = "${table.className}Controller", description = "${table.description}相关接口") 35 | @RestController 36 | @RequestMapping(value = "/v1", produces = MediaType.APPLICATION_JSON_UTF8_VALUE ) 37 | public class ${table.className}Controller { 38 | 39 | @Autowired 40 | private ${table.className}Service ${table.objectName}Service; 41 | 42 | /** 43 | * 保存${table.description} 44 | * @param record 45 | * @return 46 | */ 47 | @ApiOperation(value = "保存${table.description}", notes = "创建新${table.description}") 48 | @ApiImplicitParam(name = "record", value = "${table.description}对象", required = true, dataType = "${table.className}", paramType = "body") 49 | @PostMapping("/${table.objectName}") 50 | public Result save(@Valid @RequestBody ${table.className}SaveOrUpdateVO record) { 51 | ${table.objectName}Service.save(record); 52 | return Result.SUCCESS(); 53 | } 54 | 55 | /** 56 | * 修改${table.description} 57 | * @param id 58 | * @param record 59 | * @return 60 | */ 61 | @ApiOperation(value = "修改${table.description}", notes = "根据ID修改${table.description}") 62 | @ApiImplicitParams({ 63 | @ApiImplicitParam(name = "id", value = "${table.description}ID", required = true, dataType = "String", paramType = "path"), 64 | @ApiImplicitParam(name = "record", value = "${table.description}对象", required = true, dataType = "${table.className}", paramType = "body") 65 | }) 66 | @PutMapping("/${table.objectName}/{id}") 67 | public Result update(@Valid @PathVariable(value = "id") String id, @RequestBody ${table.className}SaveOrUpdateVO record) { 68 | ${table.objectName}Service.update(id, record); 69 | return Result.SUCCESS(); 70 | } 71 | 72 | /** 73 | * 删除${table.description} 74 | * @param id 75 | * @return 76 | */ 77 | @ApiOperation(value = "删除${table.description}", notes = "根据ID${table.description}") 78 | @ApiImplicitParam(name = "id", value = "${table.description}ID", required = true, dataType = "String", paramType = "path") 79 | @DeleteMapping("/${table.objectName}/{id}") 80 | public Result delete(@Valid @PathVariable(value = "id") String id) { 81 | ${table.objectName}Service.delete(id); 82 | return Result.SUCCESS(); 83 | } 84 | 85 | /** 86 | * 根据ID查询${table.description} 87 | * @param ${table.primaryKey.fieldName} 88 | * @return 89 | */ 90 | @ApiOperation(value = "${table.description}查询", notes = "根据ID${table.description}查询") 91 | @ApiImplicitParam(name = "id", value = "${table.description}ID", required = true, dataType = "String", paramType = "path") 92 | @GetMapping("/${table.objectName}") 93 | public Result<${table.className}VO> findById(@Valid @PathVariable(value = "id") String id) { 94 | ${table.className}VO queryResult = ${table.objectName}Service.findById(id); 95 | return Result.SUCCESS(queryResult); 96 | } 97 | 98 | /** 99 | * ${table.description}模糊查询 100 | * @param queryConditionVO 101 | * @return 102 | */ 103 | @ApiOperation(value = "${table.description}模糊查询", notes = "${table.description}不带分页模糊查询") 104 | @GetMapping("/${table.objectName}s") 105 | public Result> listByParams(${table.className}QueryConditionVO queryConditionVO) { 106 | List<${table.className}VO> queryResult = ${table.objectName}Service.listByParams(queryConditionVO); 107 | return Result.SUCCESS(queryResult); 108 | } 109 | 110 | /** 111 | * ${table.description}分页模糊查询 112 | * @param queryConditionVO 113 | * @param page 114 | * @param size 115 | * @return 116 | */ 117 | @ApiOperation(value = "${table.description}分页查询", notes = "${table.description}分页模糊查询") 118 | @ApiImplicitParams({ 119 | @ApiImplicitParam(name = "page", value = "当前页码", required = true, dataType = "Integer", paramType = "query"), 120 | @ApiImplicitParam(name = "size", value = "分页尺寸", required = true, dataType = "Integer", paramType = "query") 121 | }) 122 | @GetMapping("/${table.objectName}s/page") 123 | public Result> listByPageAndParams(${table.className}QueryConditionVO queryConditionVO, 124 | @RequestParam(value = "page", defaultValue = "1") Integer page, 125 | @RequestParam(value = "size", defaultValue = "10") Integer size) { 126 | QueryResult<${table.className}VO> queryResult = ${table.objectName}Service.listByPageAndParams(queryConditionVO, page, size); 127 | return Result.SUCCESS(queryResult); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/listVO.btl: -------------------------------------------------------------------------------- 1 | package ${table.modelPackageName}; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * --------------------------- 9 | * ${table.description} (${table.className}) 10 | * --------------------------- 11 | * 作者: ${table.author} 12 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 13 | * 版本: v1.0 14 | * --------------------------- 15 | */ 16 | @Data 17 | @ApiModel(value = "${table.className}VO",description = "${table.description}类") 18 | public class ${table.className}VO { 19 | 20 | <% 21 | for(column in table.columns) { 22 | %> 23 | @ApiModelProperty("${column.description}") 24 | private ${column.javaType} ${column.fieldName}; 25 | <% 26 | } 27 | %> 28 | 29 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/mapper.btl: -------------------------------------------------------------------------------- 1 | package ${table.daoPackageName}; 2 | 3 | import java.util.List; 4 | 5 | import ${table.modelPackageName}.${table.className}; 6 | import tk.mybatis.mapper.common.Mapper; 7 | import ${table.voPackageName}.*; 8 | import ${table.modelPackageName}.*; 9 | 10 | /** 11 | * --------------------------- 12 | * ${table.description} (${table.className}Mapper) 13 | * --------------------------- 14 | * 作者: ${table.author} 15 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 16 | * 版本: v1.0 17 | * --------------------------- 18 | */ 19 | public interface ${table.className}Mapper extends Mapper<${table.className}>{ 20 | 21 | List<${table.className}> selectByPageAndParam(${table.className}QueryConditionVO queryConditionVO); 22 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/model.btl: -------------------------------------------------------------------------------- 1 | package ${table.modelPackageName}; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | 8 | /** 9 | * --------------------------- 10 | * ${table.description} (${table.className}) 11 | * --------------------------- 12 | * 作者: ${table.author} 13 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 14 | * 版本: v1.0 15 | * --------------------------- 16 | */ 17 | @Data 18 | @Table(name = "${table.name}") 19 | public class ${table.className} { 20 | 21 | <% 22 | for(column in table.columns) { 23 | 24 | if (column.isPrimaryKey) { 25 | %> 26 | /** ${column.description} */ 27 | @Id 28 | private ${column.javaType} ${column.fieldName}; 29 | <% 30 | } else { 31 | %> 32 | /** ${column.description} */ 33 | private ${column.javaType} ${column.fieldName}; 34 | <% 35 | } 36 | 37 | } 38 | %> 39 | 40 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/queryConditionVO.btl: -------------------------------------------------------------------------------- 1 | package ${table.modelPackageName}; 2 | 3 | import io.swagger.annotations.ApiModelProperty; 4 | import lombok.Data; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * --------------------------- 12 | * 模糊查询条件VO 13 | * --------------------------- 14 | * 作者: ${table.author} 15 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 16 | * 版本: v1.0 17 | * --------------------------- 18 | */ 19 | @Data 20 | @ApiModel(value = "${table.className}QueryConditionVO",description = "${table.description}查询条件类") 21 | public class ${table.className}QueryConditionVO { 22 | 23 | @ApiModelProperty("名称") 24 | private String name; 25 | 26 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/saveOrUpdateVO.btl: -------------------------------------------------------------------------------- 1 | package ${table.modelPackageName}; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * --------------------------- 9 | * ${table.description} (${table.className}) 10 | * --------------------------- 11 | * 作者: ${table.author} 12 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 13 | * 版本: v1.0 14 | * --------------------------- 15 | */ 16 | @Data 17 | @ApiModel(value = "${table.className}SaveOrUpdateVO",description = "${table.description}保存和修改VO类") 18 | public class ${table.className}SaveOrUpdateVO { 19 | 20 | <% 21 | for(column in table.columns) { 22 | %> 23 | @ApiModelProperty("${column.description}") 24 | private ${column.javaType} ${column.fieldName}; 25 | <% 26 | } 27 | %> 28 | 29 | } -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/service.btl: -------------------------------------------------------------------------------- 1 | package ${table.servicePackageName}; 2 | 3 | import ${table.modelPackageName}.${table.className}; 4 | 5 | /** 6 | * --------------------------- 7 | * ${table.description} (${table.className}Service) 8 | * --------------------------- 9 | * 作者: ${table.author} 10 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 11 | * 版本: v1.0 12 | * --------------------------- 13 | */ 14 | public interface ${table.className}Service { 15 | 16 | /** 17 | * ${table.description}保存 18 | * @param ${table.objectName}SaveOrUpdateVO 19 | */ 20 | public void save(${table.className}SaveOrUpdateVO ${table.objectName}SaveOrUpdateVO); 21 | 22 | /** 23 | * ${table.description}修改 24 | * @param id 25 | * @param ${table.objectName}SaveOrUpdateVO 26 | */ 27 | public void update(${table.primaryKey.javaType} id, ${table.className}SaveOrUpdateVO ${table.objectName}SaveOrUpdateVO); 28 | 29 | /** 30 | * ${table.description}删除 31 | * @param id 32 | * @param userId 33 | * @param username 34 | */ 35 | public void delete(${table.primaryKey.javaType} id, String userId, String username); 36 | 37 | /** 38 | * 根据${table.description}ID查询 39 | * @param id 40 | */ 41 | public ${table.className}VO findById(${table.primaryKey.javaType} id); 42 | 43 | /** 44 | * ${table.description}模糊查询 45 | * @param queryConditionVO 46 | * @return 47 | */ 48 | public List<${table.className}VO> listByParams(${table.className}QueryConditionVO queryConditionVO); 49 | 50 | 51 | /** 52 | * ${table.description}分页模糊查询 53 | * @param queryConditionVO 54 | * @param page 55 | * @param size 56 | * @return 57 | */ 58 | public QueryResult<${table.className}VO> listByPageAndParams(${table.className}QueryConditionVO queryConditionVO, Integer page, Integer size); 59 | } 60 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/serviceImpl.btl: -------------------------------------------------------------------------------- 1 | package ${table.serviceImplPackageName}; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.github.pagehelper.PageHelper; 5 | import com.github.pagehelper.PageInfo; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.BeanUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Isolation; 11 | import org.springframework.transaction.annotation.Propagation; 12 | import org.springframework.transaction.annotation.Transactional; 13 | import org.springframework.util.CollectionUtils; 14 | import tk.mybatis.mapper.entity.Example; 15 | 16 | import java.sql.Timestamp; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | 21 | 22 | import ${table.modelPackageName}.*; 23 | import ${table.voPackageName}.*; 24 | import ${table.daoPackageName}.${table.className}Mapper; 25 | 26 | /** 27 | * --------------------------- 28 | * ${table.description} (${table.className}ServiceImpl) 29 | * --------------------------- 30 | * 作者: ${table.author} 31 | * 时间: ${strutil.formatDate(date(),'yyyy-MM-dd HH:mm:ss')} 32 | * 版本: v1.0 33 | * --------------------------- 34 | */ 35 | @Slf4j 36 | @Service 37 | @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class) 38 | public class ${table.className}ServiceImpl implements ${table.className}Service { 39 | 40 | @Autowired 41 | private ${table.className}Mapper ${table.objectName}Mapper; 42 | 43 | /** 44 | * ${table.description}保存 45 | * @param ${table.objectName}SaveOrUpdateVO 46 | */ 47 | @Override 48 | public void save(${table.className}SaveOrUpdateVO ${table.objectName}SaveOrUpdateVO) { 49 | // 保存${table.description} 50 | ${table.className} ${table.objectName}Model = new ${table.className}(); 51 | BeanUtils.copyProperties(${table.objectName}SaveOrUpdateVO, ${table.objectName}Model); 52 | ${table.objectName}Model.setId(SnowflakeId.getId() + ""); 53 | ${table.objectName}Model.setCreateId(UserUtil.getUserId()); 54 | ${table.objectName}Model.setCreateName(UserUtil.getUsername()); 55 | ${table.objectName}Model.setCreateTime(new Timestamp(System.currentTimeMillis())); 56 | ${table.objectName}Model.setDeleteFlag(Constants.UN_DELETED); 57 | 58 | ${table.objectName}Mapper.insert(${table.objectName}Model); 59 | log.info("### ${table.description}保存成功 ###"); 60 | } 61 | 62 | /** 63 | * ${table.description}修改 64 | * @param id 65 | * @param ${table.objectName}SaveOrUpdateVO 66 | */ 67 | @Override 68 | public void update(${table.primaryKey.javaType} id, ${table.className}SaveOrUpdateVO ${table.objectName}SaveOrUpdateVO) { 69 | // 1.根据ID查询${table.description} 70 | ${table.className} ${table.objectName}Model = ${table.objectName}Mapper.selectByPrimaryKey(id); 71 | if (${table.objectName}Model == null) { 72 | throw new CustomException(ResultCode.RESULT_DATA_NONE, "${table.description}"); 73 | } 74 | 75 | // 2.设置${table.description}属性 76 | BeanUtils.copyProperties(${table.objectName}SaveOrUpdateVO, ${table.objectName}Model); 77 | ${table.objectName}Model.setUpdateId(UserUtil.getUserId()); 78 | ${table.objectName}Model.setUpdateName(UserUtil.getUsername()); 79 | ${table.objectName}Model.setUpdateTime(new Timestamp(System.currentTimeMillis())); 80 | 81 | // 3.更新${table.description} 82 | ${table.objectName}Mapper.updateByPrimaryKey(${table.objectName}Model); 83 | log.info("### ${table.description}修改成功 ###"); 84 | } 85 | 86 | /** 87 | * ${table.description}删除 88 | * @param id 89 | */ 90 | @Override 91 | public void delete(${table.primaryKey.javaType} id, String userId, String username) { 92 | ${table.className} ${table.objectName}Model = ${table.objectName}Mapper.selectByPrimaryKey(id); 93 | if (${table.objectName}Model == null) { 94 | throw new CustomException(ResultCode.RESULT_DATA_NONE, "${table.description},id=" + id); 95 | } 96 | 97 | // 逻辑删除 98 | ${table.objectName}Model.setId(id); 99 | ${table.objectName}Model.setUpdateId(userId); 100 | ${table.objectName}Model.setUpdateName(username); 101 | ${table.objectName}Model.setUpdateTime(new Timestamp(System.currentTimeMillis())); 102 | ${table.objectName}Model.setDeleteFlag(Constants.DELETED); 103 | 104 | ${table.objectName}Mapper.updateByPrimaryKeySelective(${table.objectName}Model); 105 | log.info("### ${table.description}逻辑删除成功 ###"); 106 | } 107 | 108 | /** 109 | * 根据${table.description}ID查询 110 | * @param id 111 | */ 112 | @Override 113 | public ${table.className}VO findById(${table.primaryKey.javaType} id) { 114 | ${table.className} ${table.objectName}Model = ${table.objectName}Mapper.selectByPrimaryKey(id); 115 | if (${table.objectName}Model == null) { 116 | throw new CustomException(ResultCode.RESULT_DATA_NONE, "${table.description},id=" + id); 117 | } 118 | log.info("### ${table.description}查询成功, ${table.objectName}={}###", JSON.toJSONString(${table.objectName}Model)); 119 | // model转换vo 120 | ${table.className}VO ${table.objectName}VO = new ${table.className}VO(); 121 | BeanUtils.copyProperties(${table.objectName}Model, ${table.objectName}VO); 122 | log.info("### ${table.description}Model转换VO成功, ${table.objectName}VO={}###", ${table.objectName}VO); 123 | return ${table.objectName}VO; 124 | } 125 | 126 | /** 127 | * ${table.description}模糊查询 128 | * @param queryConditionVO 129 | * @return 130 | */ 131 | @Override 132 | public List<${table.className}VO> listByParams(${table.className}QueryConditionVO queryConditionVO) { 133 | List<${table.className}> ${table.objectName}List = ${table.objectName}Mapper.selectByPageAndParam(queryConditionVO); 134 | log.info("### ${table.description}Model模糊查询完毕,总条数:{}条###", ${table.objectName}List.size()); 135 | 136 | // ${table.description}Model转换VO数据 137 | List<${table.className}VO> ${table.objectName}VOList = new ArrayList<>(); 138 | ${table.objectName}List.forEach(${table.objectName} -> { 139 | ${table.className}VO ${table.objectName}VO = new ${table.className}VO(); 140 | BeanUtils.copyProperties(${table.objectName}, ${table.objectName}VO); 141 | ${table.objectName}VOList.add(${table.objectName}VO); 142 | }); 143 | log.info("### ${table.description}Model转换VO数据完毕###"); 144 | 145 | return ${table.objectName}VOList; 146 | } 147 | 148 | /** 149 | * ${table.description}分页模糊查询 150 | * @param queryConditionVO 151 | * @param page 152 | * @param size 153 | * @return 154 | */ 155 | @Override 156 | public QueryResult<${table.className}VO> listByPageAndParams(${table.className}QueryConditionVO queryConditionVO, Integer page, Integer size) { 157 | // 分页查询 158 | PageHelper.startPage(page, size); 159 | List<${table.className}> ${table.objectName}List = ${table.objectName}Mapper.selectByPageAndParam(queryConditionVO); 160 | // 获取分页后数据 161 | PageInfo<${table.className}> pageInfo = new PageInfo<>(${table.objectName}List); 162 | log.info("### ${table.description}分页查询完毕,总条数:{} ###", pageInfo.getTotal()); 163 | 164 | List<${table.className}VO> ${table.objectName}VOList = new ArrayList<>(); 165 | // 补全数据 166 | ${table.objectName}List.forEach(${table.objectName} -> { 167 | ${table.className}VO ${table.objectName}VO = new ${table.className}VO(); 168 | BeanUtils.copyProperties(${table.objectName}, ${table.objectName}VO); 169 | ${table.objectName}VOList.add(${table.objectName}VO); 170 | }); 171 | log.info("### ${table.description}Model转换VO数据完毕###"); 172 | 173 | // 封装需要返回的实体数据 174 | QueryResult queryResult = new QueryResult(); 175 | queryResult.setTotal(pageInfo.getTotal()); 176 | queryResult.setList(${table.objectName}VOList); 177 | 178 | return queryResult; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/sqlMap.btl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <% 7 | for(column in table.columns) { 8 | if(column.isPrimaryKey) { 9 | %> 10 | 11 | <% 12 | } else { 13 | %> 14 | 15 | <% 16 | } 17 | } 18 | %> 19 | 20 | 21 | 22 | <% 23 | for(column in table.columns) { 24 | if (columnLP.last) { 25 | %> 26 | a.${column.name} 27 | <% 28 | } else { 29 | %> 30 | a.${column.name}, 31 | <% 32 | } 33 | } 34 | %> 35 | 36 | 37 | 38 | 49 | 50 | -------------------------------------------------------------------------------- /thtf-generator/src/main/resources/templates/view.btl: -------------------------------------------------------------------------------- 1 | 42 | 43 | 156 | 157 | -------------------------------------------------------------------------------- /thtf-generator/src/test/java/com/thtf/generator/ThtfGeneratorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.thtf.generator; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ThtfGeneratorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------