单个 tomcat 下运行多个 war 应用, 问题与解决方法
公司内有两个 Java web 应用,最近需要去客户处展示,需要安装在一台笔记本电脑上。
两个 Java web 应用,都有些年头了,最初使用 Java 1.6 开发,现使用 Java 8 重新编译。
有一台 16G 内存、500G 硬盘的笔记本,惠普战66。尝试将两个Java web 应用安装在此电脑里同一个 tomcat 内。
想着很简单,打包成 war 文件(分别是 zsso.war, pkg.war), 复制到 C:\java\apache-tomcat-9.0.52\webapps 目录下,改些配置文件,启动 tomcat 的 bin\startup.bat , 应该就行了。
其中,zsso.war 是公司的一个单点登录软件产品,自带用户登录、权限配置等功能。此次是 pkg.war 更改时间紧张,不想再去动权限配置功能,想着可以借用 zsso.war 的功能,节省点开发时间,就算免费送客户一套单点登录系统好了。节省了开发时间,也是好的。
结果运行报错,pkg 能启动起来,zsso 启动失败,tomcat 自带的 docs, examples, host-manager,manager,ROOT 几个应用也启动失败。报错信息相同,均为 XML 解析的 class 找不到:
1 org.apache.catalina.LifecycleException: Failed to initialize component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/zsso]] 2 at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:112) 3 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140) 4 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752) 5 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728) 6 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734) 7 at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:986) 8 at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857) 9 at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) 10 at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) 11 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) 12 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) 13 at java.base/java.lang.Thread.run(Thread.java:832) 14 Caused by: javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found 15 at java.xml/javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:194) 16 at java.xml/javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:147) 17 at java.xml/javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:226) 18 at java.xml/javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:219) 19 at org.apache.tomcat.util.digester.Digester.getFactory(Digester.java:474) 20 at org.apache.tomcat.util.digester.Digester.getParser(Digester.java:665) 21 at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:730) 22 at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:310) 23 at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94) 24 at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:395) 25 at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:108) 26 ... 11 more 27 Caused by: java.lang.ClassNotFoundException: org/apache/xerces/jaxp/SAXParserFactoryImpl 28 at java.base/java.lang.Class.forName0(Native Method) 29 at java.base/java.lang.Class.forName(Class.java:427) 30 at java.xml/javax.xml.parsers.FactoryFinder.getProviderClass(FactoryFinder.java:119) 31 at java.xml/javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:183) 32 ... 21 more
查 tomcat 文档,http://tomcat.apache.org/tomcat-9.0-doc/class-loader-howto.html,里面专门有一章节 "XML Parsers and Java"。虽然没看明白,这个与我们此次报错有什么关联。但猜测,Java 中的 XML 解析相关类,与 class loader 紧密相关。
经调查,pkg.war 中使用了 SAX XML 解析,而 zsso.war 中没有使用。
推测 pkg.war 中使用了 SAX XML 解析,用了某个特定方式,导致影响了 zsso.war,也影响了 tomcat 自带的几个 web 应用及示例。
查找代码,有如下:
1 System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl"); 2 3 SAXParserFactory parserFactory = SAXParserFactory.newInstance(); 4 parserFactory.setValidating(false); 5 parserFactory.setNamespaceAware(false); 6 7 RefrenceHandler mySaxParser = new RefrenceHandler(); 8 SAXParser parser = parserFactory.newSAXParser(); 9 parser.parse(refIs, mySaxParser);
经测试,去掉第一行代码,问题解决。
最后回顾:
代码行:
System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
影响了 tomcat 中的多个 war 应用,也影响了 tomcat 自带的几个 web 应用及示例。
之前 Java 1.6 时,需要此行代码。最新的 Java 8 ,不需要此行代码。
因此,Java web 代码中,应避免/减少使用 System.setProperty(...);
======欢迎转载,转载请注明出处, https://www.cnblogs.com/jacklondon/