库中的Java重载方法在未在web服务器中运行时失败

库中的Java重载方法在未在web服务器中运行时失败,java,servlets,compilation,overloading,classnotfoundexception,Java,Servlets,Compilation,Overloading,Classnotfoundexception,我正在尝试编写一个小型库,既可以在标准java应用程序中使用,也可以作为servlet的一部分使用 我定义了两个重载方法,如下所示: // imports etc. public ExampleLibrary { /** * This one is meant to be used by a J2SE app */ public String processData(Map headers) throws MyException { //

我正在尝试编写一个小型库,既可以在标准java应用程序中使用,也可以作为servlet的一部分使用

我定义了两个重载方法,如下所示:

// imports etc.

public ExampleLibrary {

    /**
     * This one is meant to be used by a J2SE app
     */
    public String processData(Map headers) throws MyException {
        // process
        // return result
    }

    /**
     * This one is meant to be used by a servlet 
     */
    public String processData(HttpServletRequest request) throws MyException {
        // extract headers from request
        // process
        // return result
    }


    // other methods.....
}
这在作为Servlet的一部分使用时非常有效,但是在作为J2SE应用程序的一部分使用时却不起作用

在我的J2SE应用程序中,我执行了以下操作:

ExampleLibrary example = ExampleLibrary.getInstance();

Map headers = new HashMap();
headers.put("someheader1", "someheaderval1");
headers.put("someheader2", "someheaderval2");

String res = example.processData(headers);
我在编译时得到: “找不到javax.servlet.http.HttpServletRequest的javax.servlet.http.HttpServletRequest类文件”


我希望编译器选择正确的processData()方法并忽略另一个方法,因为显然J2SE应用程序中没有Servlet类文件。有什么办法解决这个问题吗?

您可以通过在编译时在类路径中包含
servlet.jar
来解决问题

但这里有一个陷阱:

如果库的用户调用这两个方法中的一个,编译器需要确定实际调用这两个方法中的哪一个。如果您有不同的方法名,则一切正常,并且编译器不需要访问
HttpServletRequest
。但是,如果名称相同,编译器需要访问
HttpServletRequest
,以确定这两个方法中哪一个最适合调用和参数

因此,lib的用户将需要
servlet.jar
来运行他的程序,但是如果使用方法重载,他将需要它来编译他的程序

下面是一个虚拟示例,说明了这一点:

虚拟试验第三方实验室: 首先,让我们创建一个虚拟的第三方库jar(并扔掉源代码):

虚拟测试你的库: 测试在不使用thirdpartylib.jar的情况下使用您的库 我在编译时得到这样的信息:“无法访问 的javax.servlet.http.HttpServletRequest类文件 找不到javax.servlet.http.HttpServletRequest“


从Tomcat获取servlet.jar。它包含servlet API。这将抑制错误。

将rt.jar和servlet.jar(或eclipse中的webApp库)放在类路径中

因为您的类依赖于
javax.servlet.http.HttpServletRequest
,所以必须提供后者的类定义才能加载类。最简单的方法是将servlet.jar与应用程序捆绑在一起

但是请注意,让JavaSE应用程序依赖于JavaEE库并不是一个好主意


更好的解决方案是将特定于servlet的部分隐藏在您自己的接口后面,您的核心应用程序可以安全地提供这些接口。然后将应用程序中特定于JavaEE的部分中的接口实现为对应servlet类的简单包装。

我怀疑您的错误与重载方法无关。
如果类路径上没有servlet-api.jar,就无法编译类。

尝试使用不同的名称,而不是重载

public String processData(Map headers) throws MyException { ... }

public String processServletData(HttpServletRequest request) throws MyException { ... }
现在它起作用了


编辑:或者,您可以在编译时将servlet.jar放在类路径上。您不需要它来运行程序,只需要编译它。java编译器需要类信息来决定选择哪个重载方法。

即使您不调用该方法?我希望不必将servlet.jar放在类路径上。如果我添加一个名为
processDataHeaders(MapHeaders)
的新方法,并使用该方法而不是重载方法,我可以毫无问题地编译J2SE应用程序,但我希望保持方法名称不变。@Thilo,看起来我有点不对劲。这确实是一个混乱的局面。在我回答一个小时后,你把你的答案改成和我的一样。很好的示例代码,哦,天哪。。如果我更仔细地读了你的回答,我就不会发火了+如果我不调用重载方法,我可以编译它。如果我调用其他方法,它会编译得很好。是的,但我希望有相同的方法名:),那么您必须为编译提供必要的类(HttpServletRequest)。但是,在运行时不需要它。这是因为Java决定在编译时使用哪个重载方法,并且需要检查类来做出决定。@aioobe,dunno。我刚刚被类似的情况弄得焦头烂额,涉及到一个间接依赖关系(即,提供的jar中的一些类依赖于第三方库,我的应用程序无法运行,除非我明确提供了第三方jar),因此至少在某些情况下似乎需要它。(很抱歉删除我的注释。我现在真的很困惑)
# libtest$ mkdir mylib
# libtest$ cat -> mylib/LibClass.java
package mylib;
import thirdpartylib.ThirdPartyClass;

public class LibClass {

    public void method(String str) {
        System.out.println("method 1");
    }

    // Overloaded method taking third party class as argument.
    public void method(ThirdPartyClass tpc) {
        tpc.thirdPartyMethod();
    }
}
# libtest$ javac -cp .:thirdpartylib.jar mylib/LibClass.java 
# libtest$ jar cf mylib.jar mylib/LibClass.class
# libtest$ rm -rf mylib
# libtest$ cat -> LibUser.java
import mylib.LibClass;

public class LibUser {
    public static void main(String[] args) {
        new LibClass().method("Hej");
    }
}
# libtest$ javac -cp .:mylib.jar LibUser.java
LibUser.java:5: cannot access thirdpartylib.ThirdPartyClass
class file for thirdpartylib.ThirdPartyClass not found
        new LibClass().method("Hej");
                      ^
1 error
# libtest$ javac -cp .:mylib.jar:thirdpartylib.jar LibUser.java
# libtest$ java -cp .:mylib.jar LibUser
method 1
public String processData(Map headers) throws MyException { ... }

public String processServletData(HttpServletRequest request) throws MyException { ... }