当我将Webapp部署到Tomcat时,我遇到一个奇怪的错误,即我认为类加载器存在问题。当我使用Jetty在本地运行Webapp时,该错误没有出现。似乎我的.yml资源文件的输入流由于某些原因而被关闭,而实际上不应该这样做。当我尝试将单模块项目转换为多模块项目时,首次出现此错误。在此之前,它使用完全相同的代码在Tomcat上运行良好:
Caused by: org.yaml.snakeyaml.error.YAMLException: java.io.IOException: Stream closed at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:200) at org.yaml.snakeyaml.reader.StreamReader.<init>(StreamReader.java:60) at org.yaml.snakeyaml.Yaml.load(Yaml.java:412) at com.config.ConfigProvider.<init>(ConfigProvider.java:20) ... 49 more Caused by: java.io.IOException: Stream closed at java.io.PushbackInputStream.ensureOpen(PushbackInputStream.java:57) at java.io.PushbackInputStream.read(PushbackInputStream.java:149) at org.yaml.snakeyaml.reader.UnicodeReader.init(UnicodeReader.java:90) at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:122) at java.io.Reader.read(Reader.java:123) at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:184) ... 55 more
这是导致该错误的行:
String s = ConfigProvider.getConfig().getString("test");
这是ConfigProvider课程。它基本上扫描正则表达式的所有资源文件^.*\\.config\\.yml$,将其转换为Map<String, Object>,并将所有获取的文件Map<String, Object>合并为一个Map<String, Object>:
ConfigProvider
^.*\\.config\\.yml$
Map<String, Object>
1 public class ConfigProvider { 2 protected static final String CONFIG_PACKAGE = ConfigProvider.class.getPackage().getName(); 3 protected static final Pattern CONFIG_PATH_REGEX = Pattern.compile("^.*\\.config\\.yml$"); 4 5 private static final ConfigProvider INSTANCE = new ConfigProvider(); 6 private Map<String, Object> configMap; 7 8 protected ConfigProvider() { 9 configMap = new HashMap<String, Object>(); 10 11 Set<String> configPaths = new Reflections(CONFIG_PACKAGE, 12 new ResourcesScanner()).getResources(CONFIG_PATH_REGEX); 13 14 if (configPaths.isEmpty()) { 15 throw new RuntimeException("no config paths found"); 16 } 17 18 for (String path : configPaths) { 19 InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); 20 Map<String, Object> fullConfig = new Map<String, Object>((Map) new Yaml().load(inputStream)); 21 22 try { 23 inputStream.close(); 24 } catch (IOException e) { 25 throw new RuntimeException("error closing stream"); 26 } 27 28 MapUtils.merge(configMap, fullConfig); 29 } 30 } 31 32 public static ConfigMap getConfig() { 33 return INSTANCE.configMap; 34 } 35 }
这是我的项目结构,名为Foo:
- Foo (this is a module) - .idea - application (this is a module) - src - main - java - resources - application.config.yml - webapp - test - pom.xml - client (this is a module) - src - main - java - resources - client.config.yml - webapp - test - pom.xml - pom.xml
ConfigProvider是我从父pom文件(Foo/pom.xml)获得的类。我WAR从application模块(Foo/application/target/application.war)中打包了一个文件,然后将其与Tomcat一起部署。以前,我的项目是单个模块项目,只有一个Foo模块与application模块相同。然后,我添加了一个client模块,并将项目转换为多模块项目,问题出现了。我认为这是因为多个模块使我的类加载器变得一团糟。我已经花了很多时间尝试调试它,但是仍然没有找到任何地方。任何人都知道可能是什么原因,或者可以考虑尝试的可能方法吗?
Foo/pom.xml
WAR
application
Foo/application/target/application.war
Foo
client
如果您需要更多信息,请告诉我。
根据这篇文章,该异常可能意味着.yml根本找不到该文件。由于您更改了项目结构,因此可能configPaths需要针对新结构修改用于构建需求的逻辑。您是否尝试记录的内容configPaths以查看新结构的路径是否正确?
.yml
configPaths
还要确保.yml文件包含在.war文件中。某些构建系统对资源的处理方式与Java类文件不同。
.war