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

我正在尝试编写一个小型库,可以在标准的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(并扔掉源代码):

 # libtest$ mkdir thirdpartylib # libtest$ cat -> thirdpartylib/ThirdPartyClass.java package thirdpartylib; public class ThirdPartyClass { public void thirdPartyMethod() { System.out.println("Third party method"); } } # libtest$ javac thirdpartylib/ThirdPartyClass.java # libtest$ jar cf thirdpartylib.jar thirdpartylib/ThirdPartyClass.class # libtest$ rm -rf thirdpartylib 

虚拟测试你的lib:

 # 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 

测试使用没有thirdpartylib.jar的lib

 # 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 

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

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

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

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

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

现在它有效。

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

我在编译时得到这个:“无法访问javax.servlet.http.HttpServletRequest类文件,找不到javax.servlet.http.HttpServletRequest”

从Tomcat获取servlet.jar。 它包含servlet API。 这应该可以抑制这个错误。

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

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