JSP Фильтры
Фильтры в JSP и сервлетах являются Java-классами.
Фильтры могут динамически перехватывать запросы и ответы, чтобы преобразовывать или использовать информацию, содержащуюся в запросах или ответах.
Вы можете прикрепить один или несколько фильтров к сервлету или группе сервлетов. Фильтры также можно прикрепить к файлам JavaServer Pages (JSP) и HTML-страницам.
Фильтры — это классы Java, которые можно использовать в программировании сервлетов для достижения следующих целей:
- Перехватывать клиентские запросы до того, как они получат доступ к серверным ресурсам.
- Обрабатывать ответы сервера до того, как они будут отправлены обратно клиенту.
Различные типы фильтров, предлагаемые спецификацией:
- Фильтры аутентификации.
- Фильтры сжатия данных.
- Фильтры шифрования.
- Фильтры, инициирующие события доступа к ресурсам.
- Фильтры преобразования изображений.
- Фильтры журналирования и аудита.
- Фильтры цепочки MIME-TYPE.
- Фильтры токенизации.
- Фильтры XSL/T, которые преобразуют XML-содержимое.
Фильтры объявляются с помощью XML-тегов в дескрипторе развёртывания веб-приложения (web.xml), а затем сопоставляются с именем сервлета или шаблоном URL в дескрипторе развёртывания вашего приложения.
Когда веб-контейнер запускает веб-приложение, он создаёт экземпляр для каждого фильтра, объявленного вами в дескрипторе развёртывания.
Порядок выполнения фильтров соответствует порядку конфигурации в файле конфигурации web.xml; обычно фильтры настраиваются перед всеми сервлетами.

