В Сервлете API Вы обычно используете Сервлет, когда Вы хотите управлять, предварительно обработать и/или постобработать определенные запросы. Но когда Вы хотите фильтровать/изменять общие запросы и/или ответы на основе особых условий, затем Фильтр намного более подходит.

Основные задачи

Учебное руководство по Java EE 6 упоминает неотступно следующие фильтры:

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

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

  • Запросите запрос и действие соответственно.
  • Заблокируйте пару запроса-и-ответа от передачи дальше.
  • Измените заголовки запроса и данные. Вы делаете это путем обеспечения настроенной версии запроса.
  • Измените заголовки ответа и данные. Вы делаете это путем обеспечения настроенной версии ответа.
  • Взаимодействуйте с внешними ресурсами.

Классический вариант использования для Фильтра проверяет присутствие зарегистрированного пользователя на Сеансе HTTP прежде, чем продолжить Запрос HTTP. Это особенно полезно, когда у Вас есть несколько страниц, на которые требуется проверить зарегистрированного пользователя. Вместо copypasting та же логика по всем страницам можно использовать Фильтр, чтобы иметь его в единственном месте.

Жизненный цикл

Когда веб-приложение запустит, контейнер сервлета создаст экземпляр фильтра и сохранит его в памяти в течение времени жизни веб-приложения. Тот же экземпляр будет снова использован для каждого входящего запроса, URL которого соответствует шаблону URL фильтра. doFilter() метод затем назовут по каждому запросу.

Необходимо написать код, который звонит также FilterChain#doFilter() продолжать запрос, или RequestDispatcher#forward() или HttpServletResponse#sendRedirect() изменить цель запроса. Если Вы назовете обоих по тому же запросу, то Вы, вероятно, доберетесь IllegalStateException: response already committed в журналах сервера каждый раз, когда второй вызов выполняется.

В Вашем web.xml, фильтры объявляются через <filter-mapping>s. Они могут послушать любой соответствие URL через <url-pattern>, или к определенному сервлету через <servlet-name>.
Порядок вызова фильтра <servlet-name> во-первых, в порядке объявления, затем <url-pattern>.

Привет, мир

Как привет мировой пример, давайте создадим a LoginFilter который проверяет присутствие зарегистрированного пользователя на Сеансе HTTP и дескрипторах соответственно. В этом примере мы, конечно, предполагаем, что у Вас есть сервлет, который помещает зарегистрированного пользователя в Сеанс HTTP session.setAttribute("user", user) каждый раз, когда форма входа в систему отправлена.

package com.example; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebFilter("/app/*") public class LoginFilter implements Filter { @Override public void init(FilterConfig config) throws ServletException { // If you have any <init-param> in web.xml, then you could get them // here by config.getInitParameter("name") and assign it as field. } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpSession session = request.getSession(false); if (session == null || session.getAttribute("user") == null) { response.sendRedirect(request.getContextPath() + "/login"); // No logged-in user found, so redirect to login page. } else { chain.doFilter(req, res); // Logged-in user found, so just continue request. } } @Override public void destroy() { // If you have assigned any expensive resources as field of // this Filter class, then you could clean/close them here. } } 

Скомпилируйте код и вставьте его /WEB-INF/classes папка. В данном случае файл класса должен закончиться в /WEB-INF/classes/com/example/LoginFilter.class. IDE как Eclipse, Netbeans или IntelliJ сделает все это автоматически при создании динамического веб-проекта.

Обратите внимание что @WebFilter аннотация только работает над Java EE 6 / Сервлет 3,0 способных контейнера (Tomcat 7, Glassfish 3, JBoss AS 6, и т.д.). Если Вы используете более старую версию, то необходимо удалить аннотацию и отобразить фильтр в файле /WEB-INF/web.xml следующим образом, который делает эффективно то же.

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <filter> <filter-name>loginFilter</filter-name> <filter-class>com.example.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/app/*</url-pattern> </filter-mapping> </web-app> 

Так или иначе это в основном говорит servletcontainer, что должно сделать следующее под покрытиями:

com.example.LoginFilter loginFilter = new com.example.LoginFilter(); filters.put("/app/*", loginFilter); // Add to filter mapping. 

Предположение, что Вы развернули это веб-приложение на http://localhost:8080/contextname, затем любой запрос, который запускает с URL http://localhost:8080/contextname/app, такой как http://localhost:8080/contextname/app/userprofile, вызовет этот фильтр. Фильтр проверяет если атрибут сессии с именем "user" присутствует. Если это будет отсутствовать, то это перенаправит к странице входа в систему на http://localhost:8080/contextname/login, иначе это только продолжит запрос. Шаблон URL /app/* свободно к Вашему выбору. Можно также сделать его /private/*, /secured/*, и т.д.

Ресурсы онлайн и учебные руководства

Связанные страницы информации о теге