Servlet Filter Writing
Servlet filters can dynamically intercept requests and responses to transform or use the information contained in the requests or responses.
One or more Servlet filters can be attached to a Servlet or a group of Servlets. Servlet filters can also be attached to JavaServer Pages (JSP) files and HTML pages. All attached Servlet filters are called before invoking the Servlet.
Servlet filters are Java classes that can be used in Servlet programming and serve the following purposes:
- Intercept client requests before accessing backend resources.
- Process server responses before sending them back to the client.
Various types of filters recommended by the specification include:
- Authentication Filters.
- Data compression Filters.
- Encryption Filters.
- Trigger resource access event filters.
- Image Conversion Filters.
- Logging and Auditing Filters.
- MIME-TYPE Chain Filters.
- Tokenizing Filters.
- XSL/T Filters, transforming XML content.
Filters are declared through XML tags in the Web deployment descriptor (web.xml) and then mapped to the Servlet names or URL patterns in your application's deployment descriptor.
When the Web container starts the Web application, it creates an instance for each filter declared in the deployment descriptor.
The execution order of filters is consistent with their order in the web.xml configuration file, typically configured before all Servlets.
Servlet Filter Methods
A filter is a Java class that implements the javax.servlet.Filter interface. The javax.servlet.Filter interface defines three methods:
No. | Method & Description |
---|---|
1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) <br>This method performs the actual filtering operation. When a client request method matches the URL set by the filter, the Servlet container invokes the filter's doFilter method. The FilterChain allows access to subsequent filters. |
2 | public void init(FilterConfig filterConfig) <br>When the web application starts, the web server creates an instance of the Filter and calls its init method to read the web.xml configuration and initialize the object, preparing for subsequent user requests (the filter object is created only once, and the init method is executed only once). Developers can obtain a FilterConfig object representing the current filter configuration through the init method's parameter. |
3 | public void destroy() <br>The Servlet container calls this method before destroying the filter instance to release resources used by the Servlet filter. |
FilterConfig Usage
The init method of the Filter provides a FilterConfig object.
If the web.xml file is configured as follows:
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.tutorialpro.test.LogFilter</filter-class>
<init-param>
<param-name>Site</param-name>
<param-value>tutorialpro.org</param-value>
</init-param>
</filter>
In the init method, use the FilterConfig object to get the parameter:
public void init(FilterConfig config) throws ServletException {
// Get the initialization parameter
String site = config.getInitParameter("Site");
// Output the initialization parameter
System.out.println("Website Name: " + site);
}
Servlet Filter Example
Here is an example of a Servlet Filter that outputs the website name and address. This example provides you with a basic understanding of Servlet Filters, and you can use the same concepts to write more complex filter applications:
package com.tutorialpro.test;
// Import necessary Java libraries
import javax.servlet.*;
import java.util.*;
// Implement the Filter class
public class LogFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// Get the initialization parameter
String site = config.getInitParameter("Site");
// Output the initialization parameter
System.out.println("Website Name: " + site);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
// Output the site URL
System.out.println("Site URL: http://www.tutorialpro.org");
// Pass the request back through the filter chain
chain.doFilter(request, response);
}
public void destroy() {
/* Called before the Filter instance is removed from service by the Web container */
}
}
This example uses the previously mentioned DisplayHeader.java as an illustration:
// Import necessary Java libraries
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")
// Extend the HttpServlet class
public class DisplayHeader extends HttpServlet {
// Method to handle GET method request
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Set response content type
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "HTTP Header Request Example - tutorialpro.org 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 Name</th><th>Header Value</th>
</tr>
</tr>
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String paramName = (String)headerNames.nextElement();
out.print("<tr><td>" + paramName + "</td>
String paramValue = request.getHeader(paramName);
out.println("<td> " + paramValue + "</td></tr>
}
out.println("</table>
</body></html>");
}
// Method to handle POST method request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Servlet Filter Mapping in web.xml
Define a filter, then map it to a URL or Servlet, similar to defining a Servlet and then mapping it to a URL pattern. Create the following entry for the filter tag in the deployment descriptor file web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.tutorialpro.test.LogFilter</filter-class>
<init-param>
<param-name>Site</param-name>
<param-value>tutorialpro.org</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<!-- Class name -->
<servlet-name>DisplayHeader</servlet-name>
<!-- Package -->
<servlet-class>com.tutorialpro.test.DisplayHeader</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayHeader</servlet-name>
<!-- URL to access -->
<url-pattern>/TomcatTest/DisplayHeader</url-pattern>
</servlet-mapping>
</web-app>
The above filter applies to all Servlets because we specified /. If you want to apply the filter to only a few Servlets, you can specify a specific Servlet path.
Now try calling any Servlet in the usual way, and you will see the generated log in the Web server. You can also use Log4J logger to log the above logs into a separate file.
Next, we access the instance address http://localhost:8080/TomcatTest/DisplayHeader, and then check the console for the output, as shown below:
Using Multiple Filters
A web application can define several different filters for specific purposes. Suppose you define two filters AuthenFilter and LogFilter. You need to create a different mapping as described below, and the rest of the processing is roughly the same as explained above:
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.tutorialpro.test.LogFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>Initialization Parameter</param-value>
</init-param>
</filter>
<filter>
<filter-name>AuthenFilter</filter-name>
<filter-class>com.tutorialpro.test.AuthenFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>Initialization Parameter</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>
Order of Filter Application
The order of the <filter-mapping>
elements in the web.xml file determines the order in which the Web container applies the filters to the Servlet. To reverse the order of the filters, you simply need to reverse the <filter-mapping>
elements in the web.xml file.
For example, the above example will apply LogFilter first and then AuthenFilter, but the following example will reverse this order:
<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>
Description of web.xml Configuration Nodes
<filter>
Specifies a filter.<filter-name>
Used to specify a name for the filter, the content of this element cannot be empty.<filter-class>
Element used to specify the fully qualified class name of the filter.<init-param>
Element used to specify initialization parameters for the filter, its sub-element<param-name>
specifies the name of the parameter,<param-value>
specifies the value of the parameter.In the filter, you can use the
FilterConfig
interface object to access initialization parameters.<filter-mapping>
Element used to set the resources that a Filter is responsible for intercepting. A Filter's intercepted resources can be specified in two ways: Servlet name and request path for resource access.<filter-name>
Sub-element used to set the registration name of the filter. This value must be the name of a filter declared in the<filter>
element.<url-pattern>
Sets the request path that the filter intercepts (URL pattern associated with the filter).<servlet-name>
Specifies the Servlet name that the filter intercepts.<dispatcher>
Specifies the way the resources intercepted by the filter are invoked by the Servlet container, which can beREQUEST
,INCLUDE
,FORWARD
, andERROR
之一, 默认REQUEST
. Users can set multiple<dispatcher>
sub-elements to specify that the Filter intercepts multiple invocation methods of resources.Values that can be set for the
<dispatcher>
sub-element and their meanings:REQUEST
: When the user directly accesses the page, the Web container will call the filter. If the target resource is accessed through theinclude()
orforward()
methods of RequestDispatcher, then the filter will not be called.INCLUDE
: If the target resource is accessed through theinclude()
method of RequestDispatcher, then the filter will be called. Otherwise, the filter will not be called.FORWARD
: If the target resource is accessed through theforward()
method of RequestDispatcher, then the filter will be called. Otherwise, the filter will not be called. ``