Java Servlet Filter Tutorial

1- Introduction

This document is based on:
  • Eclipse 4.5 MARS (Ok for Eclipse 4.4 LUNA)

  • Tomcat 8.x

You should have knowledge of  Servlet before reading documents on  Servlet-Filter, if you are a beginner, you can see the Java Servlet at:

2- Why need Server-Filter?

Situation 1:

Normally, when user requests a web page, a request is sent to the server, it will have to pass through the filter before before reaching the page required, like the illustration below:

Situation 2:

However, there are situations where the user's request do not pass all Filters 

Situation 3:

In case that the user requests a page (page 1), this request must pass Filters, in a certain filter, the  request are redirected to a different page (page2).

Example situation:
  1. Users submit a request for personal info.
  2. Request will be sent to the Server.
  3. It goes through Filter that records log information.
  4. It goes to Filter to check user logined or not, this filter  found that the user is  not logined, it will redirect the request of the user to the login page.

3- What can Servlet-filter do?

Sometimes, you believed that Filter only used to redirect the user requests to a different page, or block access to a particular page if the user has no right. Or used to write log information.
In fact, Filter can be used to encoding web pages. For example, set UTF-8 encoding for the page. Opening and closing the connection to the database and  preparing  JDBC transaction

4- Create Project to start with Servlet-Filter

First we create a WebApp project to work with servlet-filter.
  • File/New/Other...
Enter:
  • Project Name: ServletFilterTutorial
Project has been created:
Create file index.html:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>

  <h2>Servlet-Filter Tutorial</h2>

</body>
</html>

5- Configuring the runtime environment

Right-click on Project and select Properties:
Right-click on Project and select:
  • Run As/Run on Server
OK !, everything was ready to start learning Servlet-Filter.

6- The first Servlet-Filter example

Servlet-Filter is a class that implements  javax.servlet.Filter interface. Class  LogFilter below records the time and link of the request sent to the WebApp.
LogFilter.java
package org.o7planning.tutorial.servletfilter;

import java.io.IOException;
import java.util.Date;

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.http.HttpServletRequest;

public class LogFilter implements Filter {

    public LogFilter() {
    }

    @Override
    public void init(FilterConfig fConfig) throws ServletException {
        System.out.println("LogFilter init!");
    }

    @Override
    public void destroy() {
        System.out.println("LogFilter destroy!");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        String servletPath = req.getServletPath();

        System.out.println("#INFO " + new Date()
                + " - ServletPath :" + servletPath + ", URL =" + req.getRequestURL());

       
        // Go to the next element (filter or target) in chain.
        chain.doFilter(request, response);
    }

}
Configure filter in web.xml:
Add the configuration in web.xml:
<!--
  Declaring a filter named logFilter
