著區塊鏈技術的不斷發展和應用場景的日益豐富,智能合約已成為其中的重要一環。最近熱議的ERC404協議,作為下一代智能合約升級的一種可能,引起了廣泛關注。本文將深入探討ERC404協議的開發搭建及其作品內容,帶您領略其專業性和深度思考。
一、ERC404協議的背景介紹
ERC404是以太坊上用于智能合約升級的協議,旨在解決傳統智能合約升級方式中的痛點。與傳統智能合約部署一次、使用一輩子的模式不同,ERC404允許多次升級,從而為合約開發者提供了更大的靈活性和自由度。
二、ERC404協議的開發搭建
1. 開發環境:開發ERC404協議需要一定的編程知識和技能,熟悉以太坊底層技術和Solidity等編程語言。同時,需要選擇合適的集成開發環境(IDE),如Visual Studio Code、WebStorm等。
2. 協議設計:ERC404協議的設計需要遵循一定的規范和原則,如代碼簡潔、邏輯清晰、安全性高等。此外,還需要考慮異常處理、合約升級、跨鏈交互等問題。
3. 代碼編寫:代碼的編寫是實現ERC404協議的關鍵,需要進行充分測試和驗證,確保合約升級過程中的正確性和安全性。
三、作品內容解析
1. ERC404與合約升級:與傳統智能合約部署后無法升級的問題不同,ERC404提供了合約升級的可能。這將為合約開發者提供更大的靈活性和自由度,降低了合約開發和維護的成本。
2. 跨鏈交互:ERC404協議可以與其他區塊鏈上的智能合約進行跨鏈交互,從而實現更廣泛的業務場景和合作。這為區塊鏈技術的應用和發展提供了更多的可能性。
3. 安全性與隱私保護:由于智能合約的特殊性,安全性是重中之重。ERC404協議在設計過程中充分考慮了安全性問題,如采用公私鑰分離等機制,保護合約開發者的隱私。
四、深度思考與展望
1. 技術成熟度:盡管ERC404協議已經取得了初步的成功,但仍需進一步觀察其在實際應用中的表現,包括性能、穩定性和兼容性等方面。
2. 政策法規:政策法規是推動區塊鏈技術發展的關鍵因素之一。在推進ERC404協議的應用和發展過程中,需要關注相關政策法規的變化和影響。
3. 隱私保護與合規性:隨著區塊鏈技術的廣泛應用,隱私保護和合規性成為越來越重要的議題。未來,我們需要關注如何平衡隱私保護和合規性要求與技術進步之間的關系。
總結:ERC404協議作為下一代智能合約升級的一種可能,為區塊鏈技術的發展帶來了新的機遇和挑戰。通過深入了解其開發搭建和作品內容,我們可以更好地把握其專業性和深度思考,為未來的應用和發展提供更多可能性。
注開源中國OSC頭條號,獲取最新技術資訊
vue-cli是一個基于nodeJs、用于快速搭建vue項目的 腳手架。
安裝過nodeJs 、cnpm 后,全局安裝vue-cli(以后其他項目可直接使用):
cnpm install -g vue-cli
更新:
cnpm update vue-cli
查看安裝成功否(有版本號就是成功,V大寫)
vue -V
查看npm注冊表里vue-cli版本號:
cnpm view vue-cli
安裝過webpack 、vue-cli后,可以開始搭建vue項目:
vue init webpack <Project Name>
eg:右擊Git Base Here(如果你沒有用git ,你也可以按住shift鍵右擊選擇“在此處打開命令窗口”,或者 cmd :cd \project/lfxProject),如圖:
or
ps:ESLint(一個javascript代碼檢測工具)、unit tests(單元測試)、Nightwatch(一個e2e用戶界面測試工具)。
項目結構如下:
各文件作用解析,如下:
build文件夾的結構:
'use strict' require('./check-versions')() //調用版本檢查 process.env.NODE_ENV='production' //將環境配置為生產環境 const ora=require('ora') //npm包 loading插件 const rm=require('rimraf') //npm包 用于刪除文件 const path=require('path')//npm包 文件路徑工具 const chalk=require('chalk')//npm包 在終端輸出帶顏色的文字 const webpack=require('webpack')//引入webpack.js const config=require('../config')//引入配置文件 const webpackConfig=require('./webpack.prod.conf')//引入生產環境配置文件 // 在終端顯示loading效果,并輸出提示 const spinner=ora('building for production...') spinner.start() //先遞歸刪除dist文件再生成新文件,避免冗余 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err=> { if (err) throw err webpack(webpackConfig, (err, stats)=> { spinner.stop() if (err) throw err process.stdout.write(stats.toString({ colors: true, modules: false, children: false, chunks: false, chunkModules: false }) + '\n\n') if (stats.hasErrors()) { console.log(chalk.red(' Build failed with errors.\n')) process.exit(1) } console.log(chalk.cyan(' Build complete.\n')) console.log(chalk.yellow( ' Tip: built files are meant to be served over an HTTP server.\n' + ' Opening index.html over file:// won\'t work.\n' )) }) })
ps:require/export是一種nodeJs(commonJs規范)的依賴注入的方法,import/export是ES6語法,用于引入模塊,在nodeJs中使用的ES6語法最終會使用babel工具(babel-loader)轉化為ES5
'use strict' const chalk=require('chalk') const semver=require('semver')//檢查版本 const packageConfig=require('../package.json') const shell=require('shelljs')//shelljs 模塊重新包裝了 child_process,調用系統命令更加方便 function exec (cmd) {//返回通過child_process模塊的新建子進程,執行 Unix 系統命令后轉成沒有空格的字符串 return require('child_process').execSync(cmd).toString().trim() } const versionRequirements=[ { name: 'node', currentVersion: semver.clean(process.version),//使用semver格式化版本 versionRequirement: packageConfig.engines.node //獲取package.json中設置的node版本 } ] if (shell.which('npm')) { versionRequirements.push({ name: 'npm', currentVersion: exec('npm --version'),// 自動調用npm --version命令,并且把參數返回給exec函數,從而獲取純凈的版本號 versionRequirement: packageConfig.engines.npm }) } module.exports=function () { const warnings=[] for (let i=0; i < versionRequirements.length; i++) { const mod=versionRequirements[i] //若版本號不符合package.json文件中指定的版本號,就報錯 if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { warnings.push(mod.name + ': ' + chalk.red(mod.currentVersion) + ' should be ' + chalk.green(mod.versionRequirement) ) } } if (warnings.length) { console.log('') console.log(chalk.yellow('To use this template, you must update following to modules:')) console.log() for (let i=0; i < warnings.length; i++) { const warning=warnings[i] console.log(' ' + warning) } console.log() process.exit(1) } }
var path=require('path')// node自帶的文件路徑工具 var config=require('../config')// 配置文件 var ExtractTextPlugin=require('extract-text-webpack-plugin')// 提取css的插件 /** @method assertsPath 生成靜態資源的路徑(判斷開發環境和生產環境,為config文件中index.js文件中定義assetsSubDirectory) * @param {String} _path 相對于靜態資源文件夾的文件路徑 * @return {String} 靜態資源完整路徑 */ exports.assetsPath=function (_path) { var assetsSubDirectory=process.env.NODE_ENV==='production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory //nodeJs path提供用于處理文件路徑的工具;path.posix提供對路徑方法的POSIX(可移植性操作系統接口)特定實現的訪問(可跨平臺); path.posix.join與path.join一樣,不過總是以 posix 兼容的方式交互 return path.posix.join(assetsSubDirectory, _path) } /**@method cssLoaders 生成處理css的loaders配置,使用css-loader和postcssLoader,通過options.usePostCSS屬性來判斷是否使用postcssLoader中壓縮等方法 * @param {Object} option={sourceMap: true,// 是否開啟 sourceMapextract: true // 是否提取css}生成配置 * @return {Object} 處理css的loaders配置對象 */ exports.cssLoaders=function (options) { options=options || {} var cssLoader={ loader: 'css-loader', options: { minimize: process.env.NODE_ENV==='production', sourceMap: options.sourceMap } } /**@method generateLoaders 生成 ExtractTextPlugin對象或loader字符串 * @param {Array} loaders loader名稱數組 * @return {String|Object} ExtractTextPlugin對象或loader字符串 */ function generateLoaders (loader, loaderOptions) { var loaders=[cssLoader] if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // ExtractTextPlugin提取css(當上面的loaders未能正確引入時,使用vue-style-loader) if (options.extract) {// 生產環境中,默認為true return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else {//返回vue-style-loader連接loaders的最終值 return ['vue-style-loader'].concat(loaders) } } return { css: generateLoaders(),//需要css-loader 和 vue-style-loader postcss: generateLoaders(),//需要css-loader、postcssLoader 和 vue-style-loader less: generateLoaders('less'),//需要less-loader 和 vue-style-loader sass: generateLoaders('sass', { indentedSyntax: true }),//需要sass-loader 和 vue-style-loader scss: generateLoaders('sass'),//需要sass-loader 和 vue-style-loader stylus: generateLoaders('stylus'),//需要stylus-loader 和 vue-style-loader styl: generateLoaders('stylus')//需要stylus-loader 和 vue-style-loader } } /**@method styleLoaders 生成 style-loader的配置 * @param {Object} options 生成配置 * @return {Array} style-loader的配置 */ exports.styleLoaders=function (options) { var output=[] var loaders=exports.cssLoaders(options) //將各種css,less,sass等綜合在一起得出結果輸出output for (var extension in loaders) { var loader=loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) } return output }
'use strict' const utils=require('./utils') const config=require('../config') const isProduction=process.env.NODE_ENV==='production' //生產環境,提取css樣式到單獨文件 const sourceMapEnabled=isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap module.exports={ loaders: utils.cssLoaders({ sourceMap: sourceMapEnabled, extract: isProduction }), cssSourceMap: sourceMapEnabled, cacheBusting: config.dev.cacheBusting, //編譯時將“引入路徑”轉換為require調用,使其可由webpack處理 transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } }
'use strict' const path=require('path')// node自帶的文件路徑工具 const utils=require('./utils')// 工具函數集合 const config=require('../config')// 配置文件 const vueLoaderConfig=require('./vue-loader.conf')// 工具函數集合 /** * 獲取"絕對路徑" * @method resolve * @param {String} dir 相對于本文件的路徑 * @return {String} 絕對路徑 */ function resolve(dir) { return path.join(__dirname, '..', dir) } module.exports={ context: path.resolve(__dirname, '../'), //入口js文件(默認為單頁面所以只有app一個入口) entry: { app: './src/main.js' }, //配置出口 output: { path: config.build.assetsRoot,//打包編譯的根路徑(dist) filename: '[name].js', publicPath: process.env.NODE_ENV==='production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath//發布路徑 }, resolve: { extensions: ['.js', '.vue', '.json'],// 自動補全的擴展名 //別名配置 alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'),// eg:"src/components"=> "@/components" } }, module: { rules: [ //使用vue-loader將vue文件編譯轉換為js { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, //通過babel-loader將ES6編譯壓縮成ES5 { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] }, //使用url-loader處理(圖片、音像、字體),超過10000編譯成base64 { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('media/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, //nodeJs全局變量/模塊,防止webpack注入一些nodeJs的東西到vue中 node: { setImmediate: false, dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } }
'use strict' const utils=require('./utils') const webpack=require('webpack') const config=require('../config') const merge=require('webpack-merge')//webpack-merge實現合并 const path=require('path') const baseWebpackConfig=require('./webpack.base.conf') const CopyWebpackPlugin=require('copy-webpack-plugin') const HtmlWebpackPlugin=require('html-webpack-plugin') const FriendlyErrorsPlugin=require('friendly-errors-webpack-plugin')//webpack的提示錯誤和日志信息的插件 const portfinder=require('portfinder')// 查看空閑端口位置,默認情況下搜索8000這個端口 const HOST=process.env.HOST const PORT=process.env.PORT && Number(process.env.PORT) const devWebpackConfig=merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }, devtool: config.dev.devtool,//調試模式 devServer: { clientLogLevel: 'warning', historyApiFallback: {//使用 HTML5 History API 時, 404 響應替代為 index.html rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, ], }, hot: true,//熱重載 contentBase: false, // 提供靜態文件訪問 compress: true,//壓縮 host: HOST || config.dev.host, port: PORT || config.dev.port, open: config.dev.autoOpenBrowser,//npm run dev 時自動打開瀏覽器 overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,// 顯示warning 和 error 信息 publicPath: config.dev.assetsPublicPath, proxy: config.dev.proxyTable,//api代理 quiet: true, //控制臺打印警告和錯誤(用FriendlyErrorsPlugin 為 true) watchOptions: {// 檢測文件改動 poll: config.dev.poll, } }, plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }), new webpack.HotModuleReplacementPlugin(),//模塊熱替換插件,修改模塊時不需要刷新頁面 new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. new webpack.NoEmitOnErrorsPlugin(),//webpack編譯錯誤的時候,中斷打包進程,防止錯誤代碼打包到文件中 // 將打包編譯好的代碼插入index.html new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), // 提取static assets 中css 復制到dist/static文件 new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.dev.assetsSubDirectory, ignore: ['.*']//忽略.*的文件 } ]) ] }) module.exports=new Promise((resolve, reject)=> { portfinder.basePort=process.env.PORT || config.dev.port portfinder.getPort((err, port)=> { //查找端口號 if (err) { reject(err) } else { //端口被占用時就重新設置evn和devServer的端口 process.env.PORT=port devWebpackConfig.devServer.port=port // npm run dev成功的友情提示 devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ compilationSuccessInfo: { messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], }, onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined })) resolve(devWebpackConfig) } }) })
'use strict' const path=require('path') const utils=require('./utils') const webpack=require('webpack') const config=require('../config') const merge=require('webpack-merge') const baseWebpackConfig=require('./webpack.base.conf') const CopyWebpackPlugin=require('copy-webpack-plugin') const HtmlWebpackPlugin=require('html-webpack-plugin') const ExtractTextPlugin=require('extract-text-webpack-plugin') const OptimizeCSSPlugin=require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin=require('uglifyjs-webpack-plugin') const env=require('../config/prod.env') const webpackConfig=merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, devtool: config.build.productionSourceMap ? config.build.devtool : false,//是否開啟調試模式 output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [ new webpack.DefinePlugin({ 'process.env': env }), new UglifyJsPlugin({//壓縮js uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }), new ExtractTextPlugin({//提取靜態文件,減少請求 filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: true, }), new OptimizeCSSPlugin({//提取優化壓縮后(刪除來自不同組件的冗余代碼)的css cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), new HtmlWebpackPlugin({ //html打包壓縮到index.html filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true,//刪除注釋 collapseWhitespace: true,//刪除空格 removeAttributeQuotes: true//刪除屬性的引號 }, chunksSortMode: 'dependency'//模塊排序,按照我們需要的順序排序 }), new webpack.HashedModuleIdsPlugin(), new webpack.optimize.ModuleConcatenationPlugin(), new webpack.optimize.CommonsChunkPlugin({ // node_modules中的任何所需模塊都提取到vendor name: 'vendor', minChunks (module) { return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') )===0 ) } }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity }), new webpack.optimize.CommonsChunkPlugin({ name: 'app', async: 'vendor-async', children: true, minChunks: 3 }), new CopyWebpackPlugin([//復制static中的靜態資源(默認到dist里面) { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] }) if (config.build.productionGzip) { const CompressionWebpackPlugin=require('compression-webpack-plugin') webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } if (config.build.bundleAnalyzerReport) { const BundleAnalyzerPlugin=require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports=webpackConfig
config文件夾的結構:
'use strict' const merge=require('webpack-merge') const prodEnv=require('./prod.env') module.exports=merge(prodEnv, { NODE_ENV: '"development"' })
ps:webpack-merge用于實現合并類似于ES6的Object.assign()
'use strict' module.exports={ NODE_ENV: '"production"' }
(*注意屬性值要用“‘’”雙層引住),訪問(獲取值)時直接用:
process.env.屬性名
ps:process(進程)是nodejs的一個全局變量,process.env 屬性返回一個用戶環境信息的對象
'use strict'; const path=require('path'); module.exports={ //===================開發環境配置 dev: { assetsSubDirectory: 'static',//靜態資源文件夾(一般存放css、js、image等文件) assetsPublicPath: '/',//根目錄 proxyTable: {},//配置API代理,可利用該屬性解決跨域的問題 host: 'localhost', // 可以被 process.env.HOST 覆蓋 port: 3030, // 可以被 process.env.PORT 覆蓋 autoOpenBrowser: true,//編譯后自動打開瀏覽器頁面 http://localhost:3030/("port + host",默認"false"),設置路由重定向自動打開您的默認頁面 errorOverlay: true,//瀏覽器錯誤提示 notifyOnErrors: true,//跨平臺錯誤提示 poll: false, //webpack提供的使用文件系統(file system)獲取文件改動的通知devServer.watchOptions(監控文件改動) devtool: 'cheap-module-eval-source-map',//webpack提供的用來調試的模式,有多個不同值代表不同的調試模式 cacheBusting: true,// 配合devtool的配置,當給文件名插入新的hash導致清除緩存時是否生成source-map cssSourceMap: true //記錄代碼壓縮前的位置信息,當產生錯誤時直接定位到未壓縮前的位置,方便調試 }, //========================生產環境配置 build: { index: path.resolve(__dirname, '../dist/index.html'),//編譯后"首頁面"生成的絕對路徑和名字 assetsRoot: path.resolve(__dirname, '../dist'),//打包編譯的根路徑(默認dist,存放打包壓縮后的代碼) assetsSubDirectory: 'static',//靜態資源文件夾(一般存放css、js、image等文件) assetsPublicPath: '/',//發布的根目錄(dist文件夾所在路徑) productionSourceMap: true,//是否開啟source-map devtool: '#source-map',//(詳細參見:https://webpack.docschina.org/configuration/devtool) productionGzip: false,//是否壓縮 productionGzipExtensions: ['js', 'css'],//unit的gzip命令用來壓縮文件(gzip模式下需要壓縮的文件的擴展名有js和css) bundleAnalyzerReport: process.env.npm_config_report //是否開啟打包后的分析報告 } };
(1)assets文件:用于存放靜態資源(css、image),assets打包時路徑會經過webpack中的file-loader編譯(因此,assets需要使用絕對路徑)成js
(2)components文件夾:用來存放 .vue 組件(實現復用等功能,如:過濾器,列表項等)
(3)router文件夾:在router/index.js文件中配置頁面路由
(4)App.vue:是整個項目的主組件,所有頁面都是通過使用<router-view/>開放入口在App.vue下進行切換的(所有的路由都是App.vue的子組件)
(5)main.js:入口js文件(全局js,你可以在這里:初始化vue實例、require/import需要的插件、注入router路由、引入store狀態管理)
(1).babelrc:瀏覽器解析的兼容配置,該文件主要是對預設(presets)和插件(plugins)進行配置,因此不同的轉譯器作用不同的配置項,大致可分為:語法轉義器、補丁轉義器、sx和flow插件
(2).editorconfig:用于配置代碼格式(配合代碼檢查工具使用,如:ESLint,團隊開發時可統一代碼風格),這里配置的代碼規范規則優先級高于編輯器默認的代碼格式化規則 。
(3).gitignore:配置git提交時需要忽略的文件
(4)postcssrc.js: autoprefixer(自動補全css樣式的瀏覽器前綴);postcss-import(@import引入語法)、CSS Modules(規定樣式作用域)
(5)index.html:項目入口頁面,編譯之后所有代碼將插入到這來
(6)package.json:npm的配置文件(npm install根據package.json下載對應版本的安裝包)
(7)package.lock.json:npm install(安裝)時鎖定各包的版本號
(8)README.md:項目使用說明
在webStorm中打開項目,首先趕緊右擊Project進行如下操作(否則會卡死,還有各種其他方法參見:https://www.cnblogs.com/chengwb/p/6183440.html):
(1)啟動安裝:cnpm install
(2)然后npm run dev:跑起來~
(3)生成打包文件 :npm run build
然后你會發現項目多了個dist文件夾(用于部署到生產環境用,是打包壓縮之后的src文件夾)
每日一博欄目,每日為你推薦優秀博主的優質技術文章。同時歡迎用戶投稿,文章一旦被官方賬號收錄,我們會在網站首頁等位置進行推薦哦。關注開源中國OSC每日獲取優質推送,點擊“了解更多”閱讀原文章。
yshop基于當前流行技術組合的前后端分離商城系統: SpringBoot2+MybatisPlus+SpringSecurity+jwt+redis+Vue的前后端分離的商城系統, 包含分類、sku、運費模板、素材庫、小程序直播、拼團、砍價、商戶管理、 秒殺、優惠券、積分、分銷、會員、充值、多門店等功能,更適合企業或個人二次開發
Idea、webstorm、vscode
1、請確保redis已經安裝啟動
2、下載代碼
3、idea打開項目加載依賴目錄如下:
4、導入數據庫,配置開發環境數據庫信息及其redis信息,文件路徑如下:
5、然后在父級pom.xml輸入命令 mvn clean install 或者用idea工具操作
6、啟動程序,啟動程序的路徑如下:
源碼已經幫大家整理好了,需要的同學轉發本文+關注+私信【0426】即可無償獲取
*請認真填寫需求信息,我們會在24小時內與您取得聯系。