“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

I. Overview of filters

1.1 what is a filter

It is one of the three components of JavaWeb. The three components are Servlet, Listener, and Filter.

It is a JavaEE specification. The interface is used to intercept requests and filter responses.

1.2 Filter process

1.3 implementation of filters

public class AdminFilter implements Filter {
    /** * the doFilter method is used to intercept requests. You can do permission checking */
    @Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChainfilterChain) throws IOException, ServletException {
      HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
      HttpSession session = httpServletRequest.getSession();
      Object user = session.getAttribute("user");
        // If the value is null, you are not logged in yet
	  if (user == null) {    servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
      return;
 	}else{
          // Let the application continue to access the user's target resourcefilterChain.doFilter(servletRequest,servletResponse); }}}Copy the code

This is then configured in web.xml

<! The --filter tag is used to configure a filter -->
<filter>
	<! -- alias filter -->
	<filter-name>AdminFilter</filter-name>
	<! -- Configure the name of the filter class -->
	<filter-class>com.atguigu.filter.AdminFilter</filter-class>
</filter>
<! --filter-mapping Configure the intercepting path of the filter -->
<filter-mapping>
	<! --filter-name Indicates the filter for which the current interception path is used -->
	<filter-name>AdminFilter</filter-name>
	<! --url-pattern Interception path/indicates that the request address is http://ip:port/ project path/Web directory mapped to IDEA /admin/* indicates that the request address is http://ip:port/ project path /admin/* -->
	<url-pattern>/admin/*</url-pattern>
</filter-mapping>
Copy the code

1.4 Life cycle of Filter

1.5, the FilterConfig

The FilterConfig class is the configuration file class for the Filter. Each time Tomcat creates a Filter, it also creates a FilterConfig class, which contains the configuration information of the Filter configuration file.

The FilterConfig class is used to obtain the configuration content of the filter:

  1. The content of the Filter name filter-name is obtained.
  2. Gets the init-param initialization parameter configured in Filter
  3. Get the ServletContext object.

1.6. Filter chain

1.7. Intercept path of Filter

Filter there are three path matches for blocking:

  1. Precise matching
  2. Directory match
  3. Suffix name matching

1.7.1 Accurate matching

<! The request address must be: http://ip:port/ project path /login.jsp -->
<url-pattern>/login.jsp</url-pattern>
Copy the code

1.7.2 directory Matching

<! The request address must be: http://ip:port/ project path /admin/* -->
<url-pattern>/admin/*</url-pattern>
Copy the code

1.7.3. Suffix matching

<! --> < span style = "text-align: center;"
<url-pattern>*.html</url-pattern>

<! -- the path configured above means that the request address must end with. Do to intercept -->
<url-pattern>*.do</url-pattern>
Copy the code

It only cares if the requested address matches, not if the requested resource exists!!

2. Character encoding filter

The previous code processing is directly written into the Servlet, so it has the problem of code duplication, can not be reused, and increase the cost of maintenance, we want to set one place, global effect. Our solution is to process the encoding in the request (Filter) before accessing the Servlet.

2.1 Code implementation

We write the CharacterEncodingFilter class and set the encoding to UTF-8 in the filter’s doFilter method.

public class CharacterEncodingFilter implements Filter {
		@Override
		public void init(FilterConfig filterConfig) throws ServletException {}@Override
		public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		// Set the request code
		servletRequest.setCharacterEncoding("UTF-8");
		/ / release
		filterChain.doFilter(servletRequest, servletResponse);
	}
		@Override
		public void destroy(a) {
	s}
}
Copy the code

Then configure the CharacterEncodingFilter filter in web.xml.

<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>cn.wolfcode.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<url-pattern>/ *</url-pattern>
</filter-mapping>
Copy the code

2.2. Code optimization

In the filter, we set the encoding value of the request parameter to UTF-8. In this case, the encoding is written dead in Java code. If you need to change it later, the UTF-8 is hard coded and cannot be flexibly configured.

2.2.1. Configure the character encoding

Filter, like servlets, can also be configured with initialization parameters. The configuration in web.xml is as follows:

<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>cn.wolfcode.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
	<param-name>encoding</param-name>
	<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<url-pattern>/ *</url-pattern>
</filter-mapping>
Copy the code

2.2.2. Modify CharacterEncodingFilter

Get the initialization parameter value of the configured Encoding from the FilterConfig object in the initialization method.

public class CharacterEncodingFilter implements Filter {
	private String encoding;
		@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.encoding = filterConfig.getInitParameter("encoding");
	}
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		if(StringUtil.hasLength(encoding) {
		// Set the request code
		servletRequest.setCharacterEncoding(this.encoding);
	}
		/ / release
		filterChain.doFilter(servletRequest, servletResponse);
	}
	@Override
	public void destroy(a) {}}Copy the code

Three, login verification filter combat

3.1, the previous code

In actual development, there will be many resources in our project that need to be accessed after login, so we need to judge whether the current user is logged in before the request reaches these resources. If not, we should jump to the login page. Before, we added the login judgment code to the resources that need login access.

	Object obj = req.getSession().getAttribute("USER_IN_SESSION");
	if(obj == null){
	resp.sendRedirect("/login.jsp");
	return;
Copy the code

This code is sufficient, but there is a lot of duplication of code that checks the logins in the code for each resource, increasing maintenance costs. This completely defeats the purpose of using filters (set once, shared by all servlets).

3.2 Filter code implementation

3.2.1. Write CheckLoginFilter

public class CheckLoginFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {}@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		// Convert requests and responses into objects that conform to the HTTP protocol
		HttpServletRequest req = ((HttpServletRequest) servletRequest);
		HttpServletResponse resp = ((HttpServletResponse) servletResponse);
		Object obj = req.getSession().getAttribute("USER_IN_SESSION");
		// No login, redirect to the login page
		if(obj == null) {
		resp.sendRedirect("/login.jsp");
		return;
	}
		// After the login, the access is allowed
	filterChain.doFilter(req, resp);
}
	@Override
	public void destroy(a) {}}Copy the code

3.2.2 Configure CheckLoginFilter

After we have written the filter, we need to configure the filter in web.xml.

<filter>
	<filter-name>checkLoginFilter</filter-name>
	<filter-class>cn.wolfcode.web.filter.CheckLoginFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>checkLoginFilter</filter-name>
	<url-pattern>/ *</url-pattern>
</filter-mapping>	
Copy the code

3.3. Methods to Access resources anonymously

Anonymous access resources are resources that can be accessed without a login, such as /login.jsp, /login, /randomCode, static resources, and so on. If not excluded, then when the browser requests these resources, also need to log in, which will cause these resources to be inaccessible. In this case, you only need to specify which resources the CheckLoginFilter does or does not perform login verification.

3.3.1 Method 1:

You can specify which resources the CheckLoginFilter does not verify by modifying the CheckLoginFilter and configuring initialization parameters to specify which resources the CheckLoginFilter does not verify.

<filter>
	<filter-name>checkLoginFilter</filter-name>
	<filter-class>cn.wolfcode.web.filter.CheckLoginFilter</filter-class>
	<init-param>
		<param-name>unCheckUri</param-name>
	<param-value>/login.jsp; /login; /randomCode</param-value>
</init-param>
</filter>
<filter-mapping>
	<filter-name>checkLoginFilter</filter-name>
	<url-pattern>/ *</url-pattern>
</filter-mapping>
Copy the code
public class CheckLoginFilter implements Filter {
    private List<String> unCheckUriList;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.unCheckUriList =
            Arrays.asList(filterConfig.getInitParameter("unCheckUri").split(";"));
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = ((HttpServletRequest) servletRequest);
        HttpServletResponse resp = ((HttpServletResponse) servletResponse);
        Object obj = req.getSession().getAttribute("USER_IN_SESSION");
		// Get the requested resource path
        String uri = req.getRequestURI();
		// If you are not logged in and you are not accessing an anonymous resource, redirect to the login page
        if(obj == null && !unCheckUriList.contains(uri)) {
            resp.sendRedirect("/login.jsp");
            return;
        }
		// After the login, the access is allowed
        filterChain.doFilter(req, resp);
    }
    @Override
    public void destroy(a) {}}Copy the code

3.3.2 Method 2

Because it turns out that static resources are still not accessible, and in actual development, if we need to exclude more resources, especially static resources, it will be very troublesome. This time, specify which resources CheckLoginFilter is used for login verification. Save all the resources to be checked to the check directory. First, change the filter path of CheckLoginFilter.

<filter>
	<filter-name>checkLoginFilter</filter-name>
	<filter-class>cn.wolfcode.web.filter.CheckLoginFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>checkLoginFilter</filter-name>
	<! -- Only access to resources in the check directory will be checked -->
	<url-pattern>/check/*</url-pattern>
</filter-mapping>
Copy the code

Then modify the CheckLoginFilter

public class CheckLoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = ((HttpServletRequest) servletRequest);
        HttpServletResponse resp = ((HttpServletResponse) servletResponse);
        Object obj = req.getSession().getAttribute("USER_IN_SESSION");
		// No login, redirect to the login page
        if(obj == null) {
            resp.sendRedirect("/login.jsp");
            return;
        }
		// After the login, the access is allowed
        filterChain.doFilter(req, resp);
    }
    @Override
    public void destroy(a) {}}Copy the code

Finally, you only need to modify the resource for login verification and add the /check path.

4, the Listener (Listener)

The Listener is a Java Web component that listens for the creation and destruction of scope objects and the change of scope property values. If these actions are triggered by the user, the corresponding listener action is immediately executed.

4.1 Classification of listeners

The objects the listener listens for are scope objects, scope properties, and the actions it listens for: the creation and destruction of scope objects, the addition, deletion, and modification of scope attribute values. Listeners can be classified by scope objects:

  1. ServletRequestListener
  2. HttpSessionListener
  3. ServletContextListener

By scope attribute:

  1. ServletRequestAttributeListener
  2. HttpSessionAttributeListener
  3. ServletContextAttributeListener

4.2. Develop the listener step

  1. Create a class that implements the corresponding interface as required.
  2. Implement the methods.
  3. Turn the listener over to Tomcat.

4.3, actual combat

Our demand is to make a website to count the number of visitors.

4.3.1 Write a VisitorListener

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class VisitorListener implements HttpSessionListener {
    private static long totalCount = 0;
    // Session object creation executes the following method
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        totalCount++;
        System.out.println("Online population:" + totalCount);
    }
    // Session object destruction executes the following method
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { totalCount--; }}Copy the code

4.3.2 Configure the VisitorListener

To configure the VisitorListener, you can use either an annotation configuration (just post @webListener to your own write listener class) or an XML configuration.

<listener>
	<listener-class>cn.wolfcode.web.listener.VisitorListener</listener-class>
</listener>
Copy the code