【问题标题】:Tomcat ServletContext cannot load classTomcat ServletContext 无法加载类
【发布时间】:2015-02-10 23:36:25
【问题描述】:

我需要在两个 Web 应用程序之间进行通信。两者都是tomcat项目。我想避免使用 http 请求进行通信。在做了一些研究后,我发现有一个 ServletContext 对象可以处理这个问题。

我按照http://blog.imaginea.com/cross-context-communication-between-web-applications/ 上的指南进行操作,并决定在我自己的快速入门中尝试一下。

我确保我的 tomcat 服务器的 crossContext 设置为 true。

<Context crossContext="true">

我创建了两个检票口快速入门,一个名为 bar,一个名为 foo。我的想法是我可以从 bar 调用 foo 中的函数。

这里是bar中的代码

String methodName = getRequest().getParameter("PARAM_METHOD");
    ServletContext srcServletContext = ((WebApplication)WebApplication.get()).getServletContext();
    ServletContext targetServletContext = srcServletContext.getContext("/foo");

    ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();

    try
    {
        Object object = targetServletContext.getAttribute("org.apache.wicket.protocol.http.WicketServlet.CONTEXT.foo");

        ClassLoader targetServiceClassLoader = targetServletContext.getClass().getClassLoader();

        Thread.currentThread().setContextClassLoader(targetServiceClassLoader);

        // Causes a ClassNotFoundException
        Class<?> classBarService = (Class<?>)targetServiceClassLoader.loadClass("com.foo.SomeUtil");

        Method getTextMethod = object.getClass().getMethod("getText", String.class);

        Object someUtil = getTextMethod.invoke(object, "someUtil");

        Method targetMethod = classBarService.getMethod(methodName, (Class[])null);

        Object responseFromTextMethod = targetMethod.invoke(someUtil, (Object[])null);

    }
    catch (Exception e)
    {
        text += e.toString();
    }
    finally
    {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
    }

foo 在 com.foo 包中有一个名为 SomeUtil 的类。 但是,当我在更改类加载器后尝试加载类时,我得到一个“ClassNotFoundException:com.foo.SomeUtil”。我真的不知道我做错了什么。

提前感谢任何帮助。

【问题讨论】:

    标签: java tomcat servlets wicket


    【解决方案1】:

    即使将 CrossContext 设置为 true,调用类的 ClassLoader 也需要能够访问它尝试加载的类。

    尝试将包含类的 jar 部署到两个 Web 应用程序。

    引用自教程:

    解决方案-1:如果我们可以将多个 Web 应用程序(此处由“Foo”和“Bar”访问)访问的自定义数据类型类外部化到不同的库,并将其放置在 Web 的公共库位置容器(如果是 tomcat,则为 \lib),

    您要么将 jar 部署到两个 webapps,要么部署到 commons/lib,但是 AFAIK,较新版本的 tomcat 默认不再提供 commons/lib

    【讨论】:

    • 我想我认为这只是为了处理自定义数据类型。在上面的示例中,他们讨论的是 Java 原生的简单数据类型。在我的示例中,我只是使用字符串。
    • 您不只是在使用字符串。您尝试调用 com.foo.SomeUtil 类上的方法 - ClassLoader 找不到的类。因此 ClassNotFoundException
    • 我现在已经包含了 jar,但是我得到了 ClassNotFoundException 和 Class> classBarService = (Class>)targetServiceClassLoader.loadClass("com.foo.SomeUtil");在我尝试调用该类的方法之前调用。
    • 准备接受这个答案。我认为关键是将罐子放在两个项目中。最后我无法让这个工作,并决定使用套接字而不是在应用程序之间传递信息。
    • 好吧,我看到即使 Tomcat 9 也有一个 /lib 文件夹,根据文档,tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html 如果你把 JAR 文件放在那里,这些类应该只由类加载器加载一次,因此有可重用的静态字段。需要足够的测试
    【解决方案2】:

    你有没有尝试替换

    ClassLoader targetServiceClassLoader = targetServletContext.getClass().getClassLoader();
    

    ClassLoader targetServiceClassLoader = object.getClass().getClassLoader();
    

    就像教程中提出的那样?

    【讨论】:

    • 是的,我在问题中发布了代码。看起来你错字了,你在两行中都有相同的代码。
    • 不,没有错字。一个说 targetServletContext .getClass()... 另一个说 object .getClass()...
    • 我今天会试一试,看看会发生什么。抱歉,移动应用截断了您的部分文字,所以我没有看到那部分。
    猜你喜欢
    • 1970-01-01
    • 2013-07-12
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    相关资源
    最近更新 更多