-->
<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<!--
  Declare the path (of the page) will have the effect of logFilter
 /* for all paths
-->
<filter-mapping>
  <filter-name>logFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
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"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">

<display-name>ServletFilterTutorial</display-name>

<filter>
 <filter-name>logFilter</filter-name>
 <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<filter-mapping>
 <filter-name>logFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>



<welcome-file-list>
 <welcome-file>index.html</welcome-file>
 <welcome-file>index.htm</welcome-file>
 <welcome-file>index.jsp</welcome-file>
 <welcome-file>default.html</welcome-file>
 <welcome-file>default.htm</welcome-file>
 <welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Rerun you web application
You can run the following link in your browser, here are the links to sources that do not exist on your WebApp, but it is still under the effect of  LogFilter.
Log information is recorded on the Console screen :
The code allows the request pass Filter to continue to the page requested.
// Cho phép request vượt qua Filter này để tiếp tục.
// Nó có thể tới một Filter khác hoặc tới trang người dùng yêu cầu.

chain.doFilter(request, response);

7- Working models of Filter

When the user sends a request, the target may be a resource or a servlet. Request must be passed through the filter and finally the target. The filter and target is chained  together like illustration below: 
Use chain.doFilter (request, response) to move the request to the next stage. If the chain.doFilter (request, response) filter is not called, the user's request will not reach the target, it will be stopped at that filter.

8- Init Paramters of Servlet-Filter

Like with Servlet, you can initialize the parameters for Filter. The example below, a Filter do mission of writing log to a file, you can configure in web.xml file name for writing.
Log2Filter.java
package org.o7planning.tutorial.servletfilter;

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 Log2Filter implements Filter {

    private String logFile;

    public Log2Filter() {
    }

    @Override
    public void init(FilterConfig fConfig) throws ServletException {
        this.logFile = fConfig.getInitParameter("logFile");

        System.out.println("Log File " + logFile);
    }

    @Override
    public void destroy() {
        System.out.println("Log2Filter destroy!");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        if (this.logFile != null) {
            // Write log to file
            this.logToFile(this.logFile);
        }

      
        // Go to the next element (filter or target) in chain.
        chain.doFilter(request, response);
    }

    private void logToFile(String fileName) {
    
        // Write log to file
        System.out.println("Write log to file " + fileName);
    }

}
Add the configuration in web.xml:
<filter>
   <filter-name>log2Filter</filter-name>
   <filter-class>org.o7planning.tutorial.servletfilter.Log2Filter</filter-class>
   <init-param>
       <param-name>logFile</param-name>
       <param-value>AppLog.log</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>log2Filter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ServletFilterTutorial</display-name>

<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>logFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>


<filter>
  <filter-name>log2Filter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.Log2Filter</filter-class>
  <init-param>
      <param-name>logFile</param-name>
      <param-value>AppLog.log</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>log2Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 


<welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

9- Servlet-Filter url-pattern

There are 3 ways you can configure url-pattern for Filter:
URL Pattern Example
/* http://example.com/contextPath
http://example.com/contextPath/status/abc
/status/abc/* http://example.com/contextPath/status/abc
http://example.com/contextPath/status/abc/mnp
http://example.com/contextPath/status/abc/mnp?date=today
http://example.com/contextPath/test/abc/mnp
*.map http://example.com/contextPath/status/abc.map
http://example.com/contextPath/status.map?date=today
http://example.com/contextPath/status/abc.MAP

10- Servlet-Filter using Annotation

The example above, the filter configuration in  web.xml, however, with the Servlet version 3 or higher you can use Annotation to configure the Filter .
This example illustrates when users send requests to view a image file (jpg, png or gif), Filter will check image file exists or not, in case that does not exist, filter will redirect the request to a default image file.
First, you copy  flower.png & image-not-found.png files into image folder on your WebApp
 
ImageFilter.java
package org.o7planning.tutorial.servletfilter;

import java.io.File;
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.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(urlPatterns = { "*.png", "*.jpg", "*.gif" },
        initParams = {        
            @WebInitParam(name = "notFoundImage", value = "/images/image-not-found.png")        
        }
)
public class ImageFilter implements Filter {

    private String notFoundImage;

    public ImageFilter() {
    }

    @Override
    public void init(FilterConfig fConfig) throws ServletException {

        // ==> /images/image-not-found.png
        notFoundImage = fConfig.getInitParameter("notFoundImage");
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        // ==> /images/path/my-image.png
        // ==> /path1/path2/image.pngs
        String servletPath = req.getServletPath();
 
        // The path to the root directory of the webapp (WebContent)
        String realRootPath = request.getServletContext().getRealPath("");

  
        // Real path of Image.
        String imageRealPath = realRootPath + servletPath;

        System.out.println("imageRealPath = " + imageRealPath);

        File file = new File(imageRealPath);

 
        // Check image exists.
        if (file.exists()) {

      
            // Go to the next element (filter or servlet) in chain
            chain.doFilter(request, response);

        } else if (!servletPath.equals(this.notFoundImage)) {

      
            // Redirect to 'image not found' image.
            HttpServletResponse resp = (HttpServletResponse) response;
            
            // ==> /ServletFilterTutorial + /images/image-not-found.png
            resp.sendRedirect(req.getContextPath()+ this.notFoundImage);

        }

    }

}
Rerun your application and  test the following URL:
With links requested image file,  however the image file does not exist, it will be redirected to the default image.
In the example above, you can also use the Forward instead of Redirect request to the default image file in case required image file does not exist.
// Redirect:

// ==> /ServletFilterTutorial + /images/image-not-found.png
resp.sendRedirect(req.getContextPath()+ this.notFoundImage);

// Forward:

req.getServletContext().getRequestDispatcher(this.notFoundImage).forward(request, response);

11- Establishing JDBC connection in the Filter

You  can create a Connection object connect to JDBC in Servlet to handle work with Database. However, you can also create a Connection object connect to JDBC in Filter, and it will take effect with many Servlets. And you can use this Connection throughout the way of request.  You can see the illustration below for understandable
ConnectionUtils is the class that creates a  Connection object connected to the database, in this document, I do not introduce in detail how to get  Connection object.
You can learn about document on JDBC  at:
ConnectionUtils.java
package org.o7planning.tutorial.servletfilter.conn;

import java.sql.Connection;

public class ConnectionUtils {

   public static Connection getConnection() {
     
       // Create a Connection to database
       Connection conn = null;

       // .....

       return conn;
   }

   public static void closeQuietly(Connection conn) {
       try {
           conn.close();
       } catch (Exception e) {
       }
   }

   public static void rollbackQuietly(Connection conn) {
       try {
           conn.rollback();
       } catch (Exception e) {
       }
   }
}
MyUtils.java
package org.o7planning.tutorial.servletfilter.conn;

import java.sql.Connection;

import javax.servlet.ServletRequest;

public class MyUtils {

   public static final String ATT_NAME = "MY_CONNECTION_ATTRIBUTE";

   // Store Connection to attribute of request
   // Information stored only exist during requests
   // until the data is returned to the user browser.
   public static void storeConnection(ServletRequest request, Connection conn) {
       request.setAttribute(ATT_NAME, conn);
   }

   // Get the Connection object has been stored in one attribute of the request.
   public static Connection getStoredConnection(ServletRequest request) {
       Connection conn = (Connection) request.getAttribute(ATT_NAME);
       return conn;
   }
}
I declare url-pattern for JDBCFilter is /*, this filter will work with all the request of users.
JDBCFilter.java
package org.o7planning.tutorial.servletfilter.conn;

import java.io.IOException;
import java.sql.Connection;

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;

@WebFilter(urlPatterns = { "/*" })
public class JDBCFilter implements Filter {

   public JDBCFilter() {
   }

   @Override
   public void init(FilterConfig fConfig) throws ServletException {

   }

   @Override
   public void destroy() {

   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
           throws IOException, ServletException {

       HttpServletRequest req = (HttpServletRequest) request;

       //
       String servletPath = req.getServletPath();
       
       //
       // Only open Connection for special request.
       // (For example: servlet, jsp, ..)
       //
       // Avoid open connection for the common request
       // (For example image, css, javascript,... )
       //        
       if (servletPath.contains("/specialPath1") || servletPath.contains("/specialPath2")) {
           Connection conn = null;
           try {
           
               // Create a Connection
               conn = ConnectionUtils.getConnection();
         
               // Set auto commit false
               conn.setAutoCommit(false);

       
               // Store connection in attribute of request.
               MyUtils.storeConnection(request, conn);

         
               // Go to next element (filter or target) in chain
               chain.doFilter(request, response);

       
               // Call commit() to commit transaction.
               conn.commit();
           } catch (Exception e) {
               ConnectionUtils.rollbackQuietly(conn);
               throw new ServletException();
           } finally {
               ConnectionUtils.closeQuietly(conn);
           }
       }
   
       // For common request.
       else {
       
           // Go to next element (filter or target) in chain.
           chain.doFilter(request, response);
       }

   }

}
At the next filter or in target (servlet, or JSP), you can obtain a Connection object stored in a attribute of the request:
Connection conn = (Connection) request.getAttribute(ATT_NAME);

// Or

Connection conn = MyUtils.getStoredConnection();

12- Java JSP Tutorial

Next, you can learn JSP at: