springboot + vue 搭建使用maven+ant构建

新建一个springboot和vue前后端分离项目,并集成软件包构建。

简单的说就是利用maven的ant插件调用node的npm对web项目构建后,拷贝到spring boot项目下,再打包。

这样通过maven命令可以一次性完成前后端分离项目的构建。

预置条件

请自行安装idea、Webstorm 、jdk、nodejs以及maven

  • jdk11

  • maven

    配置阿里云镜像,本人使用的settings.xml如下

    <?xml version="1.0" encoding="UTF-8"?>
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
        <localRepository>D:\myMvnRepo</localRepository>
        <pluginGroups>
        </pluginGroups>
        <proxies>
        </proxies>
        <servers>
        </servers>
        <mirrors>
            <mirror>
                <id>alimaven</id>
                <name>aliyun maven</name>
                <url>https://maven.aliyun.com/repository/central</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
        </mirrors>
        <profiles>
            <profile>
                <id>spring</id>
                <activation>
                    <jdk>11</jdk>
                </activation>
                <repositories>
                    <repository>
                        <id>spring</id>
                        <url>https://maven.aliyun.com/repository/spring</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                        </snapshots>
                    </repository>
                </repositories>
            </profile>
        </profiles>
    </settings>
    
  • node 16

    配置cnpm,则后文的npm命令都是cnmp代替了。

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    

springboot hello world

  • 创建项目

    手动配置maven项目成spring-boot项目当然也是可以的。或者从官网初始化

    这里我们利用idea封装的新建spring-boot项目选项。

    选择java、maven 、jdk11
    在这里插入图片描述

    点击next ,本人选择的spring boot版本为 2.6.7,添加了一个依赖 Spring web
    在这里插入图片描述

    此后单击Create便可新建一个项目。

    请注意如果您使用的settings.xml如果不在当前用户目录下,则不是当前用户全局生效的。可以单独为该项目设置,打开idea 的setting ,File -> Setting (Ctrl+Alt + S),进入 Build,Execution,Deployment > Build Tools > Maven 选择 User settings file后的override,便可选择文件,指定settings.xml。

  • 编写服务端代码

    找到自行设置包名唯一的java文件,这里省去新建Controller,直接复用这个文件,

    在类声明上为其加上@RestController 注解。
    然后使用@GetMapping 注解hello方法,表示对/helloworld这个地址的get请求 映射当前方法。

    方便前端调试,可以先允许跨域,故对Controller使用@CrossOrigin注解。
    总体如下(注意package,以自己的为准),服务端编写完成。

    package com.example.springboot.hello;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    @CrossOrigin
    public class HelloSpringBootApplication {
          
          
    
        public static void main(String[] args) {
          
          
            SpringApplication.run(HelloSpringBootApplication.class, args);
        }
    
        @GetMapping("/helloworld")
        public String hello() {
          
          
            return "Hello World!";
        }
    }
    
  • 运行

    有main方法的java类的idea会生成执行按钮图标,或者在打开那个唯一java文件的界面ctrl+shift+F10便可构建并运行服务端。

    注意

    后文将使用npm 运行web服务 ,默认端口也是8080。虽然遇到8080被占用的情况,会自动端口数值增加来绑定。

    但springboot作为服务端默认端口8080,服务端自动绑定端口是不安全的,若需要指定springboot的web端口。

    src/main/resources/application.properties中 指定,例如指定为8000

    server.port=8000
    

    访问http://127.0.0.1:8000/helloworld 可以看到 服务端的响应


vue hello world

vue4 elementUI搭建

