- Class Filter
- Nested Class Summary
- Constructor Summary
- Method Summary
- Methods declared in class java.lang.Object
- Constructor Details
- Filter
- Method Details
- doFilter
- description
- beforeHandler
- afterHandler
- Фильтры веб-сервера
- Классы Filter, FilterChain, FilterConfig
- Класс RequestDispatcher
- Сравнение редиректа и форварда
- Java filter http method
- Constructor Summary
- Method Summary
- Methods inherited from class javax.servlet.GenericFilter
- Methods inherited from class java.lang.Object
- Methods inherited from interface javax.servlet.Filter
- Constructor Detail
- HttpFilter
- Method Detail
- doFilter
- doFilter
Class Filter
A filter used to pre- and post-process incoming requests. Pre-processing occurs before the application’s exchange handler is invoked, and post-processing occurs after the exchange handler returns. Filters are organised in chains, and are associated with HttpContext instances.
Each Filter in the chain, invokes the next filter within its own doFilter(HttpExchange, Chain) implementation. The final Filter in the chain invokes the applications exchange handler.
Nested Class Summary
Constructor Summary
Method Summary
Methods declared in class java.lang.Object
Constructor Details
Filter
Method Details
doFilter
- Examine or modify the request headers.
- Filter the request body or the response body, by creating suitable filter streams and calling HttpExchange.setStreams(InputStream, OutputStream) .
- Set attribute objects in the exchange, which other filters or the exchange handler can access.
- Decide to either:
- Invoke the next filter in the chain, by calling Filter.Chain.doFilter(HttpExchange) .
- Terminate the chain of invocation, by not calling Filter.Chain.doFilter(HttpExchange) .
- If option 1. above is taken, then when doFilter() returns all subsequent filters in the Chain have been called, and the response headers can be examined or modified.
- If option 2. above is taken, then this Filter must use the HttpExchange to send back an appropriate response.
description
beforeHandler
Returns a pre-processing Filter with the given description and operation. The operation is the effective implementation of the filter. It is executed for each HttpExchange before invoking either the next filter in the chain or the exchange handler (if this is the final filter in the chain). Exceptions thrown by the operation are not handled by the filter.
API Note: A beforeHandler filter is typically used to examine or modify the exchange state before it is handled. The filter operation is executed before Filter.Chain.doFilter(HttpExchange) is invoked, so before any subsequent filters in the chain and the exchange handler are executed. The filter operation is not expected to handle the request or send response headers, since this is commonly done by the exchange handler. Example of adding the «Foo» response header to all responses:
var filter = Filter.beforeHandler("Add response header Foo", e -> e.getResponseHeaders().set("Foo", "Bar")); httpContext.getFilters().add(filter);
afterHandler
Returns a post-processing Filter with the given description and operation. The operation is the effective implementation of the filter. It is executed for each HttpExchange after invoking either the next filter in the chain or the exchange handler (if this filter is the final filter in the chain). Exceptions thrown by the operation are not handled by the filter.
API Note: An afterHandler filter is typically used to examine the exchange state rather than modifying it. The filter operation is executed after Filter.Chain.doFilter(HttpExchange) is invoked, this means any subsequent filters in the chain and the exchange handler have been executed. The filter operation is not expected to handle the exchange or send the response headers. Doing so is likely to fail, since the exchange has commonly been handled before the operation is invoked. More specifically, the response may be sent before the filter operation is executed. Example of adding a filter that logs the response code of all exchanges:
var filter = Filter.afterHandler("Log response code", e -> log(e.getResponseCode()); httpContext.getFilters().add(filter);
Example of adding a sequence of afterHandler filters to a context:
The order in which the filter operations are invoked is reverse to the order in which the filters are added to the context’s filter-list.
var a1Set = Filter.afterHandler("Set a1", e -> e.setAttribute("a1", "some value")); var a1Get = Filter.afterHandler("Get a1", e -> doSomething(e.getAttribute("a1"))); httpContext.getFilters().addAll(List.of(a1Get, a1Set));
Report a bug or suggest an enhancement
For further API reference and developer documentation see the Java SE Documentation, which contains more detailed, developer-targeted descriptions with conceptual overviews, definitions of terms, workarounds, and working code examples. Other versions.
Java is a trademark or registered trademark of Oracle and/or its affiliates in the US and other countries.
Copyright © 1993, 2023, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
All rights reserved. Use is subject to license terms and the documentation redistribution policy.
Фильтры веб-сервера
Но и это еще не все. Правда, ты же не думаешь, что сервлеты устроены так просто?
Кроме сервлетов, которые мы уже разобрали, есть еще так называемые “служебные сервлеты” — фильтры. Они очень похожи на сервлеты, но их основная задача — помогать сервлетам обрабатывать запросы.
Фильтр — это как секретарь, а сервлет – директор. Прежде чем документ попадет на стол директору, он пройдет через руки секретаря. И после того, как директор его подпишет, он снова попадет секретарю, уже как исходящая корреспонденция, например.
Такой секретарь может отбраковывать часть запросов к директору (например, спам). Или давать стандартные ответы на известные ему вопросы (“директора нет на месте”). И так далее. Более того, таких секретарей может быть несколько: один может фильтровать спам сразу для всех директоров, другой перекидывать запросы между разными директорами и тому подобное.
Так же работают и фильтры:
Классы Filter, FilterChain, FilterConfig
Фильтры очень похожи на сервлеты, но с парой небольших отличий. Чтобы написать свой фильтр, нужно наследоваться от интерфейса javax.servlet.Filter .
У фильтра так же есть методы init() и destroy() . Вместо метода service() у фильтра есть метод doFilter() . И даже есть свой класс FilterConfig. Фильтр также добавляется в сервлет в файле web.xml или же с помощью аннотации @WebFilter.
Методы | Описание | |
---|---|---|
1 | init(FilterConfig config) | инициализация фильтра |
2 | destroy() | выгрузка фильтра |
3 | doFilter(ServletRequest , ServletResponse, FilterChain) | обработка (фильтрация) запроса |
В чем же отличие сервлета и фильтра?
Фильтров может быть несколько, и они последовательно обрабатывают запрос (и ответ). Они объединены в так называемую цепочку — и для них даже есть специальный класс FilterChain .
После обработка запроса в методе doFilter() нужно вызвать метод doFilter() следующего фильтра в цепочке. Пример:
public class MyFilter implements Filter < public void init(FilterConfig arg0) throws ServletException < >public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception < PrintWriter out = resp.getWriter(); out.print("Дописываем что-то перед телом ответа"); chain.doFilter(req, resp); //вызываем следующий фильтр в цепочке out.print("Дописываем что-то после тела ответа"); >public void destroy() < >>
Вообще-то так дописывать тело ответа нельзя . Формально фильтры и сервлеты независимы друг от друга и могут изменяться независимо. Их могут писать разные разработчики в разное время. Функция фильтров именно служебная, например:
- Логирование всех входящих запросов (и ответов)
- Сжатие данных
- Шифрование (и расшифровка) данных
- Валидация данных запроса
- Добавление/удаление нужных заголовков
- Перенаправление запросов
- Контроль доступа (проверка, залогинен ли пользователь)
Класс RequestDispatcher
Иногда в процессе работы фильтра внутри метода doFilter() может возникнуть необходимость вызвать другой сервлет . Для этого у контейнера есть специальный объект RequestDispatcher .
Получить его можно двумя способами:
Этот объект можно использовать для того, чтобы перенаправить существующий запрос на другой сервлет . Например, выяснилось, что пользователь не авторизован и мы хотим показать ему страницу с авторизацией. Ну или произошла ошибка на сервере и мы хотим отобразить пользователю error-страницу 🙂
public class HelloServlet extends HttpServlet < protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception < String path = "/error.html"; ServletContext servletContext = this.getServletContext(); RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path); requestDispatcher.forward(request, response); >>
Также ты можешь вызвать RequestDispatcher из фильтра.
public class MyFilter implements Filter < public void init(FilterConfig arg0) throws ServletException < >public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception < String path = "/error.html"; ServletContext servletContext = req.getServletContext(); RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path); requestDispatcher.forward(req, resp); >public void destroy() < >>
Обрати внимание, что запрос будет обработан в методе forward() , и вызывать doFilter() после использования RequestDispatcher не нужно.
Сравнение редиректа и форварда
И еще один важный момент. Если ты хочешь в своем сервлете перенаправить пользователя на другой URI, то сделать это можно двумя способами:
Мы их уже разбирали, но для удобства проговорю это еще раз.
Когда ты выполняешь redirect через вызов response.sendRedirect(«ссылка») , то сервер отсылает браузеру (клиенту) ответ 302 и указанную тобой ссылку. А браузер, проанализировав ответ сервера, загружает переданную тобой ссылку. То есть ссылка в браузере меняется на новую.
Если ты выполняешь forward через вызов requestDispatcher.forward() , то новый запрос выполняется внутри контейнера, и его ответ твой сервлет отсылает браузеру (клиенту) как ответ твоего сервлета. При этом браузер получает ответ от нового сервлета, но ссылка в браузере не меняется.
Java filter http method
Provides a base class that implements the Filter interface and ensures that the Request and Response are of type HttpServletRequest and HttpServletResponse respectively.
Constructor Summary
Method Summary
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.
Methods inherited from class javax.servlet.GenericFilter
Methods inherited from class java.lang.Object
Methods inherited from interface javax.servlet.Filter
Constructor Detail
HttpFilter
Method Detail
doFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain. A typical implementation of this method would follow the following pattern:-
1. Examine the request
2. Optionally wrap the request object with a custom implementation to filter content or headers for input filtering
3. Optionally wrap the response object with a custom implementation to filter content or headers for output filtering
4. a) Either invoke the next entity in the chain using the FilterChain object ( chain.doFilter() ),
4. b) or not pass on the request/response pair to the next entity in the filter chain to block the request processing
5. Directly set headers on the response after invocation of the next entity in the filter chain. This implementation tests the request and response to see if they are instances of HttpServletRequest and HttpServletResponse respectively. If they are then they are passed to doFilter(HttpServletRequest, HttpServletResponse, FilterChain) . If not, a ServletException is thrown.
doFilter
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws java.io.IOException, ServletException
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain. A typical implementation of this method would follow the following pattern:-
1. Examine the request
2. Optionally wrap the request object with a custom implementation to filter content or headers for input filtering
3. Optionally wrap the response object with a custom implementation to filter content or headers for output filtering
4. a) Either invoke the next entity in the chain using the FilterChain object ( chain.doFilter() ),
4. b) or not pass on the request/response pair to the next entity in the filter chain to block the request processing
5. Directly set headers on the response after invocation of the next entity in the filter chain. This default implementation simply calls the next filter in the filter chain.
Copyright © 2000-2023 Apache Software Foundation. All Rights Reserved.