Методы фильтра сервлета
Фильтр — это класс Java, реализующий интерфейс javax.servlet.Filter. Интерфейс javax.servlet.Filter определяет три метода:
| Порядковый номер | Метод и описание |
|---|---|
| 1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) Этот метод выполняет фактическую операцию фильтрации. Когда клиентский запрос соответствует URL, заданному для фильтра, контейнер сервлетов сначала вызовет метод doFilter фильтра. FilterChain используется для доступа к последующим фильтрам. |
| 2 | public void init(FilterConfig filterConfig) Когда веб-приложение запускается, веб-сервер создаёт экземпляр объекта Filter и вызывает его метод init для чтения конфигурации web.xml и завершения инициализации объекта, подготавливая тем самым перехват последующих пользовательских запросов (объект фильтра создаётся только один раз, и метод init выполняется только один раз). Через параметры метода init разработчики могут получить объект FilterConfig, представляющий информацию о текущей конфигурации фильтра. |
| 3 | public void destroy() Контейнер сервлетов вызывает этот метод перед уничтожением экземпляра фильтра и в этом методе освобождает ресурсы, занятые фильтром сервлета. |
Использование FilterConfig
Метод init класса Filter предоставляет объект FilterConfig.
Например, файл web.xml настроен следующим образом:
<filter> <filter-name>LogFilter</filter-name> <filter-class>com.example.test.LogFilter</filter-class> <init-param> <param-name>Site</param-name> <param-value>Example</param-value> </init-param> </filter>
Используйте объект FilterConfig в методе init для получения параметров:
public void init(FilterConfig config) throws ServletException {
// 获取初始化参数
String site = config.getInitParameter("Site");
// 输出初始化参数
System.out.println("网站名称: " + site);
}
Пример фильтра JSP
Ниже приведён пример фильтра Servlet, который выводит название и адрес веб-сайта. Этот пример даёт базовое представление о фильтрах Servlet; используя ту же концепцию, вы можете писать более сложные приложения-фильтры:
//导入必需的 java 库
import javax.servlet.*;
import java.util.*;
//实现 Filter 类
public class LogFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// 获取初始化参数
String site = config.getInitParameter("Site");
// 输出初始化参数
System.out.println("网站名称: " + site);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
// 输出站点名称
System.out.println("站点网址:http://www.example.com");
// 把请求传回过滤链
chain.doFilter(request,response);
}
public void destroy( ){
/* 在 Filter 实例被 Web 容器从服务移除之前调用 */
}
}
Код файла DisplayHeader.java выглядит следующим образом:
//导入必需的 java 库
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/DisplayHeader")
//扩展 HttpServlet 类
public class DisplayHeader extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "HTTP Header 请求实例 - Example实例";
String docType =
"<!DOCTYPE html> \n";
out.println(docType +
"<html>\n" +
"<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
"<body bgcolor=\"#F0F0F0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<table width=\"100%\" border=\"1\" align=\"center\">\n" +
"<tr bgcolor=\"#949494\">\n" +
"<th>Header 名称</th><th>Header 值</th>\n"+
"</tr>\n");
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String paramName = (String)headerNames.nextElement();
out.print("<tr><td>" + paramName + "</td>\n");
String paramValue = request.getHeader(paramName);
out.println("<td> " + paramValue + "</td></tr>\n");
}
out.println("</table>\n</body></html>");
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Сопоставление фильтра Servlet в Web.xml
Определение фильтра и его сопоставление с URL или Servlet примерно аналогично определению Servlet и его сопоставлению с шаблоном URL. В файле дескриптора развёртыванияweb.xmlсоздайте следующие записи для тега filter:
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.example.test.LogFilter</filter-class>
<init-param>
<param-name>Site</param-name>
<param-value>Example</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<!-- 类名 -->
<servlet-name>DisplayHeader</servlet-name>
<!-- 所在的包 -->
<servlet-class>com.example.test.DisplayHeader</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayHeader</servlet-name>
<!-- 访问的网址 -->
<url-pattern>/TomcatTest/DisplayHeader</url-pattern>
</servlet-mapping>
</web-app>
Приведённый выше фильтр применяется ко всем Servlet, поскольку мы указали в конфигурации/*. Если вы хотите применить фильтр только к нескольким Servlet, можно указать конкретный путь Servlet.
Теперь попробуйте вызвать любой Servlet обычным способом, и вы увидите логи, сгенерированные в веб-сервере. Вы также можете использовать логгер Log4J, чтобы записывать вышеприведённые логи в отдельный файл.
Далее мы переходим по этому примеру адресаhttp://localhost:8080/TomcatTest/DisplayHeader, а затем проверяем вывод в консоли, как показано ниже:

Использование нескольких фильтров
Веб-приложения могут определять несколько различных фильтров для конкретных целей. Предположим, вы определяете два фильтраAuthenFilterиLogFilter. Вам нужно создать другое сопоставление, как описано ниже; остальная обработка примерно такая же, как объяснено выше:
<filter> <filter-name>LogFilter</filter-name> <filter-class>com.example.test.LogFilter</filter-class> <init-param> <param-name>test-param</param-name> <param-value>Initialization Paramter</param-value> </init-param> </filter> <filter> <filter-name>AuthenFilter</filter-name> <filter-class>com.example.test.AuthenFilter</filter-class> <init-param> <param-name>test-param</param-name> <param-value>Initialization Paramter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>AuthenFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Порядок применения фильтров
Порядок элементов filter-mapping в web.xml определяет порядок, в котором веб-контейнер применяет фильтры к сервлетам. Чтобы изменить порядок фильтров на обратный, вам просто нужно изменить порядок элементов filter-mapping в файле web.xml.
Например, в приведённом выше примере сначала будет применён LogFilter, а затем AuthenFilter, но следующий пример изменит этот порядок на обратный:
<filter-mapping> <filter-name>AuthenFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Пояснение элементов конфигурации web.xml
<filter>Указывает фильтр.<filter-name>Используется для указания имени фильтра; содержимое этого элемента не может быть пустым.<filter-class>Элемент используется для указания полного имени класса фильтра.<init-param>Элемент используется для указания параметров инициализации фильтра; его дочерние элементы<param-name>указывают имя параметра,<param-value>указывают значение параметра.- В фильтре можно использовать
FilterConfigобъект интерфейса для доступа к параметрам инициализации.
<filter-mapping>Элемент используется для задания ресурсов, которые должен перехватывать фильтр. Ресурсы, перехватываемые фильтром, можно указать двумя способами: имя сервлета и путь запроса для доступа к ресурсу.<filter-name>Дочерний элемент используется для задания регистрационного имени фильтра. Это значение должно быть<filter>именем фильтра, объявленного в элементе.<url-pattern>Задаёт путь запроса, перехватываемый фильтром (шаблон URL, связанный с фильтром).
<servlet-name>Задаёт имя сервлета, перехватываемого фильтром.<dispatcher>Определяет, как ресурс, перехватываемый фильтром, вызывается контейнером сервлетов; это может бытьREQUEST,INCLUDE,FORWARDиERRORодним из следующих; значение по умолчанию —REQUEST. Пользователи могут задать несколько<dispatcher>дочерних элементов, чтобы указать, что фильтр перехватывает несколько режимов вызова ресурса.<dispatcher>Значения, которые можно задать для дочернего элемента, и их смыслREQUEST: Когда пользователь напрямую обращается к странице, Web-контейнер вызовет фильтр. Если к целевому ресурсу обращаются через метод include() или forward() класса RequestDispatcher, фильтр не будет вызван.INCLUDE: Если к целевому ресурсу обращаются через метод include() класса RequestDispatcher, фильтр будет вызван. За исключением этого, фильтр не будет вызван.FORWARD: Если к целевому ресурсу обращаются через метод forward() класса RequestDispatcher, фильтр будет вызван. За исключением этого, фильтр не будет вызван.ERROR: Если целевой ресурс вызывается через декларативный механизм обработки исключений, фильтр будет вызван. За исключением этого, фильтр не будет вызван.