1

嗨..我已经在 Tomacat5.x 中部署了 my.war,因为我使用的是 java1.5 。当时 CentOS 中的 JAVA_HOME=java5path 和 CATALINA_HOME=tomcat5.x 路径。它工作得很好。

现在我的问题是,

我在 Tomcat7.x 中使用 JAVA_HOME=java1.7 和 CATALINE_HOME=tomcat7.x 部署相同的战争我收到以下错误

java.lang.ClassNotFoundException: org.apache.catalina.servlets.InvokerServlet
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)...

同样,我也在 java1.7 中编译了代码并部署在 Tomcat7 中。同样的错误。有人可以建议我如何克服这个问题吗?

谢谢。

4

3 回答 3

1

从 Tomcat 7 开始支持新的 Servlet 标准 3.0 版,我们必须注册所有内部使用的 servlet 类。这是出于安全目的。

Tomcat 6 及以下,web.xml

<servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>
      org.apache.catalina.servlets.InvokerServlet
    </servlet-class>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>invoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
</servlet-mapping>

Tomcat 7 及以上

<listener>
    <listener-class>
        com.test.MyServletContextListener
    </listener-class>
</listener>
<context-param>
    <param-name>com.package</param-name>
    <param-value>
        com.test.servlet,
        com.example.application,
     </param-value>
    <description>servlet implemented packages</description>
</context-param>

在 MyServletContextListener.java 中扩展ServletContextListener并获取所有类并使用(覆盖)contextInitialized 方法进行注册,如下面的示例片段。

for (Class clazz : classes) {
        String mapping = prefix + clazz.getName();
        ServletRegistration sr = sc.addServlet(clazz.getName(), clazz.getName());
        sr.addMapping(mapping);
    }
于 2013-12-24T10:33:33.263 回答
0

我认为tomcat 7,支持1.6及以上版本。

见这里:http: //tomcat.apache.org/whichversion.html

于 2013-12-24T09:56:32.683 回答
0

