Springboot項目與vue項目整合打包的實現(xiàn)方式
我的環(huán)境
* JDK 1.8
* maven 3.6.0
* node環(huán)境
1.為什么需要前后端項目開發(fā)時分離,部署時合并?
在一些公司,部署實施人員的技術(shù)無法和互聯(lián)網(wǎng)公司的運維團隊相比,由于各種不定的環(huán)境也無法做到自動構(gòu)建,容器化部署等。因此在這種情況下盡量減少部署時的服務(wù)軟件需求,打出的包數(shù)量也盡量少。針對這種情況這里采用的在開發(fā)中做到前后端獨立開發(fā),打包時在后端springboot打包發(fā)布時將前端的構(gòu)建輸出一起打入,最后只需部署springboot的項目即可,無需再安裝nginx服務(wù)器
在這里我有兩種方式,一種是簡單的,一種是復(fù)雜的,下邊先來看一個簡單的例子:
1)前端開發(fā)好后將build構(gòu)建好的dist下的文件拷貝到springboot的resources的static下(boot項目默認沒有static,需要自己新建)
操作步驟:前端vue項目使用命令 npm run build 或者 cnpm run build 打包生成dist文件,在springboot項目中resources下建立static文件夾,將dist文件中的文件復(fù)制到static中,然后去application中跑起來boot項目,這樣直接訪問index.html就可以訪問到頁面(api接口請求地址自己根據(jù)情況打包時配置或者在生成的dist文件中config文件夾中的index.js中配置)
項目結(jié)構(gòu)如圖:

鼠標選中的這幾個就是從dist文件中復(fù)制過來的前端的包,然后我們直接啟動boot項目就可以通過index.html訪問了(ps:上面這是最簡單的合并方式,但是如果作為工程級的項目開發(fā),并不推薦使用手工合并,也不推薦將前端代碼構(gòu)建后提交到springboot的resouce下,好的方式應(yīng)該是保持前后端完全獨立開發(fā)代碼,項目代碼互不影響,借助jenkins這樣的構(gòu)建工具在構(gòu)建springboot時觸發(fā)前端構(gòu)建并編寫自動化腳本將前端webpack構(gòu)建好的資源拷貝到springboot下再進行jar的打包,最后就得到了一個完全包含前后端的springboot項目了。不過上述方法操作簡單,便于使用,如果想一次性打包完成的話,就看第二種)
2:第二種方法是在src/main下建立一個webapp文件夾,然后將前端項目的源文件復(fù)制到該文件夾下,具體結(jié)構(gòu)如圖:

然后使用maven命令執(zhí)行本地node打包命令,這樣就可以 在執(zhí)行mvn clean package命令時,利用maven插件執(zhí)行cnpm run build命令(我是使用的淘寶的鏡像cnpm,國外的npm命令會相對慢一些,大家根據(jù)自己的條件選擇,具體命令請看項目中前端vue文件的README.md),一次性完成整個過程
實現(xiàn)方法是這樣的,我們要引入org.codehaus.mojo插件來進行maven調(diào)用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文件夾中的文件復(fù)制到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實現(xiàn)上傳下載
這里記錄一下在Springboot中實現(xiàn)文件上傳下載的核心代碼
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()){
//檢查到文件不存在則創(chuàng)建
fileDir.mkdir();//創(chuàng)建文件,一級
fileDir.mkdirs();//創(chuàng)建多級
}
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 + "”是否存在");
}
//復(fù)制文件
IOUtils.copy(is,response.getOutputStream());
//刷新緩沖
response.getOutputStream().flush();
}catch (IOException e){
return ResultUtil.error("下載文件失敗,error:" + e.getMessage());
}
//文件的關(guān)閉在finally中執(zhí)行
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
總結(jié)
以上所述是小編給大家介紹的Springboot項目與vue項目整合打包的實現(xiàn)方式,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Java實現(xiàn)文件復(fù)制及文件夾復(fù)制幾種常用的方式
這篇文章主要給大家介紹了關(guān)于Java實現(xiàn)文件復(fù)制及文件夾復(fù)制幾種常用的方式,java復(fù)制文件的方式其實有不少種,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-09-09
Java NIO:淺析IO模型_動力節(jié)點Java學(xué)院整理
在進入Java NIO編程之前,我們今天先來討論一些比較基礎(chǔ)的知識:I/O模型。對java io nio相關(guān)知識感興趣的朋友一起學(xué)習吧2017-05-05
短網(wǎng)址的原理與生成方法(Java實現(xiàn))
這篇文章主要給大家介紹了關(guān)于短網(wǎng)址的原理與生成方法,利用的是Java實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2020-10-10