以下过程可能因为各种模块版本变化而失败。

  • cnpm安装vue

    cnpm install vue
    
  • 创建项目

    这里直接使用webstorm创建一个项目名为hello-vue。这里看起来是vue5创建时是4.

    在这里插入图片描述

  • webstorm设置cnpm

    webstorm 上File -> Setting 打开Setting

    直接搜索npm或者 进入Languages & Frameworks >Node.js and NPM
    选中Package manager
    在这里插入图片描述

    选择文件。

    在这里插入图片描述

    此时建议显示隐藏文件(不出意外cnpm在隐藏文件里)。

    本人路径如下

    C:\Users\immor\AppData\Roaming\npm\node_modules\cnpm

    可输入以下内容代替上述地址,则不会因为用户名不一样而导致路径找不到。

    ~\AppData\Roaming\npm\node_modules\cnpm

  • 添加element ui

    vue可以通过ui添加 或者命令添加见element ui的readme

    这里项目已经创建好,跳过新建,直接添加即可,在刚才创建的项目下执行以下命令。

    vue add element
    

    此时提示部分引入还是全部引入
    在这里插入图片描述

    可以使用上下键选择,按enter确定

    这里我选择Fully import.

    后续的确认选项本人选择如下:

    ? Do you wish to overwrite Element's SCSS variables? Yes
    ? Choose the locale you want to load zh-CN
    
    

    然后报错了

    npm ERR! code 1
    npm ERR! path D:\Users\immor\idea\hello-vue\node_modules\node-sass
    
    

    看到node-sass和sass-loader以及element-ui没有装上在这里插入图片描述
    这里我们修改一下package.json中依赖的版本号,高版本解析elements添加后的src/element-variables.scss会出错,以下版本号目前可行。

      "node-sass": "^6.0.1",
      "sass-loader": "^10.2.0",
    

    再使用cnpm安装相关依赖

    cnpm install
    

    此时运行配置里面有npm serve项,可以点击运行,也可以使用 cnpm run serve 运行

  • Vue里使用elementUI

    在main.js确保含有ElementUI 必要的导包

    然后全部引用只需Vue.use(ElementUI);

    (此外,为了方便后文不重复贴代码,还导入了axios,并赋值到Vue的prototype中 )

    main.js示例如下:

    import Vue from 'vue'
    import App from './App.vue'
    import './plugins/element.js'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    import axios from 'axios'
    
    Vue.use(ElementUI)
    Vue.config.productionTip = false
    Vue.prototype.$http = axios
    
    new Vue({
          
          
      render: h => h(App),
    }).$mount('#app')
    
  • Vue中使用ElementUI按钮和axios发送请求到springboot服务端

    此时需要往package.json添加axios的依赖

    devDependencies节点下添加一条记录
    在这里插入图片描述

    "axios": "^0.27.2" 注意逗号

    将新建项目生成的src/App.vue 进行删减,只剩一个图标和大体框架。目前内容就导入了一个HelloWorld.vue

    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <HelloWorld msg="Welcome to Your Vue.js App"/>
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld.vue'
    
    export default {
            
            
      name: 'app',
      components: {
            
            
        HelloWorld
      }
    }
    </script>
    
    <style>
    #app {
            
            
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    修改components/HelloWorld.vue添加一个ElementsUI的按钮,并将点击事件设置为请求前述服务端的/helloworld地址.

    <template>
      <div>
        <el-button v-on:click="sendReq" type="primary">hello world</el-button>
      </div>
    </template>
    
    <script>
    export default {
            
            
      name: 'HelloWorld',
      props: {
            
            
        msg: String
      },
      methods: {
            
            
        sendReq: function () {
            
            
          let url = '/helloworld';
          // 兼容开发模式跨域调用,建议构建前删掉该if语块
          if (process.env.NODE_ENV === 'development') {
            
            
            url = 'http://' + location.hostname + ':8000' + url;
          }
          this.$http.get(url, {
            
            
          }).then((rsp) => {
            
            
           this.$message({
            
            
              message: 'server say:' + rsp['data'],
              type: 'success'
            })
          }).catch((err) => {
            
            
            this.$message.error('发生异常:' + err);
          })
        }
      }
    
    }
    </script>
    

    正常情况,点击hello world按钮会收到服务端的响应在这里插入图片描述

配置总体构建

