Tomcat 9.0.52 不会从 WAR 文件加载项目
Tomcat 9.0.52 won't load project from the WAR file
我最近将 Tomcat 6 升级到 9.0.52,参考
https://blogs.nologin.es/rickyepoderi/index.php?/archives/44-Tomcat-7-and-the-Invoker-Servlet.html
项目已成功部署在我的本地计算机上,但我正在尝试将我的项目部署到远程服务器,但我的 tomcat 抛出“HTTP 状态 404 – 未找到' 每当我尝试使用 WAR 文件进行部署时出错。但是,如果我直接从我的本地 Tomcat 复制 ROOT 文件夹或使用 Eclipse 部署我的项目,项目加载正常。
这是 localhost.out 文件:
06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [test.ctxlistener.InvokerLoadListener]
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at test.ctxlistener.InvokerLoadListener.getClasses(Unknown Source)
at test.ctxlistener.InvokerLoadListener.contextInitialized(Unknown Source)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4768)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5230)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:698)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:696)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:690)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1889)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:583)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:473)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1618)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:319)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:946)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:772)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
Caused by: java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:434)
at java.util.Properties.load0(Properties.java:353)
at java.util.Properties.load(Properties.java:341)
at test.connection.PooledDataSource.<clinit>(Unknown Source)
... 45 more
我查看了我是否在使用任何 old/unnecessary .jars,但这没有帮助。我正在使用 JAVA 8 和 Ant 1.10.5.
我的catalina.out文件中的错误也复制如下:
06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file 06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors 06-Dec-2021 15:04:21.759 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of deployment descriptor [C:\Apache-Tomcat\apache-tomcat-9.0.52\conf\Catalina\localhost\ROOT.xml] has finished in [5,703] ms 06-Dec-2021 15:04:21.759 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 06-Dec-2021 15:04:21.790 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-nio-8443"] 06-Dec-2021 15:04:21.806 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-127.0.0.1-8009"] 06-Dec-2021 15:04:21.806 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [5803] milliseconds
我不确定我在这里遗漏了什么。任何帮助将不胜感激。谢谢!
调用程序的源代码如下:
package test.ctxlistener;
import java.io.File;
import java.net.URL;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class InvokerLoadListener implements ServletContextListener {
/**
* Invoker parameter that defines the packages to search servlets.
* Comma separated list of packages
*/
public static final String PACKAGES_PARAMETER = "invoker.packages";
/**
* Invoker parameter to setup the mapping name. By default is "/servlet/"
*/
public static final String INVOKER_PREFIX_PARAMETER = "invoker.prefix";
/**
* Scans all classes accessible from the context class loader which
* belong to the given package and subpackages.
*
* @param packageName
* @return The list of classes found
*/
private List<Class<?>> getClasses(String packageName)
throws Exception {
String path = packageName.replace('.', '/');
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
assert classLoader != null;
Enumeration<URL> resources = classLoader.getResources(path);
List<String> dirs = new ArrayList<String>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(resource.getFile());
}
TreeSet<String> classes = new TreeSet<String>();
for (String directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
ArrayList<Class<?>> classList = new ArrayList<Class<?>>();
for (String clazz : classes) {
classList.add(Class.forName(clazz));
}
return classList;
}
private TreeSet<String> findClasses(String directory,
String packageName) throws Exception {
TreeSet<String> classes = new TreeSet<String>();
if (directory.startsWith("file:") && directory.contains("!")) {
String[] split = directory.split("!");
URL jar = new URL(split[0]);
try (ZipInputStream zip = new ZipInputStream(jar.openStream())) {
ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().endsWith(".class")) {
String className = entry.getName()
.replaceAll("[$].*", "")
.replaceAll("[.]class", "")
.replace('/', '.');
if (className.startsWith(packageName)) {
classes.add(className);
}
}
}
}
}
File dir = new File(directory);
if (!dir.exists()) {
return classes;
}
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
assert !file.getName().contains(".");
classes.addAll(findClasses(file.getAbsolutePath(),
packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add(packageName
+ '.'
+ file.getName().substring(0,
file.getName().length() - 6));
}
}
}
return classes;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized(ServletContextEvent e)");
ServletContext sc = sce.getServletContext();
String list = sc.getInitParameter(PACKAGES_PARAMETER);
String prefix = sc.getInitParameter(INVOKER_PREFIX_PARAMETER);
if (prefix == null) {
prefix = "/servlet/";
}
if (list != null) {
String[] packages = list.split(",");
for (int i = 0; i < packages.length; i++) {
String packageName = packages[i].trim();
if (packageName.length() > 0) {
// load classes under servlet.invoker
System.out.println("Checking package: " + packageName);
List<Class<?>> classes = null;
try {
classes = getClasses(packageName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Class clazz : classes) {
String mapping = prefix + clazz.getName();
System.out.println(mapping);
ServletRegistration sr = sc.getServletRegistration(clazz.getName());
if ( sr == null ) {
sr = sc.addServlet(clazz.getName(), clazz.getName());}
if ( sr != null ) {
sr.addMapping(mapping);}
}
}
}
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed(ServletContextEvent e)");
}
}
这是一种可能的答案。正如评论者 @piotr-p-karwasz 所提到的,该错误是由于 test.connection.PooledDataSource
中的静态方法失败造成的。
特别是它加载属性文件的位置。
at java.util.Properties.load(Properties.java:341)
这与java.util.Properties$LineReader.readLine
非常相似
根据您的描述,如果您将整个 ROOT 文件夹复制到应用程序启动的新 Tomcat 服务器中,您应该检查是否有配置文件(如 *.properties 文件)在您的项目中,如果 Ant 构建脚本将其正确添加到您的 WAR 文件中。您可以通过将 WAR 文件解压缩到一个临时文件夹中并将其内容与您以前的 Tomcat 版本中的 ROOT 文件夹进行比较来完成此操作。
如果您在问题中提供 test.connection.PooledDataSource
class 来源,您将获得更准确的答案。
我最近将 Tomcat 6 升级到 9.0.52,参考 https://blogs.nologin.es/rickyepoderi/index.php?/archives/44-Tomcat-7-and-the-Invoker-Servlet.html
项目已成功部署在我的本地计算机上,但我正在尝试将我的项目部署到远程服务器,但我的 tomcat 抛出“HTTP 状态 404 – 未找到' 每当我尝试使用 WAR 文件进行部署时出错。但是,如果我直接从我的本地 Tomcat 复制 ROOT 文件夹或使用 Eclipse 部署我的项目,项目加载正常。
这是 localhost.out 文件:
06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [test.ctxlistener.InvokerLoadListener]
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at test.ctxlistener.InvokerLoadListener.getClasses(Unknown Source)
at test.ctxlistener.InvokerLoadListener.contextInitialized(Unknown Source)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4768)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5230)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:698)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:696)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:690)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1889)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:583)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:473)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1618)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:319)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:946)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:772)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
Caused by: java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:434)
at java.util.Properties.load0(Properties.java:353)
at java.util.Properties.load(Properties.java:341)
at test.connection.PooledDataSource.<clinit>(Unknown Source)
... 45 more
我查看了我是否在使用任何 old/unnecessary .jars,但这没有帮助。我正在使用 JAVA 8 和 Ant 1.10.5.
我的catalina.out文件中的错误也复制如下:
06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file 06-Dec-2021 15:04:21.712 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors 06-Dec-2021 15:04:21.759 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of deployment descriptor [C:\Apache-Tomcat\apache-tomcat-9.0.52\conf\Catalina\localhost\ROOT.xml] has finished in [5,703] ms 06-Dec-2021 15:04:21.759 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 06-Dec-2021 15:04:21.790 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-nio-8443"] 06-Dec-2021 15:04:21.806 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-127.0.0.1-8009"] 06-Dec-2021 15:04:21.806 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [5803] milliseconds
我不确定我在这里遗漏了什么。任何帮助将不胜感激。谢谢!
调用程序的源代码如下:
package test.ctxlistener;
import java.io.File;
import java.net.URL;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class InvokerLoadListener implements ServletContextListener {
/**
* Invoker parameter that defines the packages to search servlets.
* Comma separated list of packages
*/
public static final String PACKAGES_PARAMETER = "invoker.packages";
/**
* Invoker parameter to setup the mapping name. By default is "/servlet/"
*/
public static final String INVOKER_PREFIX_PARAMETER = "invoker.prefix";
/**
* Scans all classes accessible from the context class loader which
* belong to the given package and subpackages.
*
* @param packageName
* @return The list of classes found
*/
private List<Class<?>> getClasses(String packageName)
throws Exception {
String path = packageName.replace('.', '/');
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
assert classLoader != null;
Enumeration<URL> resources = classLoader.getResources(path);
List<String> dirs = new ArrayList<String>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(resource.getFile());
}
TreeSet<String> classes = new TreeSet<String>();
for (String directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
ArrayList<Class<?>> classList = new ArrayList<Class<?>>();
for (String clazz : classes) {
classList.add(Class.forName(clazz));
}
return classList;
}
private TreeSet<String> findClasses(String directory,
String packageName) throws Exception {
TreeSet<String> classes = new TreeSet<String>();
if (directory.startsWith("file:") && directory.contains("!")) {
String[] split = directory.split("!");
URL jar = new URL(split[0]);
try (ZipInputStream zip = new ZipInputStream(jar.openStream())) {
ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().endsWith(".class")) {
String className = entry.getName()
.replaceAll("[$].*", "")
.replaceAll("[.]class", "")
.replace('/', '.');
if (className.startsWith(packageName)) {
classes.add(className);
}
}
}
}
}
File dir = new File(directory);
if (!dir.exists()) {
return classes;
}
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
assert !file.getName().contains(".");
classes.addAll(findClasses(file.getAbsolutePath(),
packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add(packageName
+ '.'
+ file.getName().substring(0,
file.getName().length() - 6));
}
}
}
return classes;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized(ServletContextEvent e)");
ServletContext sc = sce.getServletContext();
String list = sc.getInitParameter(PACKAGES_PARAMETER);
String prefix = sc.getInitParameter(INVOKER_PREFIX_PARAMETER);
if (prefix == null) {
prefix = "/servlet/";
}
if (list != null) {
String[] packages = list.split(",");
for (int i = 0; i < packages.length; i++) {
String packageName = packages[i].trim();
if (packageName.length() > 0) {
// load classes under servlet.invoker
System.out.println("Checking package: " + packageName);
List<Class<?>> classes = null;
try {
classes = getClasses(packageName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Class clazz : classes) {
String mapping = prefix + clazz.getName();
System.out.println(mapping);
ServletRegistration sr = sc.getServletRegistration(clazz.getName());
if ( sr == null ) {
sr = sc.addServlet(clazz.getName(), clazz.getName());}
if ( sr != null ) {
sr.addMapping(mapping);}
}
}
}
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed(ServletContextEvent e)");
}
}
这是一种可能的答案。正如评论者 @piotr-p-karwasz 所提到的,该错误是由于 test.connection.PooledDataSource
中的静态方法失败造成的。
特别是它加载属性文件的位置。
at java.util.Properties.load(Properties.java:341)
这与java.util.Properties$LineReader.readLine
非常相似根据您的描述,如果您将整个 ROOT 文件夹复制到应用程序启动的新 Tomcat 服务器中,您应该检查是否有配置文件(如 *.properties 文件)在您的项目中,如果 Ant 构建脚本将其正确添加到您的 WAR 文件中。您可以通过将 WAR 文件解压缩到一个临时文件夹中并将其内容与您以前的 Tomcat 版本中的 ROOT 文件夹进行比较来完成此操作。
如果您在问题中提供 test.connection.PooledDataSource
class 来源,您将获得更准确的答案。