Springboot项目与vue项目整合打包的实现方式
作者:Andy·Hu 发布时间:2022-01-14 19:25:03
我的环境
* JDK 1.8
* maven 3.6.0
* node环境
1.为什么需要前后端项目开发时分离,部署时合并?
在一些公司,部署实施人员的技术无法和互联网公司的运维团队相比,由于各种不定的环境也无法做到自动构建,容器化部署等。因此在这种情况下尽量减少部署时的服务软件需求,打出的包数量也尽量少。针对这种情况这里采用的在开发中做到前后端独立开发,打包时在后端springboot打包发布时将前端的构建输出一起打入,最后只需部署springboot的项目即可,无需再安装nginx服务器
在这里我有两种方式,一种是简单的,一种是复杂的,下边先来看一个简单的例子:
1)前端开发好后将build构建好的dist下的文件拷贝到springboot的resources的static下(boot项目默认没有static,需要自己新建)
操作步骤:前端vue项目使用命令 npm run build
或者 cnpm run build
打包生成dist文件,在springboot项目中resources下建立static文件夹,将dist文件中的文件复制到static中,然后去application中跑起来boot项目,这样直接访问index.html就可以访问到页面(api接口请求地址自己根据情况打包时配置或者在生成的dist文件中config文件夹中的index.js中配置)
项目结构如图:
鼠标选中的这几个就是从dist文件中复制过来的前端的包,然后我们直接启动boot项目就可以通过index.html访问了(ps:上面这是最简单的合并方式,但是如果作为工程级的项目开发,并不推荐使用手工合并,也不推荐将前端代码构建后提交到springboot的resouce下,好的方式应该是保持前后端完全独立开发代码,项目代码互不影响,借助jenkins这样的构建工具在构建springboot时触发前端构建并编写自动化脚本将前端webpack构建好的资源拷贝到springboot下再进行jar的打包,最后就得到了一个完全包含前后端的springboot项目了。不过上述方法操作简单,便于使用,如果想一次性打包完成的话,就看第二种)
2:第二种方法是在src/main下建立一个webapp文件夹,然后将前端项目的源文件复制到该文件夹下,具体结构如图:
然后使用maven命令执行本地node打包命令,这样就可以 在执行mvn clean package命令时,利用maven插件执行cnpm run build命令(我是使用的淘宝的镜像cnpm,国外的npm命令会相对慢一些,大家根据自己的条件选择,具体命令请看项目中前端vue文件的README.md),一次性完成整个过程
实现方法是这样的,我们要引入org.codehaus.mojo
插件来进行maven调用node命令,pom.xml中为:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>exec-cnpm-install</id>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${cnpm}</executable>
<arguments>
<argument>install</argument>
</arguments>
<workingDirectory>${basedir}/src/main/webapp</workingDirectory>
</configuration>
</execution>
<execution>
<id>exec-cnpm-run-build</id>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${cnpm}</executable>
<arguments>
<argument>run</argument>
<argument>build</argument>
</arguments>
<workingDirectory>${basedir}/src/main/webapp</workingDirectory>
</configuration>
</execution>
</executions>
</plugin>
然后maven-resources-plugin
插件将项目的前端文件打包到boot项目的classes中,具体的请参考pom.xml中的,
将webapp/dist文件夹中的文件复制到src/main/resources/static
中,并打包到classes
<!--copy文件到指定目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<executions>
<execution>
<id>copy-spring-boot-webapp</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<encoding>utf-8</encoding>
<outputDirectory>${basedir}/src/main/resources/static</outputDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/webapp/dist</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
然后通过maven命令:
mvn clean package -P window
打包成功后我们的前端项目就整个的打包到了boot项目的jar包中,然后启动项目,访问index.html页面就看到了项目启动成功。
打出来的jar包中如果static说明打包由于种种原因失败了,我就遇到过几次,这时候需要再来一次 mvn clean package -P window
ps:下面看下SprintBoot 整合vue实现上传下载
这里记录一下在Springboot中实现文件上传下载的核心代码
package com.file.demo.springbootfile;
import com.file.util.ResultUtil;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.apache.tomcat.util.http.fileupload.util.Streams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/*
* springboot整合vue,文件上传下载
* */
//上传不要用@Controller,用@RestController
@RestController
@RequestMapping("/file")
public class FileController {
private static final Logger logger = LoggerFactory.getLogger(FileController.class);
//在文件中,不用/或者\最好,推荐使用File.separator
private final static String fileDir="files";
private final static String rootPath = System.getProperty("user.home")+ File.separator+fileDir+File.separator;
/*
* 文件上传
* */
@RequestMapping("/upload")
public Object uploadFile(@RequestParam("file")MultipartFile[] multipartFiles, final HttpServletResponse response, final HttpServletRequest request){
File fileDir = new File(rootPath);
/*
* exists():测试此抽象路径名表示的文件是否存在
* isDirectory():检查一个对象是否是文件夹
* isFile():判断是否为文件,也可能是文件目录
* */
if(!fileDir.exists() && !fileDir.isDirectory()){
//检查到文件不存在则创建
fileDir.mkdir();//创建文件,一级
fileDir.mkdirs();//创建多级
}
try{
if(multipartFiles != null && multipartFiles.length > 0){
for ( int i = 0;i<multipartFiles.length;i++){
try{
String storagePath = rootPath+multipartFiles[i].getOriginalFilename();
logger.info("上传的文件:" + multipartFiles[i].getName()+","+multipartFiles[i].getContentType()+","
+multipartFiles[i].getOriginalFilename() + ",保持的路径为:" + storagePath);
Streams.copy(multipartFiles[i].getInputStream(), new FileOutputStream(storagePath), true);
}catch (IOException e){
logger.info(ExceptionUtils.getFullStackTrace(e));
}
}
}
}catch (Exception e){
return ResultUtil.error(e.getMessage());
}
return ResultUtil.success("上传成功!");
}
/*
* 文件下载
* */
@RequestMapping("/download")
public Object downkiadFile(@RequestParam String fileName,final HttpServletResponse response,final HttpServletRequest request){
OutputStream os = null;
InputStream is = null;
try{
//获取输出流rootPath
os = response.getOutputStream();
//重置输出流
response.reset();
response.setContentType("application/x-download;charset=GBK");
response.setHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes("utf-8"), "iso-8859-1"));
//读取流
File f= new File(rootPath+fileName);
is = new FileInputStream(f);
if(is == null){
logger.error("下载文件失败,请检查文件“"+ fileName +"”是否存在");
return ResultUtil.error("下载附件失败,请检查文件“" + fileName + "”是否存在");
}
//复制文件
IOUtils.copy(is,response.getOutputStream());
//刷新缓冲
response.getOutputStream().flush();
}catch (IOException e){
return ResultUtil.error("下载文件失败,error:" + e.getMessage());
}
//文件的关闭在finally中执行
finally {
{
try {
if(is != null){
is.close();
}
}catch (IOException e){
logger.error(ExceptionUtils.getFullStackTrace(e));
}
try{
if(os != null){
os.close();
}
}catch (IOException e){
logger.info(ExceptionUtils.getFullStackTrace(e));
}
}
}
return null;
}
}
源码下载地址: https://github.com/struggle0903/SpringBootfiledemo.git
总结
以上所述是小编给大家介绍的Springboot项目与vue项目整合打包的实现方式,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://www.cnblogs.com/Struggle-xh/archive/2019/07/03/11124181.html


