使用Gradle整合SpringBoot+Vue.js-开发调试与打包

原文:https://segmentfault.com/a/1190000008968295

首先非常感谢kevinz分享的文章《springboot+gradle+vue+webpack 组合使用》,这文章对我的帮助非常大。

我是做Java后台开发的,一般做Java的要做网页都是用jsp,但我并不喜欢在jsp代码中使用jstl标签,我一直想找一个Java能用的前后端分离的解决方案。目前确定比较好的组合是:前台页面用Vue.js,后台用SpringBoot。但是Vue.js在网上能找到的都是需要Node.js环境进行打包的,这使得不懂Node.js的Java程序员望而却步。

在此之前,为了能用上Vue.js快速开发网页,我利用Vue.js的异步组件的特性来加载组件,并配合vue-router来实现组件的视图切换。这样子就能用传统的JavaScript写法在网页端用上Vue.js。对于小型的项目是能适用的,但是对于大型的项目组织起来比较麻烦,而且没有代码压缩、混淆的功能。

在看到kevinz的文章后,我认真研究了,并稍作修改,在这里记下学习的笔记。


我的开发环境如下:

  1. IDEIntellij IDEA
  2. JDKJava8
  3. Gradle:3.3
  4. Node.js:6.10.1
  5. Vue-CLI:2.8.1

1.Node.js安装与配置

  1. 到官网下载最新的Node.js安装
  2. 由于Node.js安装后,默认的node_modules和缓存文件是存在C盘的,最好是修改成其它盘。
  3. 在其它盘创建Node.js缓存文件夹,如:

    1. E: \_development \nodejs \g lobal 存放例如用`npm install -g express`命令安装的模块文件
    2. E: \_development \nodejs \cache 存放下载缓存
  4. 找到【nodejs安装目录】/node_modules/npm/npmrc 文件,用txt打开,修改配置:

    1. prefix= E:\_development\nodejs\global 指定全局安装的 node 模块的目录
    2. cache= E:\_development\nodejs\cache 指定缓存目录
    3. registry=https: //registry.npm.taobao.org 指定使用国内的淘宝的 Node . js 镜像
  5. 为了测试配置是否成功,运行一下命令npm install -g express安装一个express试试,Java程序员可能不知道,express是Node.js的后端mvc框架,类似Java中的SpringMVC。如果安装成功,会生成一个E:_developmentnodejsglobalnode_modules目录,express的文件就在该目录下。
  6. 新增环境变量:

    NODE_PATH=E:\_development\nodejs\global\node_modules
  7. Path环境变量加入路径:

    E:\_development\nodejs\global 加入该路径,才能使用后面安装vue-cli后的vue命令

2.vue-cli安装

vue-cli中cli是command line interface的缩写,安装很简单:npm install -g vue-cli-g是全局安装的意思。安装过程可能比较久。安装完可以通过vue -V查看是否安装成功。如下图:

3.在IDEA搭建项目框架

  1. 创建整体工程的结构是,先创建一个总工程,叫show,再创建两个子模块,一个叫server,一个叫web。
  2. 打开IDEA,File-->New-->Project-->Gradle-->取消勾选Java-->Next。如下图:

  3. 输入父工程的信息,如下图:

  4. 设置Gradle相关配置,由于网络特殊原因,最好用本地的Gradle库,配置如下图:

  5. 设置项目存放路径,如下图:

  6. 项目创建出来就除了Gradle的配置文件,其它什么都没有,接下来要创建两个子工程server和web。show项目创建后如下图:

  7. 创建server子项目,对着show项目:

    1. 右键-->New--> Module-->Gradle-->勾选Java
    2. --> Next-->ArtifactId填 "server"
    3. --> Next-->Finished
  8. 创建web子项目,对着show项目:

    1. 右键-->New--> Module-->Gradle-->勾选Javaweb
    2. --> Next-->ArtifactId填 "web"
    3. --> Next-->Finished
  9. show总项目的build.gradle文件修改成如下配置:

    1. group 'com .gongshi'
    2. version ' 1.0 '
  10. show总项目的setting.gradle文件修改成如下配置:

    1. rootProject.name = 'show'
    2. include 'server'
    3. include 'web'
  11. web子项目的build.gradle文件修改成如下配置:

    1. plugins {
    2. id "com.moowork.node" version "1.1.1"
    3. id 'java'
    4. }
    5. //调用npm run build命令的Gradle任务
    6. task npmBuild(type: NpmTask, dependsOn: npmInstall) {
    7. group = 'node'
    8. args = [ 'run', 'build']
    9. }
    10. //Gradle的java插件的jar任务,依赖npmBuild,即web子模块打jar包前必须运行npm run build
    11. jar.dependsOn npmBuild
    12. //调用npm run dev
    13. task npmDev(type: NpmTask, dependsOn: npmInstall) {
    14. group = 'node'
    15. args = [ 'run', 'dev']
    16. }

    在上面的代码中, id "com.moowork.node" version "1.1.1" 一行是加入了一个Gradle插件,叫gradle-node-plugin,该插件可以通过调用Gradle命令来调用node.js的命令或npm的命令。插件自带了一些内容的命令,如:gradle npmInstall用于运行npm install命名,另外还有:

    1. $ gradle npm_install
    2. $ gradle npm_update
    3. $ gradle npm_list
    4. $ gradle npm_cache_clean
    5. ...
  12. server子项目的build.gradle文件修改成如下配置:

    1. plugins {
    2. id 'org.springframework.boot' version '1.5.2.RELEASE'
    3. id 'java'
    4. }
    5. jar {
    6. baseName = 'server'
    7. version = '1.0'
    8. }
    9. repositories {
    10. //使用淘宝的maven镜像
    11. maven{ url 'http://maven.aliyun.com/nexus/content/groups/public'}
    12. }
    13. dependencies {
    14. compile project ( ':web' ) //server模块依赖web模块
    15. compile ( "org.springframework.boot:spring-boot-starter-web" )
    16. compile ( "org.springframework.boot:spring-boot-devtools" )
    17. testCompile ( "org.springframework.boot:spring-boot-starter-test" )
    18. }

    在上面的代码中,需要特别注意的是compile project(':web'),这个设置能在server打包时把web的资源先打包,并作为依赖,加入到server项目生成的jar包中。