Springboot对服务端项目构建已经在springboot插件里面集成好了,根据开始的选择,执行mvn package 就能打包。

但前后端分离项目,需要前端编译为静态页面后丢进 src/main/resources/static,再执行mvn package

人肉执行npm 构建再复制再执行mvn命令,也是可以的。

这里我们使用maven的ant插件代劳

  • 引入ant插件

    在springboot 项目的pom.xml build>plugins中新增plugin,

     <artifactId>maven-antrun-plugin</artifactId>
     <version>1.8</version>
    

    但需要运行配置,运行配置里面可以写ant的target但idea并不能很好识别maven的ant配置。复杂的ant可以链接到ant文件。

    大体上如下(后面会进一步修改,这里不用复制)

    <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.8</version>
        <executions>
            <execution>
                <id>build web</id>
                <phase>generate-resources</phase>
                <goals>
                    <goal>run</goal>
                </goals>
                <configuration>
                    <target name="npm build web">
                        <echo>use npm:${npm.name}</echo>
                        <echo>web ui source in : ${web.ui.dir}</echo>
                        <echo>java static source dir is : ${java.web.res}</echo>
                        <property name="npm" value="${npm.name}"/>
                        <property name="web.ui.dir" value="${web.ui.dir}"/>
                        <property name="java.web.res" value="${java.web.res}"/>
                        <ant antfile="build.xml"/>
                    </target>
                </configuration>
            </execution>
            <execution>
                <id>clean</id>
                <phase>clean</phase>
                <goals>
                    <goal>run</goal>
                </goals>
                <configuration>
                    <target name="clean web static">
                        <echo>clean web static</echo>
                        <delete verbose="true" includeEmptyDirs="true">
                            <fileset dir="${java.web.res}">
                                <include name="**/*"/>
                                <exclude name=".gitkeep"/>
                            </fileset>
                        </delete>
                    </target>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    配置了两个

    generate-resources阶段,执行npm 去构建前端项目。并将生成的文件复制到在static目录。

    clean阶段则删除复制过来的文件。

    其中generate-resources 内容主要是传递三个变量(这三个变量,在maven的properties里面声明,后文贴出完整pom会有)给ant再调用build.xml。

    build.xml内容如下,主要是在不同操作系统下用不同的命令行调用npm run build

    <?xml version="1.0" encoding="UTF-8" ?>
    <project name="npm" default="build">
    
        <condition property="isMac">
            <os family="mac"/>
        </condition>
    
        <condition property="isWindows">
            <os family="windows"/>
        </condition>
    
        <condition property="isUnix">
            <os family="unix"/>
        </condition>
        <target name="copyBuild">
            <echo>clean ${java.web.res}</echo>
            <delete verbose="true" includeEmptyDirs="true">
                <fileset dir="${java.web.res}">
                    <include name="**/*"/>
                    <exclude name=".gitignore"/>
                </fileset>
            </delete>
            <echo>copy build result to ${java.web.res}</echo>
            <copy todir="${java.web.res}">
                <fileset dir="${web.ui.dir}/dist">
                    <include name="**/*.*"/>
                </fileset>
            </copy>
        </target>
    
        <target name="doMac" if="isMac">
            <echo message="build at mac target "/>
        </target>
    
        <target name="doWindows" if="isWindows">
            <echo message="build at windows target ;web src in:${web.ui.dir}"/>
            <exec executable="cmd.exe">
                <arg line="/c cd /d ${web.ui.dir} &amp;&amp; ${npm} run build  "/>
            </exec>
            <antcall target="copyBuild"/>
        </target>
    
        <target name="doUnix" if="isUnix">
            <echo message="build at Unix target;web src in:${web.ui.dir}"/>
            <echo>cmd is:cd ${web.ui.dir} &amp;&amp; ${npm} run build</echo>
            <exec executable="/bin/sh">
                <arg line="-c &quot; cd  ${web.ui.dir} &amp;&amp; ${npm} run build &quot;"/>
            </exec>
            <antcall target="copyBuild"/>
        </target>
    
    
        <target name="build" depends="doMac, doWindows, doUnix"
                description="Public target"><!-- set the operating system test properties -->
            <echo message="build webui success!"/>
        </target>
    
    </project>
    
  • 使用profile控制构建web的开关

    按照上述方法设置的pom文件每次构建java都需要构建web。

    npm构建项目本身会判断是否增量,第二次没有首次花费时间,但依然没有必要每次构建web。ant里面调用npm和复制做成动态也可以通过一些判断实现,但这里我们可以通过maven的profile来控制web的构建。

    将pom中的ant插件配置放置在一个名为buildWeb的profile中,总体的pom如下:

    关于properties配置注意事项,前文创建web项目名为hello-vue,和springboot文件是平级。故在properties标签里设置了web.ui.dir的值为${basedir}/../hello-vue通过当前根目录退到上一级再找到 hello-vue文件夹。这里请根据自己放置web代码实际位置配置。

    npm.name 这里也是配做 cnpm

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.6.7</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>hello-spring-boot</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>hello-spring-boot</name>
        <description>hello-spring-boot</description>
        <properties>
            <java.version>11</java.version>
            <npm.name>cnpm</npm.name>
            <web.ui.dir>${basedir}/../hello-vue</web.ui.dir> 
            <java.web.res>${basedir}/src/main/resources/static</java.web.res>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
    
            </plugins>
        </build>
        <profiles>
            <profile>
                <id>buildWeb</id>
                <build>
                    <plugins>
                        <plugin>
                            <artifactId>maven-antrun-plugin</artifactId>
                            <version>1.8</version>
                            <executions>
                                <execution>
                                    <id>build web</id>
                                    <phase>generate-resources</phase>
                                    <goals>
                                        <goal>run</goal>
                                    </goals>
                                    <configuration>
                                        <target name="npm build web">
                                            <echo>use npm:${npm.name}</echo>
                                            <echo>web ui source in : ${web.ui.dir}</echo>
                                            <echo>java static source dir is : ${java.web.res}</echo>
                                            <property name="npm" value="${npm.name}"/>
                                            <property name="web.ui.dir" value="${web.ui.dir}"/>
                                            <property name="java.web.res" value="${java.web.res}"/>
                                            <ant antfile="build.xml"/>
                                        </target>
                                    </configuration>
                                </execution>
                                <execution>
                                    <id>clean</id>
                                    <phase>clean</phase>
                                    <goals>
                                        <goal>run</goal>
                                    </goals>
                                    <configuration>
                                        <target name="clean web static">
                                            <echo>clean web static</echo>
                                            <delete verbose="true" includeEmptyDirs="true">
                                                <fileset dir="${java.web.res}">
                                                    <include name="**/*"/>
                                                    <exclude name=".gitkeep"/>
                                                </fileset>
                                            </delete>
                                        </target>
                                    </configuration>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        </profiles>
    </project>
    
    

    此时没有配置为默认激活buildWeb

    • idea 激活profile

      可以看到idea的maven插件界面展开Profiles可以看到刚才配置的buildWeb在这里插入图片描述

      我们勾选该项,再点击package便可触发,构建web。

      构建一次之后,static目录下有了内容,后续仅仅编译java时,则不需要勾选此项。

    • 命令构建激活profile

      使用mvn命令时 使用-P 指定激活的profile

      mvn -P buildWeb clean
      mvn -P buildWeb install
      
  • 降低耦合的建议

    将构建web任务单独作为maven模块,然后web服务的模块编译依赖该模块,便能触发先构建web ui再编译和打包web服务。

    或者使用gradle同时替代maven与ant。

运行

构建出的jar包脱离ide运行,只需jre即可。在target目录生成了一个jar包,使用java -jar执行。

jar -jar hello-spring-boot-0.0.1-SNAPSHOT.jar

猜你喜欢

转载自blog.csdn.net/qq_26700087/article/details/124521482