Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Фильтрация запросов и ответов

Фильтр — это объект, который может преобразовать заголовок и содержимое (или оба) запроса или ответа. Фильтры отличаются от веб-компонентов тем, что сами фильтры обычно не создают ответ. Вместо этого фильтр обеспечивает функциональность, которую можно «прикрепить» к любому веб-ресурсу. Следовательно, фильтр не должен иметь никаких зависимостей от веб-ресурса, для которого он выступает фильтром. Таким образом, он может быть составлен из более чем одного типа веб-ресурса.

Основные задачи, которые может выполнять фильтр, следующие.

  • Создавать запрос и действовать соответственно.

  • Блокировать пару запрос-ответ от дальнейшей передачи.

  • Изменять заголовки и данные запроса. Вы делаете это, предоставляя кастомную версию запроса.

  • Изменить заголовки и данные ответа. Вы делаете это, предоставляя кастомную версию ответа.

  • Взаимодействовать с внешними ресурсами.

Фильтры применяются для аутентификации, ведения журнала, преобразования изображений, сжатия данных, шифрования, токенизации потоков, преобразования XML и так далее.

Вы можете настроить веб-ресурс для фильтрации по цепочке из нуля, одного или нескольких фильтров в определённом порядке. Эта цепочка указывается при развёртывании веб-приложения, содержащего компонент, и создаётся при загрузке веб-контейнера компонентом.

Программные фильтры

API фильтрации определяется интерфейсами Filter, FilterChain и FilterConfig в пакете javax.servlet. Вы определяете фильтр путём реализации интерфейса Filter.

Используйте аннотацию @WebFilter, чтобы зарегистрировать фильтр в веб-приложении. Эта аннотация указывается для класса и содержит метаданные об объявленном фильтре. Аннотированный фильтр должен указывать хотя бы один шаблон URL. Это делается с помощью атрибутов urlPatterns или value в аннотации. Все остальные атрибуты являются необязательными, с настройками по умолчанию. Используйте атрибут value, когда единственным атрибутом в аннотации является шаблон URL. Используйте атрибут urlPatterns, когда также используются другие атрибуты.

Классы, аннотированные @WebFilter, должны реализовывать интерфейс javax.servlet.Filter.

Чтобы добавить данные конфигурации в фильтр, укажите атрибут initParams аннотации @WebFilter. Атрибут initParams содержит аннотацию @WebInitParam. Следующий фрагмент кода определяет фильтр, задающий параметр инициализации:

import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

@WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/*"},
initParams = {
    @WebInitParam(name = "mood", value = "awake")})
public class TimeOfDayFilter implements Filter {
    ...

Наиболее важным методом в интерфейсе Filter является doFilter, который передаёт объекты запроса, ответа и цепочки фильтров. Этот метод может выполнять следующие действия.

  • Исследование заголовков запроса.

  • Кастомизация объекта запроса, если фильтр хочет изменить заголовки или данные запроса.

  • Кастомизация объекта ответа, если фильтр хочет изменить заголовки или данные ответа.

  • Вызов следующей сущности в цепочке фильтров. Если текущий фильтр является последним фильтром в цепочке, которая заканчивается целевым веб-компонентом или статическим ресурсом, следующим объектом является ресурс в конце цепочки. В противном случае это следующий фильтр, который был настроен в WAR. Фильтр вызывает следующую сущность, вызывая метод doFilter для объекта цепочки, передавая запрос и ответ, с которыми он был вызван, или изменённые версии, которые он создал. В качестве альтернативы, фильтр может заблокировать запрос, не делая вызова следующего объекта. В последнем случае фильтр отвечает за заполнение ответа.

  • Исследование заголовков ответа после вызова следующего фильтра в цепочке.

  • Генерация исключения для указания ошибки в обработке.

В дополнение к doFilter вы должны реализовать методы init и destroy. Метод init вызывается контейнером при создании объекта фильтра. Если вы хотите передать параметры инициализации в фильтр, вы извлекаете их из объекта FilterConfig, переданного в init.

Программирование кастомных запросов и ответов

У фильтра есть много способов изменить запрос или ответ. Например, фильтр может добавить атрибут к запросу или вставить данные в ответ.

Фильтр, который изменяет ответ, должен обычно захватывать ответ прежде, чем он будет возвращён клиенту. Для этого вы передаёте замещающий поток сервлету, который генерирует ответ. Замещающий поток не позволяет сервлету закрывать исходный поток ответов после его завершения и позволяет фильтру изменять ответ сервлета.

Чтобы передать этот замещающий поток сервлету, фильтр создаёт обёртку (wrapper) ответа, которая переопределяет метод getWriter или getOutputStream для возврата этого замещающего потока. Обёртка (wrapper) передаётся методу doFilter цепочки фильтров. По умолчанию методы обёртки (wrapper) обращаются к обёртываемому объекту запроса или ответа.

Чтобы переопределить методы запроса, вы помещаете запрос в объект, который расширяет либо ServletRequestWrapper, либо HttpServletRequestWrapper. Чтобы переопределить методы ответа, вы оборачиваете ответ в объект, который расширяет либо ServletResponseWrapper, либо HttpServletResponseWrapper.

Указание назначений для фильтров

Чтобы веб-контейнер мог решить, как применять фильтр к веб-ресурсам, необходимо настроить назначение для фильтров. Назначение фильтров соотносит фильтр с веб-компонентом по имени или с веб-ресурсами по шаблону URL. Фильтры вызываются в том порядке, в котором назначение фильтров идёт в списке назначений фильтров WAR. Список назначений фильтров для WAR указывается в его дескрипторе развёртывания, используя IDE NetBeans или редактируя XML вручную.

Если вы хотите регистрировать каждый запрос в веб-приложении, назначьте фильтр счётчика посещений шаблону URL /*.

Вы можете назначить один фильтр одному или нескольким веб-ресурсам, а также назначить более одного фильтра каждому веб-ресурсу. Это проиллюстрировано на рисунке 18-1, в котором фильтру F1 назначены сервлеты S1, S2 и S3, фильтру F2 — сервлет S2, фильтру F3 — сервлеты S1 и S2.

Рис. 18-1. Назначение фильтров сервлетам

Схема назначения фильтров F1-F3 сервлетам S1-S3. F1 фильтрует S1-S3, затем F2 фильтрует S2, затем F3 фильтрует S1 и S2.

Напомним, что цепочка фильтров является одним из объектов, переданных методу doFilter фильтра. Эта цепочка формируется косвенно с помощью назначения фильтров. Порядок фильтров в цепочке такой же, как порядок назначения фильтров в дескрипторе развёртывания веб-приложения.

Когда фильтр назначен сервлету S1, веб-контейнер вызывает метод doFilter для F1. Метод doFilter каждого фильтра в цепочке фильтров S1 вызывается предыдущим фильтром в цепочке с помощью метода chain.doFilter. Поскольку цепочка фильтров S1 содержит фильтры F1 и F3, вызов F1 для chain.doFilter вызывает метод doFilter фильтра F3. Когда метод F3 doFilter завершается, управление возвращается к методу F1 doFilter.

Указание назначений фильтров в IDE NetBeans

  1. Разверните узел проекта приложения на вкладке «Проект».

  2. Разверните веб-страницы и узлы WEB-INF под узлом проекта.

  3. Выполните двойной клик на web.xml.

  4. Нажмите Фильтры в верхней части окна редактора.

  5. Разверните узел Фильтры сервлетов в окне редактора.

  6. Нажмите Добавить элемент фильтра, чтобы назначить фильтр веб-ресурсу по имени или шаблону URL.

  7. В диалоговом окне «Добавить фильтр сервлета» введите имя фильтра в поле «Имя фильтра».

  8. Нажмите кнопку Обзор, чтобы найти класс сервлета, к которому применяется фильтр.

    Вы можете включить символы подстановки, чтобы применить фильтр к нескольким сервлетам.

  9. Нажмите ОК.

  10. Чтобы ограничить применение фильтра к запросам, выполните следующие действия.

  11. Разверните узел Назначение фильтров.

  12. Выберите фильтр из списка фильтров.

  13. Нажмите Добавить.

  14. В диалоговом окне «Добавить назначение фильтра» выберите один из следующих типов диспетчеризации:

    • REQUEST: только когда запрос поступает непосредственно от клиента

    • ASYNC: только при получении асинхронного запроса от клиента

    • FORWARD: только когда запрос был перенаправлен компоненту (см. раздел Передача управления другому веб-компоненту)

    • INCLUDE: только при обработке запроса включённым компонентом (см. Включение других ресурсов в ответ)

    • ERROR: только когда запрос обрабатывается с помощью механизма страницы ошибок (см. Обработка ошибок сервлета)

      Вы можете настроить фильтр для применения к любой комбинации предыдущих ситуаций, выбрав несколько типов диспетчеризации. Если типы не указаны, по умолчанию используется REQUEST.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)