[英]Spring boot WAR runs from maven, not from command line?
我檢查了這個問題 ,但是答案(雖然很有趣)基本上說“不要使用WAR包裝”,這不是這里的選擇。
我有一個使用嵌入式Tomcat(Spring Boot 1.5.3.RELEASE,嵌入式Tomcat 8.5.14)的經過重新包裝的Spring Boot WAR。 重新包裝的應用程序可以使用mvn spring-boot:run
命令mvn spring-boot:run
但是當我嘗試使用`java -jar target \\ mywar.war'來運行它時,我得到了:
java.io.FileNotFoundException: file:\C:\work\spring-boot\target\spring-boot-mywar.war!\WEB-INF\classes!\mywar.war (The filename, directory name, or volume label syntax is incorrect)
這是由於Spring Boot嘗試加載“包裝”戰爭的上下文而引起的:
Context context = tomcat.addWebapp("/mywar", Thread.currentThread().getContextClassLoader().getResource("mywar.war").getPath());
實際錯誤發生在嵌入式Tomcat類內部:
private URL getWebappConfigFileFromJar(File docBase, String contextName) {
URL result = null;
try (JarFile jar = new JarFile(docBase)) {
JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
if (entry != null) {
result = UriUtil.buildJarUrl(docBase, Constants.ApplicationContextXml);
}
} catch (IOException e) {
Logger.getLogger(getLoggerName(getHost(), contextName)).log(Level.WARNING,
"Unable to determine web application context.xml " + docBase, e);
}
return result;
}
操作new JarFile(docBase)
拋出FileNotFoundException
。
當使用Maven spring-boot:run
目標時,這可以很好地工作,所以我覺得基本結構是合理的-我認為存在一些類路徑問題或某些使它無法工作的問題。
有沒有人建議在使用WAR打包時在命令行上復制spring-boot:run
環境?
對於spring boot應用程序,您可以使用mvn spring-boot:run
,使用java -jar thePackage.war
或將war軟件包放入tomcat Webapps中。 每種方法都可以運行您的應用程序。
所以我認為您的項目中存在一些問題。 確保您的pom文件中包含spring-boot-maven-plugin
。 然后,當您使用mvn package
,應該看到一些有關repackage的日志。 如果解包war文件,則應該看到一些目錄,例如:“ META-INFO”和“ BOOT-INF”。
探索了插件的實際spring-boot:run目標后,發現它會重建項目並從target/classes
文件夾中的已編譯類啟動應用程序。 它似乎根本沒有使用WAR文件:
[INFO] --- spring-boot-maven-plugin:1.5.3.RELEASE:run (default-cli) @ spring-boot-app ---
11:58:55.526 [main] INFO app.MyApplication - Beginning run() of MyApplication
2017-05-22 11:58:55.791 DEBUG 4140 --- [ main] .b.l.ClasspathLoggingApplicationListener : Application started with classpath: [file:/C:/work/myapp/target/classes/....[SNIP]
WAR無法運行的原因是未提取內部包含的應用程序WAR文件並將其寫入嵌入式Tomcat上下文。 手動提取“內部WAR”並將其寫入上下文位置可解決此問題:
/**
* Utility method which exports and unpacks the WAR file into the Tomcat context directory
* @param warName
* @param contextPath
* @return
* @throws IOException
* @throws URISyntaxException
*/
private static String exportWar(String warName, String contextPath) throws IOException, URISyntaxException {
log.info("Beginning export WAR");
try {
UnzipUtility unzipUtility = new UnzipUtility();
unzipUtility.unzip(warName, contextPath);
} catch (IOException ex) {
throw ex;
}
return contextPath + warName;
}
這是UnzipUtility,基於codejava.net的示例:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* This utility extracts files and directories of a standard zip file to
* a destination directory.
* @author www.codejava.net
*
*/
public class UnzipUtility {
/**
* Size of the buffer to read/write data
*/
private static final int BUFFER_SIZE = 4096;
public void unzip(String zipFileName, String destDirectory) throws IOException {
File destDir = new File(destDirectory);
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn = new ZipInputStream(Thread.currentThread().getContextClassLoader().getResourceAsStream(zipFileName));
ZipEntry entry = zipIn.getNextEntry();
// iterates over entries in the zip file
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
// if the entry is a file, extracts it
ensureParentExists(filePath);
extractFile(zipIn, filePath);
} else {
// if the entry is a directory, make the directory
File dir = new File(filePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
/**
* Extracts a zip entry (file entry)
* @param zipIn
* @param filePath
* @throws IOException
*/
private void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] bytesIn = new byte[BUFFER_SIZE];
int read = 0;
while ((read = zipIn.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
bos.close();
}
private void ensureParentExists(String filePath) {
File parent = new File(filePath).getParentFile();
if ( parent != null && !parent.exists()) {
// parent of parent - recursive
ensureParentExists(parent.getPath());
// make this dir
parent.mkdir();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.