Bläddra i källkod

support run as an executable jar

sunyj 8 år sedan
förälder
incheckning
6037cec7f3

+ 11 - 8
pom.xml

@@ -16,7 +16,6 @@
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<oracle.jdbc.version>11.2.0</oracle.jdbc.version>
-		<servlet.version>3.0-alpha-1</servlet.version>
 		<druid.version>1.0.24</druid.version>
 		<jasperreports.version>6.4.0</jasperreports.version>
 		<jasperreports-functions.version>6.3.0</jasperreports-functions.version>
@@ -35,6 +34,10 @@
 	</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-security</artifactId>
@@ -67,13 +70,6 @@
 			</exclusions>
 		</dependency>
 
-		<dependency>
-			<groupId>javax.servlet</groupId>
-			<artifactId>servlet-api</artifactId>
-			<version>${servlet.version}</version>
-			<scope>provided</scope>
-		</dependency>
-
 		<dependency>
 			<groupId>com.alibaba</groupId>
 			<artifactId>druid</artifactId>
@@ -385,6 +381,13 @@
 					</webResources>
 				</configuration>
 			</plugin>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>com.uas.report.Application</mainClass>
+                </configuration>
+			</plugin>
 		</plugins>
 		<pluginManagement>
 			<plugins>

+ 85 - 7
src/main/java/com/uas/report/Application.java

@@ -1,22 +1,28 @@
 package com.uas.report;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
+import com.uas.report.util.ContextUtils;
+import com.uas.report.util.FileUtils;
+import com.uas.report.util.ReportUtils;
+import net.sf.jasperreports.engine.DefaultJasperReportsContext;
+import net.sf.jasperreports.engine.JasperCompileManager;
+import net.sf.jasperreports.engine.design.JRCompiler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeansException;
+import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.support.SpringBootServletInitializer;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
+import org.springframework.util.ResourceUtils;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 
-import com.uas.report.util.ContextUtils;
-import com.uas.report.util.ReportUtils;
+import java.io.*;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 /**
  * 不使用spring boot内嵌的容器,部署在自定义Tomcat下时的程序入口
@@ -53,4 +59,76 @@ public class Application extends SpringBootServletInitializer implements Applica
 		// 开启定时任务
 		ReportUtils.startTask();
 	}
+
+	public static void main(String[] args) throws IOException {
+		new SpringApplication(Application.class).run(args);
+		setCompilerClasspath();
+	}
+
+	/**
+	 * 设置 japser 的 {@link JRCompiler#COMPILER_CLASSPATH}
+	 * <p/>
+	 * 以 spring boot jar 形式运行时,才需要设置
+	 * <p/>
+	 * 因为导出为 word 时,需要动态编译 java 文件 {@link JasperCompileManager#compile(net.sf.jasperreports.engine.design.JasperDesign)}
+	 * <p/>
+	 * 而以 spring boot jar 形式运行时, classpath 为 war 包名,javac -classpath 编译失败
+	 *
+	 * @throws IOException
+	 */
+	private static void setCompilerClasspath() throws IOException {
+		URL location = Application.class.getProtectionDomain().getCodeSource().getLocation();
+		// 是否以 spring boot jar 形式运行
+		if (ResourceUtils.isJarURL(location)) {
+			// 提取 war 中的 jar 包到指定路径
+			File warFile = ResourceUtils.getFile(ResourceUtils.extractJarFileURL(location));
+			String libDir = ReportUtils.getLibDir();
+			extractLib(warFile, new File(libDir));
+			// 将提取的 jar 路径添加到 COMPILER_CLASSPATH
+			String compilerClasspath = System.getProperty("java.class.path") + File.pathSeparator + libDir + File.separator + "*";
+			DefaultJasperReportsContext.getInstance().setProperty(JRCompiler.COMPILER_CLASSPATH, compilerClasspath);
+		}
+	}
+
+	/**
+	 * 提取 war 中的 jar
+	 *
+	 * @param warFile war 文件
+	 * @param libDir  提取的 jar 所存放的路径
+	 * @throws IOException
+	 */
+	private static void extractLib(File warFile, File libDir) throws IOException {
+		if (libDir.isFile()) {
+			throw new IOException("路径并非文件夹");
+		}
+		// 删除旧的文件
+		FileUtils.delete(libDir);
+		if (!libDir.exists()) {
+			libDir.mkdirs();
+		}
+		ZipFile zipFile = new ZipFile(warFile);
+		Enumeration<? extends ZipEntry> entries = zipFile.entries();
+		while (entries.hasMoreElements()) {
+			ZipEntry zipEntry = entries.nextElement();
+			// 只提取 jasperreports-$version.jar
+			if (zipEntry.getName().matches("[\\s\\S]*?jasperreports-[\\d.]+?.jar")) {
+				logger.info("extract... " + zipEntry.getName());
+				try (InputStream inputStream = zipFile.getInputStream(zipEntry)) {
+					String name = zipEntry.getName();
+					if (name.lastIndexOf("/") != -1) {
+						name = name.substring(name.lastIndexOf("/") + 1);
+					}
+					try (OutputStream outputStream = new FileOutputStream(new File(libDir, name))) {
+						byte[] buffer = new byte[32 * 1024];
+						int bytesRead;
+						while ((bytesRead = inputStream.read(buffer)) != -1) {
+							outputStream.write(buffer, 0, bytesRead);
+						}
+						outputStream.flush();
+					}
+				}
+			}
+		}
+	}
+
 }

+ 1 - 1
src/main/java/com/uas/report/service/impl/FileServiceImpl.java

@@ -592,7 +592,7 @@ public class FileServiceImpl implements FileService {
 		Executable command = new Executable() {
 			@Override
 			public String execute() {
-				FileUtils.delete(new File(ReportUtils.getTmpDir()), new FileFilter() {
+				FileUtils.delete(new File(ReportUtils.getGenerateDir()), new FileFilter() {
 					@Override
 					public boolean accept(File file) {
 						// 只删除已过期的文件(并且刚过期的文件本次不删除,以尽量避免打印耗时过长时,部分临时文件过期而被误删)

+ 18 - 4
src/main/java/com/uas/report/util/ReportUtils.java

@@ -49,21 +49,35 @@ public class ReportUtils {
 	/**
 	 * @return 临时路径
 	 */
-	public static String getTmpDir() {
-		return ContextUtils.getBean(FileService.class).getMasterPath("tmp") + "/generate";
+	private static String getTmpDir() {
+		return ContextUtils.getBean(FileService.class).getMasterPath("tmp");
+	}
+
+	/**
+	 * @return 存放 pdf、虚拟文件等文件的路径
+	 */
+	public static String getGenerateDir() {
+		return getTmpDir() + "/generate";
 	}
 
 	/**
 	 * @return 文件虚拟路径
 	 */
 	public static String getVirtualizerDir() {
-		return getTmpDir() + "/virtualizer";
+		return getGenerateDir() + "/virtualizer";
 	}
 
 	/**
 	 * @return pdf、excel 等文档路径
 	 */
 	public static String getDocumentDir() {
-		return getTmpDir() + "/documents";
+		return getGenerateDir() + "/documents";
+	}
+
+	/**
+	 * @return 存放 lib 的临时路径
+	 */
+	public static String getLibDir() {
+		return getTmpDir() + "/lib";
 	}
 }