13.在IDEA右侧找到Gradle的栏目,点击Refresh All Gradle Projects, IDEA会按找各个build.gradle文件的配置,下载依赖的jar。


到这里为止,项目的结构搭建好了,下一步是先编写一下SpringBoot的代码,把一个简单Java后台跑起来。

4.编写SpringBoot的后台

1.创建包com.gongshi,创建类:Application.java。如下:

Application.java:

  1. package com.gongshi;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.boot.web.servlet.ServletRegistrationBean;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.web.context.WebApplicationContext;
  9. import org.springframework.web.servlet.DispatcherServlet;
  10. @ SpringBootApplication
  11. public class Application {
  12. private static final Logger logger = LoggerFactory.getLogger( Application. class);
  13. public static void main( String[] args) {
  14. SpringApplication.run( Application. class);
  15. logger.info( "SpringBoot server stated on port: 8080");
  16. }
  17. //增加一个SpringMVC的DispatcherServlet,接收前台/api开头的请求
  18. @ Bean
  19. public ServletRegistrationBean apiV1ServletBean( WebApplicationContext wac) {
  20. DispatcherServlet servlet = new DispatcherServlet(wac);
  21. ServletRegistrationBean bean = new ServletRegistrationBean(servlet, "/api/*");
  22. bean.setName( "ApiServlet");
  23. return bean;
  24. }
  25. }

3.创建包com.gongshi.controller,创建类:AppController.java。如下:

AppController.java:

  1. package com.gongshi.controller;
  2. import org.springframework.web.bind. annotation.RequestMapping;
  3. import org.springframework.web.bind. annotation.RestController;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. @RestController
  7. @RequestMapping("/app")
  8. public class AppController {
  9. //简单的后台接口,用于测试
  10. @RequestMapping("/info")
  11. public Object info(){
  12. Map<String,Object> map = new HashMap<>();
  13. map.put( "info", "hello hello hello");
  14. return map;
  15. }
  16. }

3.在server/src/main/resources目录下,创建一个staic目录,创建一个html页面,用于测试,如下:
index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title </title>
  6. </head>
  7. <body>
  8. <h1>Hello Spring Boot </h1>
  9. </body>
  10. </html>

4.暂时注释掉server/builde.gradle中的compile project(':web')配置(因为web子项目未配置好vue.js相的内容),在IDEA右侧Gradle栏目,点击运行server的bootRun任务,bootRun任务会运行Application.java下的main方法。启动Spring Boot,如下图:

为了测试后台是否正常运行,分别访问一下:

  1. http://localhost:8080,结果如下:

  2. http://localhost:8080/index.html,结果如下:

  3. http://localhost:8080/app/info,结果如下:

以上三个结果中,需要注意下第1个和第2个。Spring Boot默认会将server/src/main/resources/static下的文件作为静态资源,提供给外部访问。当访问http://localhost:8080时,发现static有index.html文件,默认会显示到浏览器端。这就是为什么1和2的结果是一样的。

5.编写Vue.js的前台

  1. 在这里前台使用vue-cli生成前台的模板。随便打开一个文件夹,比如:D:demo,按住shift+右键-->在此处打开命令窗口,即可打开一个命令行,输入命令vue init webpack web,其中webpack是用webpack做vue.js的打包工具,web是生成的模板名称。依次做以下的选择:
  1. P roject name --> web
  2. P roject description --> A Vue.js project
  3. A uthor --> Hello
  4. V ue build --> 回车
  5. I nstall vue-router ? --> y
  6. U se ESlint to lint your code? --> n
  7. S etup unit tests with Karma + Mocha? --> n
  8. S etup 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的模板页面。如下图:

6.修改Vue.js的前台配置

  1. 因为gradle构建输出目录是build,vue-cli生成的模板的构建脚本的目录也是build,因此这里要把构建脚本的build目录修改成script:点选show/web/build目录,shift+F6重命名,将show/web/build目录改成script目录,避免与gradle的构建输出目录冲突。
  2. 修改show/web/package.json中与build目录相关的配置:
  1. "scripts": {
  2. "dev": "node build/dev-server.js",
  3. "build": "node build/build.js"
  4. },
  5. 改成:
  6. "scripts": {
  7. "dev": "node script/dev-server.js",
  8. "build": "node script/build.js"
  9. },

3.修改show/web/script/webpack.dev.conf.js中与build目录相关的配置:

  1. Object.keys(baseWebpackConfig. entry).forEach( function ( name ) {
  2. baseWebpackConfig. entry[ name] = [ './build/dev-client'].concat(baseWebpackConfig. entry[ name])
  3. })
  4. 改成:
  5. Object.keys(baseWebpackConfig. entry).forEach( function ( name ) {
  6. baseWebpackConfig. entry[ name] = [ './script/dev-client'].concat(baseWebpackConfig. entry[ name])
  7. })

4.修改show/web/config/index.js中的配置,包括webpack打包输出位置,以及配置代理避免跨域问题,具体修改项看下面注释:

show/web/config/index.js:

  1. // see http://vuejs-templates.github.io/webpack for documentation.
  2. var path = require( 'path')
  3. var assetsRoot = path. resolve(__dirname, '../build/resources/main/static') // <----- 1 . add
  4. module.exports = {
  5. build: {
  6. en v: require( './prod.env'),
  7. index: path. resolve(assetsRoot, 'index.html'), // <----- 2 . change
  8. assetsRoo t: assetsRoot, // <----- 3 . change
  9. assetsSubDirectory: 'assets', // <----- 4 . change
  10. assetsPublicPath: '/',
  11. productionSourceMap: true,
  12. // Gzip off by default as many popular static hosts such as
  13. // Surge or Netlify already gzip all static assets for you.
  14. // Before setting to `true`, make sure to :
  15. // npm install --save-dev compression-webpack-plugin
  16. productionGzip: false,
  17. productionGzipExtension s: [ 'js', 'css'],
  18. // Run the build command with an extra argument to
  19. // View the bundle analyzer report after build finishe s:
  20. // `npm run build --report`
  21. // Set to `true` or `false` to always turn it on or off
  22. bundleAnalyzerRepor t: process.env.npm_config_report
  23. },
  24. de v: {
  25. en v: require( './dev.env'),
  26. por t: 3000, // <----- 5 . change
  27. autoOpenBrowser: true,
  28. assetsSubDirectory: 'assets', // <----- 6 . change
  29. assetsPublicPath: '/',
  30. proxyTable: { // <----- 7 . change
  31. '/api/**': 'http://localhost:8080' //代理前台/api开头的请求,代理到 8080 端口,spring boot的访问端口
  32. },
  33. // CSS Sourcemaps off by default because relative paths are "buggy"
  34. // with this option, according to the CSS-Loader README
  35. // (http s: //github. com /webpack/css-loader#sourcemaps)
  36. // In our experience, they generally work as expected,
  37. // just be aware of this issue when enabling this option.
  38. cssSourceMap: false
  39. }
  40. }

5.测试show/web子项目的开发环境。关闭spring boot后台,在IDEA右侧Gradle栏目找到npmDev任务并运行。如果运行成功,会自动打开浏览器显示http://localhost:3000,并显示Vue.js的模板页面,此时找到show/web/src/components/Hello.vue,修改一点内容:

  1. <script>
  2. export default {
  3. name: 'hello',
  4. data () {
  5. return {
  6. msg : ' Welcome to Your Vue . js App 333333333'//< -----change
  7. }
  8. }
  9. }
  10. </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子项目打包过来的文件重复。

7.开发调试

  1. 先运行show/server子项目的bootRun任务,启动Spring Boot
  2. 再运行show/web子项目的npmDev任务,启动node的开发服务器
  3. 当show/web子项目有请求需要调用Spring Boot后台,加上/api前缀,请求即可代理从node的开发服务器http://localhost:3000/api/xxxx代理到http://localhost:8080/api/xxxx
  4. 而在开发前台页面时候(对show/web/src目录下的文件修改),应该访问http://localhost:3000/,而不是8080端口,访问3000端口,即可看到页面修改的即时效果。

8.打包

运行show/server子项目的build任务,即可完成打包。打包的jar包已经包含show/web子项目的输出内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值