Как получить подкласс для использования защищенных методов родительского класса? - PullRequest
0 голосов
/ 20 июля 2011

Я пишу класс сервлета фронт-контроллера для веб-приложений. Фронт-контроллер предназначен для различения трех основных случаев:

  1. Запрос файла (вызов экземпляра FileRequestHandler)
  2. Запрос данных (вызов экземпляра DataRequestHandler)
  3. Запрос сервлета (вызов экземпляра ServletRequestHandler)

Для тестирования я хотел использовать Tomcat DefaultServlet ( javadoc , исходный код ) для обслуживания файлов, но я не могу заставить его работать. Проблема в том, что, хотя мой класс FileRequestHandler должен должным образом расширять DefaultServlet, я не могу получить доступ к его защищенным методам (в частности, doGet для обработки запросов GET). Классы в разных пакетах между прочим.


Код:

public class FileRequestHandler extends DefaultServlet {

// fields

    private static final long serialVersionUID = 1L;

// methods

    public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
            throws IOException, ServletException 
    {
                                                                                                                                    /* DEBUG */try {
            System.out.println("(!!) doGet >> " + DefaultServlet.class.getMethod("doGet",new Class[]{HttpServletRequest.class,HttpServletResponse.class}) ) ;
            doGet(request,response) ;
                                                                                                                                    /* DEBUG */}
                                                                                                                                    /* DEBUG */catch(Exception e) { System.out.println("(!) " + this.getClass( ).getName( ) + " >> buildResponse >> " + e.toString( ) ) ; }
    }

 }

Трассировка стека:

(часть, ведущая к нулевому указателю)

at org.apache.catalina.servlets.DefaultServlet.serveResource (DefaultServlet.java:741) в org.apache.catalina.servlets.DefaultServlet.doGet (DefaultServlet.java:398) в org.pulse.web.FileRequestHandler.buildResponse (FileRequestHandler.java:39)


Обновление:

Мне, возможно, придется уточнить, что сервлет фронт-контроллера будет перехватывать все запросы Http (<url-pattern>/</url-pattern> в web.xml) о том, что DefaultServlet, создаваемый контейнером сервлета, не будет получать запросы, насколько я могу судить. Я сейчас явно назвал DefaultServlet#init в классе фронт-контроллера:

 FileRequestHandler fileRequestHandler = new FileRequestHandler( ) ;
 fileRequestHandler.init( ) ;

Теперь я получаю сервлет 404 недоступно.

Update2: Проблема, как выясняется, на самом деле является дополнительной проблемой с неадекватным использованием расширенного класса, а не с прямой проблемой наследования.


Пост в журнале, который я добавил для определения корня проблемы, вызовет NoSuchMethodException. . Если я опущу это, я получу NullPointerException.

Это выглядит очень просто. Тем не менее я не могу заставить его работать так, как я хочу. Любые идеи, предложения или идеи?

ТИА

FK

Ответы [ 2 ]

1 голос
/ 20 июля 2011

Вам не нужно делать ничего особенного, чтобы вызвать защищенный метод из суперкласса.На самом деле, поскольку вы не переопределили doGet() в своем сервлете, его метод doGet() должен буквально быть методом суперкласса.Вам не нужно делать ничего особенного, кроме обычного вызова, например:

public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
        throws IOException, ServletException  {

        doGet(request,response) ;
}

Если вы хотите, вы можете заменить doGet(request,response) на super.doGet(request,response), но в этом случае это не будет иметь никакого значения, потому чтовы не переопределили doGet() в своем подклассе.

1 голос
/ 20 июля 2011

Class.getMethod возвращает публичные методы - такого метода public нет, поэтому исключение. Вы можете использовать getDeclaredMethod для получения закрытых методов.

Непонятно, почему вы получили NullPointerException, когда вы пробовали его без регистрации - если вы можете опубликовать более полную трассировку стека, это может быть яснее.

РЕДАКТИРОВАТЬ: Судя по исходному коду для DefaultServlet , похоже, что это строка, выдающая исключение:

CacheEntry cacheEntry = resources.lookupCache(path);

Это не имеет особого смысла, поскольку init() должен был вызвать исключение в этом случае ... есть ли что-нибудь еще, сообщающее об ошибке в ваших журналах?

...