首先很是感謝kevinz分享的文章《springboot+gradle+vue+webpack 組合使用》,這文章對個人幫助很是大。css
我是作Java後臺開發的,通常作Java的要作網頁都是用jsp,但我並不喜歡在jsp代碼中使用jstl標籤,我一直想找一個Java能用的先後端分離的解決方案。目前肯定比較好的組合是:前臺頁面用Vue.js,後臺用SpringBoot。可是Vue.js在網上能找到的都是須要Node.js環境進行打包的,這使得不懂Node.js的Java程序員望而卻步。html
在此以前,爲了能用上Vue.js快速開發網頁,我利用Vue.js的異步組件的特性來加載組件,並配合vue-router來實現組件的視圖切換。這樣子就能用傳統的JavaScript寫法在網頁端用上Vue.js。對於小型的項目是能適用的,可是對於大型的項目組織起來比較麻煩,並且沒有代碼壓縮、混淆的功能。前端
在看到kevinz的文章後,我認真研究了,並稍做修改,在這裏記下學習的筆記。vue
個人開發環境以下:java
IDE:Intellij IDEA JDK:Java8 Gradle:3.3 Node.js:6.10.1 Vue-CLI:2.8.1
在其它盤建立Node.js緩存文件夾,如:node
E:\_development\nodejs\global 存放例如用`npm install -g express`命令安裝的模塊文件 E:\_development\nodejs\cache 存放下載緩存
找到【nodejs安裝目錄】/node_modules/npm/npmrc 文件,用txt打開,修改配置:webpack
prefix=E:\_development\nodejs\global 指定全局安裝的node模塊的目錄 cache=E:\_development\nodejs\cache 指定緩存目錄 registry=https://registry.npm.taobao.org 指定使用國內的淘寶的Node.js鏡像
npm install -g express
安裝一個express試試,Java程序員可能不知道,express是Node.js的後端mvc框架,相似Java中的SpringMVC。若是安裝成功,會生成一個E:_developmentnodejsglobalnode_modules目錄,express的文件就在該目錄下。新增環境變量:git
NODE_PATH=E:\_development\nodejs\global\node_modules
Path環境變量加入路徑:程序員
E:\_development\nodejs\global 加入該路徑,才能使用後面安裝vue-cli後的vue命令
vue-cli中cli是command line interface的縮寫,安裝很簡單:npm install -g vue-cli
,-g
是全局安裝的意思。安裝過程可能比較久。安裝完能夠經過vue -V
查看是否安裝成功。以下圖:github
建立server子項目,對着show項目:
右鍵-->New-->Module-->Gradle-->勾選Java -->Next-->ArtifactId填"server" -->Next-->Finished
建立web子項目,對着show項目:
右鍵-->New-->Module-->Gradle-->勾選Javaweb -->Next-->ArtifactId填"web" -->Next-->Finished
將show
總項目的build.gradle
文件修改爲以下配置:
group 'com.gongshi' version '1.0'
將show
總項目的setting.gradle
文件修改爲以下配置:
rootProject.name = 'show' include 'server' include 'web'
將web
子項目的build.gradle
文件修改爲以下配置:
plugins { id "com.moowork.node" version "1.1.1" id 'java' } //調用npm run build命令的Gradle任務 task npmBuild(type: NpmTask, dependsOn: npmInstall) { group = 'node' args = ['run', 'build'] } //Gradle的java插件的jar任務,依賴npmBuild,即web子模塊打jar包前必須運行npm run build jar.dependsOn npmBuild //調用npm run dev task npmDev(type: NpmTask, dependsOn: npmInstall) { group = 'node' args = ['run', 'dev'] }
在上面的代碼中, id "com.moowork.node" version "1.1.1"
一行是加入了一個Gradle插件,叫gradle-node-plugin,該插件能夠經過調用Gradle命令來調用node.js的命令或npm的命令。插件自帶了一些內容的命令,如:gradle npmInstall
用於運行npm install
命名,另外還有:
$ gradle npm_install $ gradle npm_update $ gradle npm_list $ gradle npm_cache_clean ...
將server
子項目的build.gradle
文件修改爲以下配置:
plugins { id 'org.springframework.boot' version '1.5.2.RELEASE' id 'java' } jar { baseName = 'server' version = '1.0' } repositories { //使用淘寶的maven鏡像 maven{ url 'http://maven.aliyun.com/nexus/content/groups/public'} } dependencies { compile project(':web')//server模塊依賴web模塊 compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-devtools") testCompile("org.springframework.boot:spring-boot-starter-test") }
在上面的代碼中,須要特別注意的是compile project(':web')
,這個設置能在server打包時把web的資源先打包,並做爲依賴,加入到server項目生成的jar包中。
13.在IDEA右側找到Gradle的欄目,點擊Refresh All Gradle Projects, IDEA會按找各個build.gradle文件的配置,下載依賴的jar。
到這裏爲止,項目的結構搭建好了,下一步是先編寫一下SpringBoot的代碼,把一個簡單Java後臺跑起來。
1.建立包com.gongshi,建立類:Application.java。以下:
Application.java:
package com.gongshi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; @SpringBootApplication public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class); logger.info("SpringBoot server stated on port: 8080"); } //增長一個SpringMVC的DispatcherServlet,接收前臺/api開頭的請求 @Bean public ServletRegistrationBean apiV1ServletBean(WebApplicationContext wac) { DispatcherServlet servlet = new DispatcherServlet(wac); ServletRegistrationBean bean = new ServletRegistrationBean(servlet, "/api/*"); bean.setName("ApiServlet"); return bean; } }
3.建立包com.gongshi.controller,建立類:AppController.java。以下:
AppController.java:
package com.gongshi.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/app") public class AppController { //簡單的後臺接口,用於測試 @RequestMapping("/info") public Object info(){ Map<String,Object> map = new HashMap<>(); map.put("info","hello hello hello"); return map; } }
3.在server/src/main/resources目錄下,建立一個staic目錄,建立一個html頁面,用於測試,以下:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello Spring Boot</h1> </body> </html>
4.暫時註釋掉server/builde.gradle
中的compile project(':web')
配置(由於web子項目未配置好vue.js相的內容),在IDEA右側Gradle欄目,點擊運行server的bootRun任務,bootRun任務會運行Application.java下的main方法。啓動Spring Boot,以下圖:
爲了測試後臺是否正常運行,分別訪問一下:
以上三個結果中,須要注意下第1個和第2個。Spring Boot默認會將server/src/main/resources/static下的文件做爲靜態資源,提供給外部訪問。當訪問http://localhost:8080時,發現static有index.html文件,默認會顯示到瀏覽器端。這就是爲何1和2的結果是同樣的。
vue init webpack web
,其中webpack是用webpack
作vue.js的打包工具,web
是生成的模板名稱。依次作如下的選擇:Project name --> web Project description --> A Vue.js project Author --> Hello Vue build --> 回車 Install vue-router ? --> y Use ESlint to lint your code? --> n Setup unit tests with Karma + Mocha? --> n Setup e2e tests with Nightwatch? --> n
2.執行以上步驟後,vue-cli工具就會將項目模板生成到D:demoweb目錄,此時把web目錄下全部文件拷貝到IDEA的show/web子項目中。以下圖:
3.IDEA下方打開Terminal命令行終端,執行命令:cd web
,npm install
,這樣子npm就會根據package.js中的信息下載依賴的模塊。安裝後show/web/目錄下會出現node_modules目錄。以下圖:
4.此時須要測試一下vue-cli搭建的web子項目是否正確,打開IDEA右側Gradle欄目,找到npmDev任務,雙擊運行一下,任務運行成功會自動打開瀏覽器,顯示localhost:8080,顯示Vue的模板頁面。以下圖:
shift+F6
重命名,將show/web/build目錄改爲script目錄
,避免與gradle的構建輸出目錄衝突。"scripts": { "dev": "node build/dev-server.js", "build": "node build/build.js" }, 改爲: "scripts": { "dev": "node script/dev-server.js", "build": "node script/build.js" },
3.修改show/web/script/webpack.dev.conf.js中與build目錄相關的配置:
Object.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) }) 改爲: Object.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./script/dev-client'].concat(baseWebpackConfig.entry[name]) })
4.修改show/web/config/index.js中的配置,包括webpack打包輸出位置,以及配置代理避免跨域問題,具體修改項看下面註釋:
show/web/config/index.js:
// see http://vuejs-templates.github.io/webpack for documentation. var path = require('path') var assetsRoot = path.resolve(__dirname, '../build/resources/main/static')// <-----1.add module.exports = { build: { env: require('./prod.env'), index: path.resolve(assetsRoot, 'index.html'),// <-----2.change assetsRoot: assetsRoot,// <-----3.change assetsSubDirectory: 'assets',// <-----4.change assetsPublicPath: '/', productionSourceMap: true, // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin productionGzip: false, productionGzipExtensions: ['js', 'css'], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off bundleAnalyzerReport: process.env.npm_config_report }, dev: { env: require('./dev.env'), port: 3000,// <-----5.change autoOpenBrowser: true, assetsSubDirectory: 'assets',// <-----6.change assetsPublicPath: '/', proxyTable: {// <-----7.change '/api/**': 'http://localhost:8080'//代理前臺/api開頭的請求,代理到8080端口,spring boot的訪問端口 }, // CSS Sourcemaps off by default because relative paths are "buggy" // with this option, according to the CSS-Loader README // (https://github.com/webpack/css-loader#sourcemaps) // In our experience, they generally work as expected, // just be aware of this issue when enabling this option. cssSourceMap: false } }
5.測試show/web子項目的開發環境。關閉spring boot後臺,在IDEA右側Gradle欄目找到npmDev任務並運行。若是運行成功,會自動打開瀏覽器顯示http://localhost:3000,並顯示Vue.js的模板頁面,此時找到show/web/src/components/Hello.vue
,修改一點內容:
<script> export default { name: 'hello', data () { return { msg: 'Welcome to Your Vue.js App 333333333'//<-----change } } } </script>
打開瀏覽器查看http://localhost:3000,若是對應的內容更新了,則代表web子項目的開發環境正確。
若是運行npmDev報錯,有多是屢次運行npmDev命令,有其它Node.js進程佔用了端口,打開任務管理器關閉便可,以下圖:
5.測試show/web子項目的打包。在IDEA右側Gradle欄目找到npmBuild任務並運行。若是運行成功,webpack打包的前端資源會輸出到show/web/build目錄下,以下圖:
注意:
我把webpack的打包輸出路徑故意設置成build/resources/main/static,這樣子,web子項目打成jar包後,在classpath中的路徑就是/static目錄了,即跟spring boot默認的靜態資源查找路徑是同樣的。
再者,server子項目依賴web項目(show/server/build.gradle中的compile project(':web')
配置),因此server子項目打jar包前會先將web子項目打成jar包,web子項目的jar包中已經包含了webpack輸出的靜態資源。
因此,當server子項目打包後,訪問http://localhost:8080/index.html就能訪問到web子項目webpack打包的輸出的index.html文件。
注意:
server子項目打包前,請先刪除show/server/src/main/resources/static目錄,避免與web子項目打包過來的文件重複。
運行show/server子項目的build任務,便可完成打包。打包的jar包已經包含show/web子項目的輸出內容。