1 Introduction
Filter, also known as filter, is one of the most exciting technologies in Servlet Technology. web developers use filter technology to intercept all web resources managed by web server, such as JSP, servlet, static picture file or static HTML file, so as to realize some special functions. For example, it implements some advanced functions such as URL level permission access control, filtering sensitive words, compressing response information and so on.
The Servlet API provides a Filter interface. When developing web applications, if the Java class written implements this interface, it is called Filter. Through Filter technology, developers can intercept requests and responses before accessing a target resource. The source code of Filter interface is as follows:
public abstract interface Filter{ public abstract void init(FilterConfig paramFilterConfig) throws ServletException; public abstract void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) throws IOException, ServletException; public abstract void destroy(); }
2. Working principle of filter
There is a doFilter method in the Filter interface. After we write the Filter and configure which web resource to intercept, the web server will call the doFilter method of the Filter before calling the service method of the web resource. Therefore, writing code in this method can achieve the following:
- Let a piece of code execute before calling the target resource;
- Whether to call the target resource, that is, whether to let the user access the web resource;
- After calling the target resource, let a piece of code execute.
When calling the doFilter method, the web server will pass in a filterChain object. The filterChain object is the most important object in the filter interface. It also provides a doFilter method. Developers can decide whether to call this method according to their needs. If this method is called, the web server will call the service method of the web resource, that is, the web resource will be accessed; Otherwise, web resources will not be accessed.
3. Filter development process
3.1 Filter development steps
Filter development is divided into two steps:
- Write a Java class to implement the Filter interface and implement its doFilter method;
- Filter written using filter and filter mapping element pairs in web.xml file
Class and set the resources it can intercept.
Step 1: filter 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; /** * How Filter works */ public class FilterTest implements Filter{ public void destroy() { System.out.println("----Filter Destroy----"); } public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException { // Preprocess the request and response request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("----call service Execute a piece of code before----"); // Execute target resources, release filterChain.doFilter(request, response); System.out.println("----call service Then execute a piece of code----"); } public void init(FilterConfig arg0) throws ServletException { System.out.println("----Filter initialization----"); } }
Step 2: configure the filter in web. xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!--Configure filter--> <filter> <filter-name>FilterTest</filter-name> <filter-class>com.yangcq.filter.FilterTest</filter-class> </filter> <!--Mapping filter--> <filter-mapping> <filter-name>FilterTest</filter-name> <!-- "/*" Indicates that all requests are blocked --> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
3.2 Filter chain
In a web application, you can develop and write multiple filters, which are combined to be called a Filter chain. The web server determines which Filter to call first according to the registration order of the Filter in the web.xml file. When the doFilter method of the first Filter is called, the web server will create a filterchain object representing the Filter chain and pass it to the method. In the doFilter method, if the developer calls the doFilter method of the filterchain object, the web server will check whether there is still a Filter in the filterchain object. If so, the second Filter will be called; If not, the target resource is called.
4 filter configuration in spring framework
If the spring framework is used in the project, we don't need to write many filters ourselves. Spring has written some common filters for us. Let's take the character encoding filter as an example to see how to configure the filter under the spring framework.
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
It's simple, isn't it? These lines of configuration code complete the function of global control character coding. Next, let's take a look at the code of the filter characterencoding filter and feel the style of the master. If we want to write a filter, we can take this as an example.
Not yet? Let's take another look at a filter used in a project: InvilidCharacterFilter (a filter to prevent script attacks)
import java.io.IOException; import java.util.Enumeration; import javax.servlet.FilterChain; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.web.filter.CharacterEncodingFilter; /* * InvalidCharacterFilter: Filter illegal characters in request to prevent script attacks * InvalidCharacterFilter It inherits the characterencoding filter of the Spring framework, * Of course, we can also implement such a filter ourselves */ public class InvalidCharacterFilter extends CharacterEncodingFilter{ // Illegal characters to be filtered private static String[] invalidCharacter = new String[]{ "script","select","insert","document","window","function", "delete","update","prompt","alert","create","alter", "drop","iframe","link","where","replace","function","onabort", "onactivate","onafterprint","onafterupdate","onbeforeactivate", "onbeforecopy","onbeforecut","onbeforedeactivateonfocus", "onkeydown","onkeypress","onkeyup","onload", "expression","applet","layer","ilayeditfocus","onbeforepaste", "onbeforeprint","onbeforeunload","onbeforeupdate", "onblur","onbounce","oncellchange","oncontextmenu", "oncontrolselect","oncopy","oncut","ondataavailable", "ondatasetchanged","ondatasetcomplete","ondeactivate", "ondrag","ondrop","onerror","onfilterchange","onfinish","onhelp", "onlayoutcomplete","onlosecapture","onmouse","ote", "onpropertychange","onreadystatechange","onreset","onresize", "onresizeend","onresizestart","onrow","onscroll", "onselect","onstaronsubmit","onunload","IMgsrc","infarction" }; protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException{ String parameterName = null; String parameterValue = null; // Get requested parameters @SuppressWarnings("unchecked") Enumeration<String> allParameter = request.getParameterNames(); while(allParameter.hasMoreElements()){ parameterName = allParameter.nextElement(); parameterValue = request.getParameter(parameterName); if(null != parameterValue){ for(String str : invalidCharacter){ if (StringUtils.containsIgnoreCase(parameterValue, str)){ request.setAttribute("errorMessage", "Illegal character:" + str); RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error.jsp"); requestDispatcher.forward(request, response); return; } } } } super.doFilterInternal(request, response, filterChain); } }
Next, you need to configure it in web.xml:
<filter> <filter-name>InvalidCharacterFilter</filter-name> <filter-class>com.yangcq.filter.InvalidCharacterFilter</filter-class> </filter> <filter-mapping> <filter-name>InvalidCharacterFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
In addition, if we don't use the CharacterEncodingFilter class of Spring, we can write it ourselves.
import java.io.IOException; import java.util.Enumeration; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.commons.lang.StringUtils; /** * SelfDefineInvalidCharacterFilter: Filter illegal characters in request to prevent script attacks */ public class SelfDefineInvalidCharacterFilter implements Filter{ public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { String parameterName = null; String parameterValue = null; // Get requested parameters @SuppressWarnings("unchecked") Enumeration<String> allParameter = request.getParameterNames(); while(allParameter.hasMoreElements()){ parameterName = allParameter.nextElement(); parameterValue = request.getParameter(parameterName); if(null != parameterValue){ for(String str : invalidCharacter){ if (StringUtils.containsIgnoreCase(parameterValue, str)){ request.setAttribute("errorMessage", "Illegal character:" + str); RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error.jsp"); requestDispatcher.forward(request, response); return; } } } } // Execute target resources, release filterChain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { } // Illegal characters to be filtered private static String[] invalidCharacter = new String[]{ "script","select","insert","document","window","function", "delete","update","prompt","alert","create","alter", "drop","iframe","link","where","replace","function","onabort", "onactivate","onafterprint","onafterupdate","onbeforeactivate", "onbeforecopy","onbeforecut","onbeforedeactivateonfocus", "onkeydown","onkeypress","onkeyup","onload", "expression","applet","layer","ilayeditfocus","onbeforepaste", "onbeforeprint","onbeforeunload","onbeforeupdate", "onblur","onbounce","oncellchange","oncontextmenu", "oncontrolselect","oncopy","oncut","ondataavailable", "ondatasetchanged","ondatasetcomplete","ondeactivate", "ondrag","ondrop","onerror","onfilterchange","onfinish","onhelp", "onlayoutcomplete","onlosecapture","onmouse","ote", "onpropertychange","onreadystatechange","onreset","onresize", "onresizeend","onresizestart","onrow","onscroll", "onselect","onstaronsubmit","onunload","IMgsrc","infarction" }; }
You still need to configure it in web.xml:
<filter> <filter-name>SelfDefineInvalidCharacterFilter</filter-name> <filter-class>com.yangcq.filter.SelfDefineInvalidCharacterFilter</filter-class> </filter> <filter-mapping> <filter-name>SelfDefineInvalidCharacterFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
5 life cycle of filter
5.1 creation of filter
The web server is responsible for the creation and destruction of filters. When the web application starts, the web server will create an instance object of Filter and call its init method to complete the initialization function of the object, so as to prepare for interception of subsequent user requests. The Filter object will be created only once and the init method will be executed only once. The FilterConfig object representing the current Filter configuration information can be obtained through the parameters of the init method.
5.2 destruction of filter
The web container calls the destroy method to destroy the Filter, which is executed only once in the Filter's life cycle. In the destroy method, you can release the resources used by the Filter.
5.3 FilterConfig interface
When configuring Filter, users can use init param to configure some initialization parameters for Filter. When the web container instantiates the Filter object and calls its init method, it will pass in the FilterConfig object that encapsulates the Filter initialization parameters. Therefore, when writing Filter, developers can obtain the following information through the method of FilterConfig object:
- String getFilterName(): get the name of the Filter;
- String getInitParameter(String name): returns the value of the initialization parameter with the name specified in the deployment description. If it does not exist, it returns null;
- Enumeration getInitParameterNames(): returns an enumeration collection of the names of all initialization parameters of the filter;
- public ServletContext getServletContext(): returns the reference of the Servlet context object.
Example: use FilterConfig to get Filter configuration information
import java.io.IOException; import java.util.Enumeration; 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 FilterTest implements Filter { /* Filter initialization * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("----Filter initialization----"); /** * <filter> <filter-name>FilterTest</filter-name> <filter-class>com.yangcq.filter.FilterTest</filter-class> <!--Configure initialization parameters of FilterTest filter -- > <init-param> <description>FilterTest</description> <param-name>name</param-name> <param-value>gacl</param-value> </init-param> <init-param> <description>Configure initialization parameters of FilterTest filter < / description > <param-name>like</param-name> <param-value>java</param-value> </init-param> </filter> <filter-mapping> <filter-name>FilterDemo02</filter-name> <!--"/*"Means to intercept all requests -- > <url-pattern>/*</url-pattern> </filter-mapping> */ //Get the name of the filter String filterName = filterConfig.getFilterName(); //Get the initialization parameters configured in the web.xml file String initParam1 = filterConfig.getInitParameter("name"); String initParam2 = filterConfig.getInitParameter("like"); //Returns an enumerated collection of the names of all initialization parameters of the filter. Enumeration<String> initParameterNames = filterConfig.getInitParameterNames(); System.out.println(filterName); System.out.println(initParam1); System.out.println(initParam2); while (initParameterNames.hasMoreElements()) { String paramName = (String) initParameterNames.nextElement(); System.out.println(paramName); } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("FilterDemo Before execution!!!"); chain.doFilter(request, response); //Let target resources execute and release System.out.println("FilterDemo After execution!!!"); } @Override public void destroy() { System.out.println("----Filter destruction----"); } }
6 meanings of some parameters when deploying Filter
The deployment of Filter is divided into two steps:
- Register Filter;
- Map Filter.
6.1 register Filter
After the Filter is developed, it needs to be registered in the web.xml file so that it can be called by the web server. Example of registering Filter in web.xml file:
<filter> <description>Filter name</description> <filter-name>Custom name</filter-name> <filter-class>com.yangcq.filter.FilterTest</filter-class> <!--to configure FilterTest Initialization parameters of filter--> <init-param> <description>Configure initialization parameters for filters</description> <param-name>name</param-name> <param-value>gacl</param-value> </init-param> <init-param> <description>to configure FilterTest Initialization parameters of filter</description> <param-name>like</param-name> <param-value>java</param-value> </init-param> </filter>
- Description: used to add description information. The content of this element can be empty and description can not be configured;
- Filter name: used to specify a name for the filter. The content of this element cannot be empty;
- Filter class: the element is used to specify the complete qualified class name of the filter;
- Init param: the element is used to specify initialization parameters for the filter. Its child element param name specifies the name of the parameter and param value specifies the value of the parameter.
In the filter, you can use the FilterConfig interface object to access the initialization parameters. If the filter does not need to specify initialization parameters, the init param element may not be configured.
6.2 mapping Filter
After registering the Filter in the web.xml file, map the Filter in the web.xml file, for example:
<!--Mapping filter--> <filter-mapping> <filter-name>FilterTest</filter-name> <!-- "/*" Indicates that all requests are blocked --> <url-pattern>/*</url-pattern> </filter-mapping>
- Filter mapping: the element is used to set the resources intercepted by a filter. The resources intercepted by the filter can be specified in two ways: Servlet name and resource access request path;
- Filter name: the sub element is used to set the registered name of the filter. The value must be the name of the filter declared in the filter element;
- URL pattern: set the request path intercepted by the Filter (the URL Style associated with the Filter);
- Servlet Name: Specifies the name of the servlet intercepted by the filter;
- Dispatcher: specifies how the resource intercepted by the Filter is called by the Servlet container. It can be one of REQUEST, INCLUDE, FORWARD and ERROR. The default is REQUEST. Users can set multiple dispatcher sub elements to specify how the Filter intercepts multiple calls of resources. For example:
<filter-mapping> <filter-name>testFilter</filter-name> <url-pattern>/index.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
The values that can be set by 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 the include() or forward() method of RequestDispatcher, the filter will not be called;
- INCLUDE: if the target resource is accessed through the include() method of RequestDispatcher, the filter will be called. Otherwise, the filter will not be called;
- FORWARD: if the target resource is accessed through the forward() method of RequestDispatcher, the filter will be called. Otherwise, the filter will not be called;
- ERROR: if the target resource is called through the declarative exception handling mechanism, the filter will be called. Otherwise, the filter will not be called.