Чтобы Ваш сервлет получил доступ к другим ресурсам сервера, таким как другой сервлет, страница JSP, или CGI скрипт, Вы можете:

  • Либо дать сервлету сделать HTTP запрос. (Это относится к общему программированию на Java. Для более подробной информации, обратитесь к ресурсу Работа с URL-ами.)
  • Либо сделать запрос ресурса с помощью объекта RequestDispatcher, если ресурс доступен на сервере, на котором запущен сервлет.

Этот урок обсуждает второй из вышеуказанных пунктов:

 

Получение объекта RequestDispatcher

Чтобы получить доступ к объекту RequestDispatcher, используйте метод getRequestDispatcher класса ServletContext. Этот метод в качестве аргумента берет URL запрашиваемого ресурса. Формат этого аргумента последовательность имен директорий разбитых знаком слэш /, и именем ресурса на конце. Вот следующие примеры возможных URL:

  • /servlet/myservlet
  • /servlet/tests/MyServlet.class
  • /myinfo.html

Вот пример, когда сервлет BookStoreServlet получает объект RequestDispatcher для главной страницы магазина Duke's Bookstore:

public class BookStoreServlet extends HttpServlet {
    public void service (HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Получаем dispatcher; 
        // он получает главную страницу для пользователя
        RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(
                "/examples/applications/bookstore/bookstore.html");
        ...
    }
}

URL ресурса должен быть доступным на сервере, на котором запущен сервлет в момент обращения. Если ресурс недоступен, или у сервера не реализован объект RequestDispatcher для ресурса данного типа, этот метод вернет значение null. Сервлет должен быть готов к таким ситуациям. Сервлет BookStoreServlet делает это вот таким простым путем:

public class BookStoreServlet extends HttpServlet {
    public void service (HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Получаем dispatcher; 
        // он получает главную страницу для пользователя
        RequestDispatcher dispatcher = ...;
        if (dispatcher == null) {
            // No dispatcher means the html file can not be delivered
            response.sendError(response.SC_NO_CONTENT);
        }
        ...
    }
}
 

Перенаправление запроса

Как только Вы получаете объект RequestDispatcher, Вы можете дать возможность ассоциированному с ним ресурсу отвечать на запрос клиента. Перенаправление очень полезно, например, когда сервлет производит запрос, и ответ носит общий характер, так что он может быть передан другому ресурсу. Сервлет может, например, заведовать информацией кредитных карт, когда пользователь размещает заказ, и потом отправлять запрос клиента к заказу, который возвращает страницу "Спасибо за заказ". В примере Duke's Bookstore, сервлет BookStoreServlet получает сессию пользователя, а потом RequestDispatcher возвращает стартовую страницу магазина Duke's Bookstore:

public class BookStoreServlet extends HttpServlet {
    public void service (HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ...
        // Получить или начать новую сессию пользователя
        HttpSession session = request.getSession();
        // Открыть пользователю стартовую страницу
        dispatcher.forward(request, response);
        ...
    }
}

Запомните, что метод forward должен быть использован тогда, когда необходимо отдать другому ресурсу возможность отвечать пользователю. Если Вы уже получили доступ к объектам ServletOutputStream или PrintWriter, Вы не можете использовать этот метод; он вызовет исключение IllegalStateException.

Если Вы уже начали отвечать пользователю, используя объекты PrintWriter или ServletOutputStream, Вам необходимо использовать метод include.

 

Включение ответа

Метод include интерфейса RequestDispatcher позволяет вызываемому сервлету отвечать клиенту, и использовать в качестве части ответа ресурс, ассоциированный с объектом RequestDispatcher.

Поскольку сервер вызывает метод RequestDispatcher.include подразумевается также, что он отвечет клиенту, сервлет будет использовать объекты PrintWriter и ServletOutputStream до или после вызова метода include. Вы должны запомнить, однако, что вызываемый ресурс не может устанавливать заголовки в ответе клиенту. Если этот ресурс попытается установить заголовки, нет гарантии, что они будут установлены.

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

public class ReceiptServlet extends HttpServlet { 
    public void doPut(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        // Выполняем заказ клиента
        ...
        // Благодарим за заказ
        res.setContentType("text/html");
        PrintWriter toClient = res.getWriter();
        ...
        toClient.println("Thank you for your order!");
        // Получаем request-dispatcher, 
		// чтобы послать список заказанного клиентом
        RequestDispatcher summary = getServletContext()
		        .getRequestDispatcher("/OrderSummary");
        // Опускаем список заказанного в случае ошибки
        if (summary != null) {
            try {
                summary.include(req, res);
            } catch (IOException e) {
			} catch (ServletException e) {
			}
        }
        toClient.println("Come back soon!");
        toClient.println("</html>");
        toClient.close();
    }
}