我在从 Tomcat 6 迁移到 Tomcat 7 时遇到了这个问题。Ricky over-here改进了一个几乎对我有用的解决方案。我必须改进它才能为我工作。我改变了他的听众小赌注,它就像一个魅力。我希望它可以帮助其他人:

    
    导入java.io.File;
    导入 java.io.IOException;
    导入 java.net.JarURLConnection;
    导入 java.net.URL;
    导入 java.util.Enumeration;
    导入 java.util.HashSet;
    导入 java.util.Set;
    导入 java.util.jar.JarEntry;
    导入 java.util.jar.JarFile;
    导入 javax.servlet.ServletContext;
    导入 javax.servlet.ServletContextEvent;
    导入 javax.servlet.ServletContextListener;
    导入 javax.servlet.ServletRegistration;
    导入 javax.servlet.http.HttpServlet;
    导入 org.apache.catalina.ContainerServlet;

    /**
     *
     * http://snippets.dzone.com/posts/show/4831
     *
     * @作者瑞奇
     */
    公共类 InvokerLoadListener 实现 ServletContextListener {

        /**
         * 定义包以搜索 servlet 的调用程序参数。
         * 逗号分隔的软件包列表
         */
        公共静态最终字符串 PACKAGES_PARAMETER = "invoker.packages";
        
        /**
         * 调用者参数设置映射名称。默认情况下是“/servlet/”
         */
        公共静态最终字符串 INVOKER_PREFIX_PARAMETER = "invoker.prefix";

        /**
         * 扫描可从上下文类加载器访问的所有类
         * 属于给定的包和子包。
         *
         * @param 包名
         * @return 找到的类列表
         */
        私人设置getClasses(字符串包名){
            设置类 = new HashSet();
            尝试 {
                类加载器 classLoader = Thread.currentThread().getContextClassLoader();
                字符串路径 = packageName.replace('.', '/');
                枚举资源 = classLoader.getResources(path);
                而(资源.hasMoreElements()){
                    URL 资源 = resources.nextElement();
                    if (resource.getProtocol().equals("jar")) {
                        // 在 jar 中 => 读取 jar 文件并检查
                        findClassesJar(资源、路径、类);
                    } else if (resource.getProtocol().equals("file")) {
                        // 读取子目录并找到
                        findClassesFile(new File(resource.getFile()), packageName, classes);
                    } 别的 {
                        System.err.println("未知协议连接:" + 资源);
                    }
                }
            } 捕捉(IOException e){
                e.printStackTrace();
            }
            返回课程;
        }

        /**
         * 读取一个jar文件并检查其中的所有类与包
         * 指定名称。
         *
         * @param resource 资源地址
         * @param 路径
         * @param 类
         * @返回
         */
        private Set findClassesJar(URL resource, String path, Set classes) {
            JarURLConnection jarConn = null;
            JarFile jar = null;
            尝试 {
                jarConn = (JarURLConnection) 资源.openConnection();
                jar = jarConn.getJarFile();
                枚举 e = jar.entries();
                而(e.hasMoreElements()){
                    JarEntry entry = e.nextElement();
                    if ((entry.getName().startsWith(path + "/")
                            || entry.getName().startsWith(path + "."))
                            && entry.getName().endsWith(".class")) {
                        字符串名称 = entry.getName().replace('/', '.');
                        name = name.substring(0, name.length() - 6);
                        checkClass(名称,类);
                    }
                }
            } 捕捉(IOException e){
                e.printStackTrace();
            } 最后 {
                尝试 {
                    jar.close();
                } 捕捉(IOException e){
                }
            }
            返回课程;
        }

        /**
         * 用于查找给定文件中所有类的递归方法(文件
         * 或目录)。
         *
         * @param file 基本目录
         * @param packageName 在基目录中找到的类的包名
         * @classes 类列表
         * @return 相同的类
         * @throws ClassNotFoundException
         */
        private Set findClassesFile(File file, String packageName, Set classes) {
            if (file.isFile() && file.getName().endsWith(".class")) {
                //classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
                checkClass(packageName.substring(0, packageName.length() - 6), 类);
            } 别的 {
                文件[] 文件 = file.listFiles();
                如果(文件!= null){
                    对于(文件 f:文件){
                        findClassesFile(f, packageName + "." + f.getName(), classes);
                    }
                }
            }
            返回课程;
        }

        私人设置检查类(字符串名称,设置类){
            尝试 {
                类 clazz = Class.forName(name);
                //将AND更改为OR
                if (HttpServlet.class.isAssignableFrom(clazz)
                        || ContainerServlet.class.isAssignableFrom(clazz)) {
                    类.add(clazz);
                }
            } 捕捉(ClassNotFoundException e){
                e.printStackTrace();
            }
            返回课程;
        }

        @Override
        公共无效上下文初始化(ServletContextEvent sce){
            System.out.println("contextInitialized(ServletContextEvent e)");
            ServletContext sc = sce.getServletContext();
            字符串列表 = sc.getInitParameter(PACKAGES_PARAMETER);
            字符串前缀 = sc.getInitParameter(INVOKER_PREFIX_PARAMETER);
            如果(前缀 == null){
                前缀 = "/servlet/";
            }
            如果(列表!= null){
                String[] packages = list.split(",");
                对于 (int i = 0; i 0) {
                        System.out.println("检查包:" + packageName);
                        // 加载 servlet.invoker 下的类
                        设置类 = getClasses(packageName);
                        System.out.println("尺寸:" + classes.size());
                        对于(类 clazz:类){
                            字符串映射 = 前缀 + clazz.getName();
                            System.out.println("添加 '" + clazz.getName() + "' 在映射中'" + 映射 + "'");
                            ServletRegistration sr = sc.getServletRegistration(clazz.getName());
                            //改变了这个;似乎有时 servlet 已经注册,需要重新映射
                            如果(sr == null)
                                 sr = sc.addServlet(clazz.getName(), clazz.getName());
                            如果 ( sr != null )
                               sr.addMapping(映射);
                        }
                    }
                }
            }
        }

        @Override
        公共无效上下文销毁(ServletContextEvent sce){
            System.out.println("contextDestroyed(ServletContextEvent e)");
        }
    }

干杯

于 2021-02-22T16:02:01.490 回答