Java перегруженный метод в библиотеке не работает, если он не запущен на веб-сервере - PullRequest
2 голосов
/ 31 августа 2011

Я пытаюсь написать небольшую библиотеку, которую можно использовать либо в стандартном Java-приложении, либо в составе сервлета.

Я определил пару перегруженных методов следующим образом:

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

Это прекрасно работает, когда используется как часть сервлета, однако не работает, когда используется как часть приложения 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 not found "

Я ожидал, что компилятор выберет правильный метод processData () и проигнорирует другой, поскольку очевидно, что в приложении J2SE нет файла класса Servlet.Есть идеи как это решить?

Ответы [ 6 ]

4 голосов
/ 31 августа 2011

Вы можете решить вашу проблему, включив servlet.jar в ваш путь к классу при компиляции.

Вот в чем загвоздка:

Если пользователь вашей библиотеки вызывает один из двух методов,Компилятор должен выяснить, какой из двух методов на самом деле вызывать.Если у вас разные имена методов, все в порядке, и компилятору не нужен доступ к HttpServletRequest.Однако, если у вас одинаковое имя, компилятору необходим доступ к HttpServletRequest, чтобы решить, какой из двух методов лучше всего подходит для вызова и аргумента.

Таким образом, пользователь вашей библиотеки не будет нужно servlet.jar до запустить его программу, но если вы используете перегрузку метода, ему понадобится, чтобы она могла скомпилировать его программу.

Вотфиктивный пример, который иллюстрирует это:

Пустой тест-третье лицо lib:

Во-первых, давайте создадим фиктивный сторонний библиотечный файл библиотеки (и выбросим источник):

# 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

Проверка использования вашей библиотеки без 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
2 голосов
/ 31 августа 2011

Поскольку ваш класс зависит от javax.servlet.http.HttpServletRequest, вы должны предоставить определение класса последнего, чтобы загрузить ваш класс.Простейшим способом было бы связать servlet.jar с вашим приложением.

Обратите внимание, однако, что вообще не стоит делать зависимость приложения JavaSE от библиотеки JavaEE.Решением было бы спрятать отдельные части сервлета за вашими собственными интерфейсами, которые могут быть безопасно предоставлены вашим основным приложением.Затем реализуйте интерфейс (ы) в специфичной для JavaEE части вашего приложения в виде простых оболочек вокруг соответствующего класса сервлета.

1 голос
/ 31 августа 2011

Попробуйте использовать другие имена вместо перегрузки.

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

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

Теперь это работает.

Редактировать: В качестве альтернативы вы можете поместить servlet.jar в classpath во время компиляции.Вам не понадобится это для запуска программы, просто для ее компиляции.Компилятору java нужна информация о классе, чтобы решить, какой перегруженный метод выбрать.

0 голосов
/ 31 августа 2011

Я подозреваю, что ваша ошибка не имеет ничего общего с перегруженными методами.Вы просто не можете скомпилировать свой класс, не имея servlet-api.jar на пути к классам.

0 голосов
/ 31 августа 2011

положить rt.jar и servlet.jar (или библиотеку webApp в eclipse) в пути к классам

0 голосов
/ 31 августа 2011

Я получаю это во время компиляции: «не удается получить доступ к файлу класса javax.servlet.http.HttpServletRequest для javax.servlet.http.HttpServletRequest не найден»

Получить сервлет.jar изКот.Он содержит API сервлета.Это должно подавить эту ошибку.

...