What is a filter
Filters are one of the more advanced features of servlets, so don’t think of them as anything more than a Java class that implements the Filter interface!
First, let’s look at where filters are in the Web container:
As you can see from the figure above, when the browser sends a request to the server, the filter is executed before accessing Web resources. The e server also passes the filter in Response to the Response from the Web resource before reaching the browser.
It’s easy to see how a filter can be likened to a mesh. Let’s think about what a real-world strainer could do: filter out the tea leaves while it’s brewing. How does the strainer filter the tea? The size of the mesh, as long as the mesh is smaller than tea, you can achieve filtration!
In a Web container, filters can do: Filtering sensitive string, avoid regulations cannot appear sensitive string 】 【 Chinese garbled 【 rules Web resources use utf-8 】, privilege to verify the rule only with the Session or browser cookies, to access Web resources], etc., etc., the role of the filter is very big, just imagine an unexpected effect
That is: when we need to restrict user access to certain resources, processing certain resources in advance when processing requests, processing the contents of the server response and returning them, we use filters to do it!
Why do I need a filter
Here’s an example:
No filter to solve the Chinese garble problem
-
If I didn’t use filters: the browser sends data to the Servlet via HTTP requests, and if Chinese is present, it must specify the encoding, otherwise it will be garbled!
-
The JSP page submits Chinese data to the Servlet for processing
<form action="${pageContext.request.contextPath}/Demo1" method="post">
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
Copy the code
- If the Servlet does not specify an encoding, the result is garbled
Other posts on how to solve Chinese garble problems in servlets include: blog.csdn.net/hon_3y/arti…
That is: if EVERY time I receive Chinese data from a client, I have to encode it in Serlvet. The code duplication rate is too high !!!!
There are filters to solve the problem of Chinese garble
With filters, things are different: as long as I specify an encoding in the filter, I can make the entire Web resource use that encoding, and reuse is ideal!
The filter API
Any Java class that implements the Filter interface can be called a Filter! The method of the Filter interface is also quite simple:
The init() and destory() methods are the same as servlets. Executed only once when the Web server loads and destroys!
It is worth noting that the doFilter () method, * * it has three parameters (ServletRequest, ServletResponse, FilterChain), * * once upon a time two parameters we can find: filter can finish any protocol filtering operation!
So what is FilterChain? Let’s see:
FilterChain is an interface in which the doFilter() method is defined. What is going on here ??????
We can think of it this way: there is not just one filter, so how do we manage these filters? The chain structure is used in Java. Put all the filters in the FilterChain, and if the conditions are met, the next filter is executed (if there are no filters, the target resource is executed).
Now I want to be able to filter stones and tea leaves out of a teacup. The stone is on the first floor and the tea is on the first floor. So the filter should have two layers of mesh. The Filter is called the FilterChain, and the stone Filter and the tea Filter are the filters. In the stone filter, the tea belongs to the next layer, put the tea release, let the tea filter tea. After the tea is filtered, what is left is the tea (tea is our target resource).
Quick start
Write a simple filter
- Java classes that implement the Filter interface are called filters
public class FilterDemo1 implements Filter {
public void destroy(a) {}public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
Let the next filter execute, if there are no filters, execute the target resource.
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {}}Copy the code
The filter deployment
Filters and servlets are the same and need to be deployed to a Web server.
The first method: configure in the web.xml file
filter
<filter>
Used to register filters
<filter>
<filter-name>FilterDemo1</filter-name>
<filter-class>FilterDemo1</filter-class>
<init-param>
<param-name>word_file</param-name>
<param-value>/WEB-INF/word.txt</param-value>
</init-param>
</filter>
Copy the code
<filter-name>
Used forSpecify a name for the filterThe content of this element cannot be empty.<filter-class>
Element used to specify the filterThe full qualified class name.<init-param>
The element is used to specify initialization parameters for the filter, and its children specify parameter names,<param-value>
Specifies the value of the argument. In the filter, yesUse the FilterConfig interface object to access initialization parameters.
filter-mapping
The
element sets the resources that a filter is responsible for intercepting.
The resource that a Filter intercepts can be specified in two ways: the Servlet name and the request path for resource access
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/ *</url-pattern>
</filter-mapping>
Copy the code
<filter-name>
The child element is used to set the filter’s registration name.The value must be the name of the filter declared in the element<url-pattern>
Set the request path to be intercepted by the filter (the URL style associated with the filter)-
specifies the name of the servlet blocked by the filter.
<dispatcher>
Specifies how the resource intercepted by the filter is invoked by the Servlet containerOne of REQUEST,INCLUDE,FORWARD and ERROR, default REQUEST. You can set multiple Settings<dispatcher>
Child elementsUsed to specify that Filter intercepts multiple calls to a resource.
dispatcher
The values that can be set for child elements and their meanings:
- REQUEST: The Web container invokes the filter when the user accesses the page directly. This filter is not invoked if the target resource is accessed through the RequestDispatcher’s include() or forward() methods.
- INCLUDE: This filter is called if the target resource is accessed through the RequestDispatcher’s INCLUDE () method. Otherwise, the filter is not called.
- FORWARD: This filter will be called if the target resource is accessed through the FORWARD () method of the RequestDispatcher, otherwise it will not be called.
- ERROR: This filter is invoked if the target resource is invoked through declarative exception handling. Otherwise, the filter is not called.
The second way is through annotations
@WebFilter(filterName = "FilterDemo1",urlPatterns = "/ *")
Copy the code
The above configuration is “/*”. All Web resources require path filters
If you want to filter some Web resources, you need to specify the name of the Web resource.
Filter execution order
As mentioned above, the doFilter() method of a Filter is extremely important. The FilterChain interface represents all filters, and the doFilter() method in the FilterChain determines whether the next Filter is allowed to execute (if there are no filters, the target resource is executed).
Testing a
- First print a sentence in the doFilter() of the filter and call the doFilter() method of the chain object
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("I'm filter one.");
Allow the next filter to execute, or the target resource to execute.
chain.doFilter(req, resp);
}
Copy the code
- Let’s visit the test.jsp page:
We found that test.jsp (our target resource) was successfully accessed and the string was printed on the server!
Test two
Let’s try it outchain.doFilter(req, resp);
This code comment look!
The test.jsp page does not have any output (that is, no JSP page is accessed).
Test three
Look directly at the code below. We already know that “ready to release” will be printed on the console and the test.jsp page can be accessed, but will “release completed” be printed on the console?
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("Ready for release");
Allow the next filter to execute, or the target resource to execute.
chain.doFilter(req, resp);
System.out.println("Release completed");
}
Copy the code
The answer is very simple and will definitely be printed on the console. Let’s take a look:
Notice that the complete process sequence looks like this: The client sends the HTTP request to the Web server, which executes the filter. When it reaches “Ready for release,” it prints the string to the console, and then executes the doFilter() method. When the Web server finds that there is no filter, it executes the target resource (that is, test.jsp). After executing the target resource, go back to the filter, continue executing the code, and print “Release done”
The test of four
Let’s add another filter and see the order of execution.
- Filter 1
System.out.println("Filter 1 is running");
Allow the next filter to execute, or the target resource to execute.
chain.doFilter(req, resp);
System.out.println("Filter 1 is ready.");
Copy the code
- Filter 2
System.out.println("Filter 2 is running.");
chain.doFilter(req, resp);
System.out.println("Filter 2 is ready.");
Copy the code
- Servlet
System.out.println("I am Servlet1");
Copy the code
When we access Servlet1, let’s see what appears on the console:
Execute FilterDemo1, permit FilterDemo2, permit Servlet1, Servlet1 returns to FilterDemo2, and FilterDemo2 returns to FilterDemo1
Note: the order of execution between filters depends on the order of execution of the mapping in the web. XML file. If configured via annotations, compare the string priorities of urlPatterns
Filter Simple Application
- Three typical applications of filter:
- 1. Whether to call chain.dofilter (Request, response) according to the condition in filter, that is, whether to let the target resource execute
- 2. Request \ Response can be preprocessed before the target resource is executed
- 3. After the execution of the target resource, the execution results of the target resource can be captured to achieve some special functions
Disable the browser from caching all dynamic pages
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// Set the HTTP request header to response.
// We are using HTTP. The ServletResponse does not have a way to set the request header, so it must be HttpServletRequest
// If we write Filter, we will force them to be Http type
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control"."no-cache");
response.setHeader("Pragma"."no-cache");
// The response of the release target resource is set not to be cached
chain.doFilter(request, response);
}
Copy the code
- Before filtering, the response header would look like this:
- After filtering, the response header looks like this:
Automatic login
Develop entity, collection simulation database, Dao
- Entity:
private String username ;
private String password;
public User(a) {}public User(String username, String password) {
this.username = username;
this.password = password;
}
// Various setters and getters
Copy the code
- Ensemble simulation database
public class UserDB {
private static List<User> users = new ArrayList<>();
static {
users.add(new User("aaa"."123"));
users.add(new User("bbb"."123"));
users.add(new User("ccc"."123"));
}
public static List<User> getUsers(a) {
return users;
}
public static void setUsers(List<User> users) { UserDB.users = users; }}Copy the code
- The development of dao
public User find(String username, String password) {
List<User> userList = UserDB.getUsers();
// Check the List to see if there are any corresponding username and password
for (User user : userList) {
if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
returnuser; }}return null;
}
Copy the code
Login interface
<form action="${pageContext.request.contextPath}/LoginServlet">The user name<input type="text" name="username">
<br>password<input type="password" name="password">
<br>
<input type="radio" name="time" value="10">Ten minutes<input type="radio" name="time" value="30">30 minutes<input type="radio" name="time" value="60">1 hour<br>
<input type="submit" value="Login">
</form>
Copy the code
The Servlet that handles the login
// Get the data sent by the client
String username = request.getParameter("username");
String password = request.getParameter("password");
UserDao userDao = new UserDao();
User user = userDao.find(username, password);
if (user == null) {
request.setAttribute("message"."Wrong username or password!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
// If not empty, store an attribute in session
request.getSession().setAttribute("user", user);
request.setAttribute("message"."Congratulations, you're logged in!");
// If you want the user to close the browser and still log in, you must use cookies
Cookie cookie = new Cookie("autoLogin", user.getUsername() + "." + user.getPassword());
// Set the maximum Cookie declaration period to user-specified
cookie.setMaxAge(Integer.parseInt(request.getParameter("time")) * 60);
// Return the Cookie to the browser
response.addCookie(cookie);
// Go to the prompt page
request.getRequestDispatcher("/message.jsp").forward(request, response);
Copy the code
The filter
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
// If the user does not close the browser, there is no need for cookies to concatenate login
if (request.getSession().getAttribute("user") != null) {
chain.doFilter(request, response);
return;
}
// If the user closes the browser, the session value is not available. So use cookies to automatically log in
Cookie[] cookies = request.getCookies();
String value = null;
for (int i = 0; cookies ! =null && i < cookies.length; i++) {
if (cookies[i].getName().equals("autoLogin")) { value = cookies[i].getValue(); }}// Get the user name and password for the Cookie
if(value ! =null) {
String username = value.split("\ \.") [0];
String password = value.split("\ \.") [1];
UserDao userDao = new UserDao();
User user = userDao.find(username, password);
if(user ! =null) {
request.getSession().setAttribute("user", user);
}
}
chain.doFilter(request, response);
Copy the code
- Effect:
improved
We put the username and password directly in the Cookie, which is clear text. Anyone who knows a little programming will know your account number.
Therefore, we need to encrypt the password!
Cookie cookie = new Cookie("autoLogin", user.getUsername() + "." + md5.md5(user.getPassword()));
Copy the code
- In the filter, the encrypted password is not the database password. Therefore, we need to add a feature to the Dao [find users by username].
public User find(String username) {
List<User> userList = UserDB.getUsers();
// Check the List to see if there are any corresponding username and password
for (User user : userList) {
if (user.getUsername().equals(username)) {
returnuser; }}return null;
}
Copy the code
- In the filter, compare whether the MD5 password brought in by the Cookie is the same as the password obtained in the database (also md5)
// Get the user name and password for the Cookie
if(value ! =null) {
String username = value.split("\ \.") [0];
String password = value.split("\ \.") [1];
// The password obtained in the Cookie is md5 encrypted and cannot be directly compared with the database password
UserDao userDao = new UserDao();
User user = userDao.find(username);
// Get the user information from the user name, get the user password, the password is md5
String dbPassword = md5.md5(user.getPassword());
// If the two passwords match, it is the correct password
if (password.equals(dbPassword)) {
request.getSession().setAttribute("user", user); }}Copy the code
If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat can follow the wechat public account :Java3y