猜你喜欢
- 1.Fanout Exchange介绍Fanout Exchange 消息广播的模式,不管路由键或者是路由模式,会把消息发给绑定给它的全部队
- C#删除指定文件或文件夹public static string deleteOneFile(string fileFullPath) &n
- 一、什么是深拷贝和浅拷贝对于所有面向对象的语言,复制永远是一个容易引发讨论的题目,C#中也不例外。此类问题在面试中极其容易被问到,我们应该在
- 1, 新建一个项目, 类型为 安装和部署 中的安装项目或安装向导 2,双击应用程序文件夹,添加所有需要的文件(包括图标,Access,图片和
- Gradle 属性( Gradle build environment)[详细信息]("https://docs.gradle.o
- ? 通配符类型<? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类;<? super T&
- 机器跑了一晚上,发现有崩溃现象,由于页面内有动态绘图功能,我怀疑是绘图原因,但是今天上午有人提醒我才想到,是不是间隔调用时DWR产生了内存泄
- 导入生成器需要的依赖坐标:<dependency> <groupId>com.baomidou</
- 客户端的代码:package tcp.http;import java.io.*;import java.net.*;import java
- 为什么Android要申请权限简单说下在Android6.0及6.0以上一些google认为涉及“危险和用户隐私”的一些权限不仅要做清单文件
- 本文实例为大家分享了C#实现钟表程序设计的具体代码,供大家参考,具体内容如下工作空间:代码如下:using System;using Sys
- 原因如下: Delete()之后需要datatable.AccepteChanges()方法确认完全删除,因为Delete()只是将相应列的
- 配置两个parent的方法在向pom.xml 文件中添加依赖之前需要先添加spring-boot-starter-parent。spring
- 前言 之前unity5.x在代码中写了debug.log..等等,打
- 多继承指一个子类能同时继承于多个父类,从而同时拥有多个父类的特征,但缺点是显著的。1.若子类继承的父类中拥有相同的成员变量,子类在引用该变量
- 由于今天用Security进行权限管理的时候出现了一些Bug,特此发这篇博客来补习一下对SpringSecurity的理解前言引入当今市面上
- JetBrainsMono 是 JetBrains 公司开发的一款开源字体,可免费商用。正如其名字带的Mono,即Monospaced Fo
- 本文实例讲述了C#获取进程或线程相关信息的方法。分享给大家供大家参考。具体实现方法如下:using System;using System.
- 本文实例为大家分享了C#字符串倒序写法的实现代码,供大家参考,具体内容如下//string concatenation with for l
- 效果展示单选版可看上篇博文 用flutter封装一个点击菜单工具栏组件本文是CHeckbox多选版效果如图所示,点击选项回调选中的