- How to Create Java Servlet Filter
- 1. Create Filter Class
- 2. Specify Initialization Parameters for Filter
- 3. Specify Filter Mapping
- Specify Filter Mapping via XML
- Specify Filter Mapping using Annotations
- 4. How to create a servlet filter in Eclipse IDE
- 5. How to create a servlet filter in NetBeans IDE
- References:
- Other Java Servlet Tutorials:
- About the Author:
- Filter application in java
- Перебор элементов. Метод forEach
- Фильтрация. Метод filter
- Отображение. Метод map
- Плоское отображение. Метод flatMap
How to Create Java Servlet Filter
Java servlet filters are essential components of Java web applications, as filters allow programmers to intercept requests and transform responses for a variety of purposes. Even if you don’t create any filters, servlet containers (like Tomcat) and web frameworks (like Spring) use filters behind the scene.
In this tutorial, you will find a detailed, step-by-step guide to create Java servlet filters for your projects.
Basically, there are 3 steps to create a filter:
— Write a Java class that implements the Filter interface and override filter’s life cycle methods.
— Specify initialization parameters for the filter (optional).
— Specify filter mapping, either to Java servlets or URL patterns.
Let’s see each step in detailed.
1. Create Filter Class
package net.codejava; 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; public class HelloFilter implements Filter < @Override public void init(FilterConfig filterConfig) throws ServletException < // invoked when an instance of this filter is created by the container // used to initialize resources, read parameters. >@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException < // invoked when a matching request sent to the server // used to intercept the request and transform the response chain.doFilter(request, response); // invokes next filter in the chain >@Override public void destroy() < // invoked when the filter instance is being destroyed by the container // used clean up resources >>
As you can see, this class must implement the Filter interface and override its three life cycle methods: init() , doFilter() and destroy() . The purpose of each method is clearly explained in the comments. Read this article to learn more about the annotation type @WebFilter .
NOTE: Since Java Servlet API 4.0, you can override only the doFilter() method because the Filter interface implements the init() and destroy() as default methods. For example:
package net.codejava; import java.io.IOException; import javax.servlet.*; public class HelloFilter implements Filter < @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException < // invoked when a matching request sent to the server // used to intercept the request and transform the response chain.doFilter(request, response); // invokes next filter in the chain >>
2. Specify Initialization Parameters for Filter
You can specify initialization parameters for the filter in the web deployment descriptor file ( web.xml ) like this:
Hello Filter net.codejava.HelloFilter message A message from Hello Filter threshold 1024
Hello Filter net.codejava.HelloFilter
You can specify as many parameters as you want. Then in the filter’s init() method you can read these initialization parameters via the FilterConfig object like this:
public void init(FilterConfig fConfig) throws ServletException < String message = fConfig.getInitParameter("message"); String threshold = fConfig.getInitParameter("threshold"); // do something with the parameters >
NOTE: You can use annotations to specify initialization parameters right inside the filter class, but it is not recommended because that requires re-compiling the code when you want to change the values of the parameters.
3. Specify Filter Mapping
The purpose of a filter is to intercept requests, so you have to specify what URLs will be handled by the filter via the mapping step. You can map a filter to any URL patterns using either XML or annotations.
Specify Filter Mapping via XML
Hello Filter Hello Servlet
Hello Servlet net.codejava.HelloServlet Hello Servlet /hello
If the servlet class is annotated using @WebServlet annotation, you must specify the name of the servlet like this:
@WebServlet(name = «Hello Servlet», urlPatterns = ) public class HelloServlet extends HttpServlet
You can map a filter to a URL pattern like this:
Here, the filter Hello Filter is mapped to the URL pattern /* , which means it will intercept all the requests.
And the following example illustrates how to map a filter to multiple URL patterns:
Hello Filter /hello /bonjour /ciao
Specify Filter Mapping using Annotations
From Servlet API 3.0, you can use the @WebFilter to annotate a class a filter. For example:
import javax.servlet.annotation.WebFilter; // other imports @WebFilter("/hello") public class HelloFilter implements Filter < // implement life cycle methods… >
You can see this filter class is mapped to the URL pattern /hello — which is more convenient than using XML, right?
The following example shows how to map a filter to multiple URL patterns:
@WebFilter(< "/servlet1", "/servlet2", "/servlet3" >) public class FilterA implements Filter
@WebFilter(servletNames = < "Hello Servlet" >) public class HelloFilter implements Filter
Note that you can map one filter to one or more serlvets/URL patterns, and map multiple filters to one servlet/URL pattern.
4. How to create a servlet filter in Eclipse IDE
When developing a Java web application using Eclipse IDE, you can create a filter easily via wizards. To create a filter class in Eclipse, click menu File > New, and choose Filter under Web group:
Or you can right-click on a package, and click New > Filter:
Then specify the class name of the filter:
Click Next. Then specify filter mappings:
You can specify URL pattern mapping:
or specify servlet mapping:
Click Finish and Eclipse will generate basic code for the filter class with @WebFilter annotations.
5. How to create a servlet filter in NetBeans IDE
NetBeans IDE also makes it easy to create a filter. Click menu File > New File… and choose Filter in the Web group:
Click Next, and specify the class name for the filter:
Click Next to configure filter deployment:
You can choose to use XML mapping for filter by checking the option “Add information to deployment descriptor (web.xml)”. And edit the filter mappings:
Finally, specify the init parameters for the filter:
Click Finish and NetBeans will generate code for the filter based on the information you have provided.
That’s almost the things you need to know about creating a Java filter. I recommend you to read this famous Servlet and JSP book to learn fully about Java servlet and JSP. If you want to get hands-on experience in developing a fully functional website with Java, this course is my recommendation.
References:
Other Java Servlet Tutorials:
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.
Filter application in java
Перебор элементов. Метод forEach
Для перебора элементов потока применяется метод forEach() , который представляет терминальную операцию. В качестве параметра он принимает объект Consumer , который представляет действие, выполняемое для каждого элемента набора. Например:
Stream citiesStream = Stream.of("Париж", "Лондон", "Мадрид","Берлин", "Брюссель"); citiesStream.forEach(s->System.out.println(s));
Фактически это будет аналогично перебору всех элементов в цикле for и выполнению с ними действия, а именно вывод на консоль. В итоге консоль выведет:
Париж Лондон Мадрид Берлин Брюссель
Кстати мы можем сократить в данном случае применение метода forEach следующим образом:
Stream citiesStream = Stream.of("Париж", "Лондон", "Мадрид","Берлин", "Брюссель"); citiesStream.forEach(System.out::println);
Фактически здесь переадается ссылка на статический метод, который выводит строку на консоль.
Фильтрация. Метод filter
Для фильтрации элементов в потоке применяется метод filter() , который представляет промежуточную операцию. Он принимает в качестве параметра некоторое условие в виде объекта Predicate и возвращает новый поток из элементов, которые удовлетворяют этому условию:
Stream citiesStream = Stream.of("Париж", "Лондон", "Мадрид","Берлин", "Брюссель"); citiesStream.filter(s->s.length()==6).forEach(s->System.out.println(s));
Здесь условие s.length()==6 возвращает true для тех элементов, длина которых равна 6 символам. То есть в итоге программа выведет:
Рассмотрим еще один пример фильтрации с более сложными данными. Допустим, у нас есть следующий класс Phone:
class Phone < private String name; private int price; public Phone(String name, int price)< this.name=name; this.price=price; >public String getName() < return name; >public void setName(String name) < this.name = name; >public int getPrice() < return price; >public void setPrice(int price) < this.price = price; >>
Отфильтруем набор телефонов по цене:
Stream phoneStream = Stream.of(new Phone("iPhone 6 S", 54000), new Phone("Lumia 950", 45000), new Phone("Samsung Galaxy S 6", 40000)); phoneStream.filter(p->p.getPrice()<50000).forEach(p->System.out.println(p.getName()));
Отображение. Метод map
Отображение или маппинг позволяет задать функцию преобразования одного объекта в другой, то есть получить из элемента одного типа элемент другого типа. Для отображения используется метод map , который имеет следующее определение:
Stream map(Function mapper)
Передаваемая в метод map функция задает преобразование от объектов типа T к типу R. И в результате возвращается новый поток с преобразованными объектами.
Возьмем вышеопределенный класс телефонов и выполним преобразование от типа Phone к типу String:
Stream phoneStream = Stream.of(new Phone("iPhone 6 S", 54000), new Phone("Lumia 950", 45000), new Phone("Samsung Galaxy S 6", 40000)); phoneStream .map(p-> p.getName()) // помещаем в поток только названия телефонов .forEach(s->System.out.println(s));
Операция map(p-> p.getName()) помещает в новый поток только названия телефонов. В итоге на консоли будут только названия:
iPhone 6 S Lumia 950 Samsung Galaxy S 6
Еще проведем преобразования:
phoneStream .map(p-> "название: " + p.getName() + " цена: " + p.getPrice()) .forEach(s->System.out.println(s));
Здесь также результирующий поток содержит только строки, только теперь названия соединяются с ценами.
Для преобразования объектов в типы Integer, Long, Double определены специальные методы mapToInt() , mapToLong() и mapToDouble() соответственно.
Плоское отображение. Метод flatMap
Плоское отображение выполняется тогда, когда из одного элемента нужно получить несколько. Данную операцию выполняет метод flatMap :
Stream flatMap(Function> mapper)
Например, в примере выше мы выводим название телефона и его цену. Но что, если мы хотим установить для каждого телефона цену со скидкой и цену без скидки. То есть из одного объекта Phone нам надо получить два объекта с информацией, например, в виде строки. Для этого применим flatMap:
Stream phoneStream = Stream.of(new Phone("iPhone 6 S", 54000), new Phone("Lumia 950", 45000), new Phone("Samsung Galaxy S 6", 40000)); phoneStream .flatMap(p->Stream.of( String.format("название: %s цена без скидки: %d", p.getName(), p.getPrice()), String.format("название: %s цена со скидкой: %d", p.getName(), p.getPrice() - (int)(p.getPrice()*0.1)) )) .forEach(s->System.out.println(s));
Результат работы программы:
название: iPhone 6 S цена без скидки: 54000 название: iPhone 6 S цена со скидкой: 48600 название: Lumia 950 цена без скидки: 45000 название: Lumia 950 цена со скидкой: 40500 название: Samsung Galaxy S 6 цена без скидки: 40000 название: Samsung Galaxy S 6 цена со скидкой: 36000