Spring Boot应用中Aspose License加载后无法生效问题求助
我开发了一个带公共REST API的Spring Boot应用,用于提取指定PDF文件的文本。通过AsposeLicenseLoader类的静态方法加载Aspose许可证,日志显示加载完成,但执行PDF文本提取时,输出仍带有评估版水印:
Evaluation Only. Created with Aspose.Pdf. Copyright 2002-2017 Aspose Pty Ltd.
许可证加载代码:
public class AsposeLicenseLoader { private static Logger logger = LoggerFactory.getLogger(AsposeLicenseLoader.class); private static boolean isLicenseLoaded; public static void doLoad(AsposeConfig asposeConfig) { String location = asposeConfig.license().location(); logger.debug("Loading Aspose license \"{}\""); try (InputStream is = AsposeLicenseLoader.class.getClassLoader() .getResourceAsStream(location)) { com.aspose.pdf.License pdfLicense = new com.aspose.pdf.License(); pdfLicense.setLicense(is); isLicenseLoaded = true; logger.info("Aspose license loading completed"); } catch (Exception e) { logger.error("Unable to load the Aspose license", e); } } public static boolean isAsposeLicenseLoaded() { return isLicenseLoaded; } }
PDF文本提取逻辑:
com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document(filePath); // Create TextAbsorber object to extract text com.aspose.pdf.TextAbsorber textAbsorber = new com.aspose.pdf.TextAbsorber(); // Accept the absorber for all the pages pdfDocument.getPages().accept(textAbsorber); // Get the extracted text extractedText = textAbsorber.getText();
但如果在每次提取文本前显式加载许可证,就能正常提取无水印的完整文本。根据Aspose官方文档,许可证只需加载一次即可,无需每次请求都加载,想排查操作中的错误点。
1. 许可证加载时机过晚
如果许可证加载操作在第一次PDF提取之后才执行,第一个请求会触发Aspose的评估模式,后续即使加载许可证,也可能因为静态状态未正确覆盖而继续显示水印。
解决办法:
在应用启动的最早期执行许可证加载,比如通过Spring的@PostConstruct注解在Bean初始化时加载:
@Component public class AsposeLicenseInitializer { private final AsposeConfig asposeConfig; public AsposeLicenseInitializer(AsposeConfig asposeConfig) { this.asposeConfig = asposeConfig; } @PostConstruct public void initLicense() { if (!AsposeLicenseLoader.isAsposeLicenseLoaded()) { AsposeLicenseLoader.doLoad(asposeConfig); } } }
2. 许可证文件未正确读取
原代码中未验证getResourceAsStream返回的输入流是否为null,如果文件路径错误或文件不存在,可能导致许可证加载静默失败,但日志仍显示“加载完成”。此外,原debug日志未填充location参数,无法确认实际加载的路径。
解决办法:
修改doLoad方法,增加输入流非空判断,同时验证许可证是否真正生效:
public class AsposeLicenseLoader { private static Logger logger = LoggerFactory.getLogger(AsposeLicenseLoader.class); private static boolean isLicenseLoaded; private static final Object lock = new Object(); // 增加锁避免多线程重复加载 public static void doLoad(AsposeConfig asposeConfig) { synchronized (lock) { if (isLicenseLoaded) { logger.debug("Aspose license already loaded, skip loading"); return; } String location = asposeConfig.license().location(); logger.debug("Loading Aspose license from \"{}\"", location); // 补全日志参数 try (InputStream is = AsposeLicenseLoader.class.getClassLoader() .getResourceAsStream(location)) { if (is == null) { logger.error("Aspose license file not found at location: {}", location); return; } com.aspose.pdf.License pdfLicense = new com.aspose.pdf.License(); pdfLicense.setLicense(is); // 验证许可证是否生效 boolean licenseValid = pdfLicense.isLicensed(); isLicenseLoaded = licenseValid; if (licenseValid) { logger.info("Aspose license loaded successfully"); } else { logger.warn("Aspose license file exists but is invalid"); } } catch (Exception e) { logger.error("Failed to load Aspose license", e); isLicenseLoaded = false; } } } public static boolean isAsposeLicenseLoaded() { return isLicenseLoaded; } }
3. 类加载器隔离问题
如果加载许可证的AsposeLicenseLoader类和使用Document类的代码由不同的类加载器加载,Aspose的许可证静态状态无法共享,导致提取时仍处于评估模式。
解决办法:
在加载许可证和提取文本的代码中添加类加载器日志,确认一致性:
// 在doLoad方法中添加 logger.debug("AsposeLicenseLoader class loader: {}", AsposeLicenseLoader.class.getClassLoader()); logger.debug("com.aspose.pdf.License class loader: {}", com.aspose.pdf.License.class.getClassLoader()); // 在文本提取代码中添加 logger.debug("com.aspose.pdf.Document class loader: {}", com.aspose.pdf.Document.class.getClassLoader());
如果类加载器不同,需确保Aspose的依赖jar包被同一个类加载器加载,比如调整Spring Boot的依赖配置,避免将Aspose依赖放在隔离的类路径下。
4. 多线程并发加载问题
如果多个线程同时调用doLoad方法,可能导致isLicenseLoaded被错误设置为true,但实际许可证未加载完成。
解决办法:
通过添加同步锁(如上述修改中的lock对象),确保许可证只被加载一次,且加载过程是原子性的。
内容的提问来源于stack exchange,提问作者user18905365

