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

发布于 2024-12-02 07:31:32 字数 1160 浏览 1 评论 0原文

我正在尝试编写一个小型库,它可以在标准 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() 方法并忽略另一个方法,因为显然 Servlet 中没有 Servlet 类文件一个 J2SE 应用程序。有什么想法如何解决这个问题吗?

I am trying to write a small library that can either be used in a standard java app or as part of a servlet.

I have defined a couple of overloaded methods as follows:

// 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.....
}

This works great when used as part of a Servlet, however it does not work when used as part of a J2SE app.

In my J2SE app I did the following:

ExampleLibrary example = ExampleLibrary.getInstance();

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

String res = example.processData(headers);

I get this at compile time:
"cannot access javax.servlet.http.HttpServletRequest class file for javax.servlet.http.HttpServletRequest not found"

I was expecting the compiler to choose the correct processData() method and ignore the other one as obviously there is no Servlet class file in a J2SE app. Any ideas how to solve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凉月流沐 2024-12-09 07:31:32

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

但这里有一个问题:

如果库的用户调用这两个方法之一,编译器需要找出实际调用这两个方法中的哪一个。如果您有不同的方法名称,一切都很好,并且编译器不需要访问 HttpServletRequest。但是,如果名称相同,编译器需要访问 HttpServletRequest 才能决定这两种方法中哪一个最适合调用和参数。

因此,您的库的用户将不需要需要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

虚拟测试您的库:

# 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< 的情况下使用您的库/代码>

# 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

You can solve your problem by including servlet.jar on your classpath when compiling.

Here's the catch though:

If a user of your library calls one of the two methods, the compiler needs to figure out which of the two methods to actually call. If you have different method names, everything is fine and, the compiler does not need access to the HttpServletRequest. If you have the same name however, the compiler needs to access HttpServletRequest in order to decide which of the two methods best fit the call and argument.

Thus, The user of your lib will not need servlet.jar to run his program, but if you use method overloading, he will need it to be able to compile his program.

Here's a dummy example that illustrates this:

Dummy test-thirdparty lib:

First, let's create a dummy third party library jar (and throw away the source):

# 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

Dummy test your 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

Testing to use your lib without thirdpartylib.jar

# 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
江湖彼岸 2024-12-09 07:31:32

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

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

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

Since your class is dependent on javax.servlet.http.HttpServletRequest, you must provide the class definition of the latter in order to load your class. The simplest way would be to bundle servlet.jar with your app.

Note however, that altogether it is not a good idea to make a JavaSE app dependent on a JavaEE library.

A better solution would be to hide the servlet specific parts behind your own interface(s), which can be safely supplied with your core app. Then implement the interface(s) in the JavaEE specific part of your app as simple wrappers around the corresponding servlet class.

装迷糊 2024-12-09 07:31:32

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

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

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

现在可以了。

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

Try using different names instead of overloading.

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

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

Now it works.

Edit: Alternatively you can put servlet.jar on the classpath while compiling. You won't need it to run the program, just to compile it. The java compiler needs the class info to decide which overloaded method to choose.

2024-12-09 07:31:32

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

从 Tomcat 获取 servlet.jar。它包含 servlet API。这应该可以消除该错误。

I get this at compile time: "cannot access
javax.servlet.http.HttpServletRequest class file for
javax.servlet.http.HttpServletRequest not found"

Get servlet.jar from Tomcat. It contains the servlet API. That should suppress that error.

定格我的天空 2024-12-09 07:31:32

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

put rt.jar and servlet.jar (or webApp library in eclipse) in class path

写下不归期 2024-12-09 07:31:32

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

I suspect your error has nothing to do with overloaded methods.
You simply cannot compile your class without having servlet-api.jar on the classpath.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文