package com.uas.report; 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 java.io.*; import java.net.URL; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * 不使用spring boot内嵌的容器,部署在自定义Tomcat下时的程序入口 * * @author sunyj * @since 2017年1月11日 下午5:18:41 */ @SpringBootApplication(scanBasePackages = "com.uas.report") @EnableWebMvc public class Application extends SpringBootServletInitializer implements ApplicationContextAware { private static Logger logger = LoggerFactory.getLogger(Application.class); @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { try { File logFile = new File("logs/log.log"); if (!logFile.getParentFile().exists()) { logFile.getParentFile().mkdir(); } System.setErr(new PrintStream(new FileOutputStream(logFile, true))); } catch (FileNotFoundException e) { logger.error("", e); } // 程序入口 return builder.sources(Application.class); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 注册spring上下文对象 ContextUtils.setApplicationContext(applicationContext); logger.info("ApplicationContext registed"); // 开启定时任务 ReportUtils.startTask(); } public static void main(String[] args) throws IOException { new SpringApplication(Application.class).run(args); setCompilerClasspath(); } /** * 设置 japser 的 {@link JRCompiler#COMPILER_CLASSPATH} *

* 以 spring boot jar 形式运行时,才需要设置 *

* 因为导出为 word 时,需要动态编译 java 文件 {@link JasperCompileManager#compile(net.sf.jasperreports.engine.design.JasperDesign)} *

* 而以 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 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(); } } } } } }