day036 filter

1 case 1 - automatic login

1.1 requirements and process introduction

When the user directly accesses the login page (e.g. shopping cart page, order page, etc.), the user object of the last login is directly displayed. This function is the function of automatic login. If the user did not check auto login when logging in last time, the user will not be displayed when accessing the login page directly. The user needs to log in first when adding shopping cart and submitting order.

(in short, it's the same as jd. Today, we only do the previous sentence, and the latter sentence is permission control, which is the later content.)

 

1.2 technical analysis

1: Session technology can be used to let the server know the multiple requests sent by the browser.

2: You need to use filter technology to filter every request sent by the user before allowing the user to execute the real resource.

1.3 filter overview

A filter is a java applet running at the front end of the server.

servlet, filter and listener are collectively referred to as the three components of the server. They are all created by the tomcat server and called by the service.

Differences between servlet and filter:

0: the filter can do what the servlet can do, and the servlet can't do what the filter can do.

1: Servlets are usually used for specific request processing, while filter s are usually used for general request processing;

2: filter must take precedence over servlet execution;

filter must be passed before entering the servlet and when leaving the servlet.

1.4 application scenario of filter

1: The Chinese parameters of all requests of the website are garbled and the response is garbled.

2: Site access control.

3: Automatic login.

4: Sensitive word filtering.

1.5 preparation steps of filter

The English name of filter: filter is an interface defined by Java EE.

Programmers only need to implement the filter interface and write the corresponding methods.

About the three parameters of the doFilter method in the filter interface:

Parameter of ServletRequest type: represents the request object.

Parameter of ServletResponse type: represents the response object.

Parameter of FilterChain type: represents the object used for release. (if it is not released, the resources requested by the browser will not receive any response)

1.6 implementation of automatic login case

1: Case environment construction. (database creation, static page replication, jar package selection, tool class replication)

2: Write a three-tier package structure.

3: Add login Modify the HTML file to login JSP file.

4: Write LoginServlet to complete the user's complete login process. When the user logs in successfully, the user object needs to be saved in the session.

5: Write service and dao.

6: Modify the login servlet to judge whether the user wants to complete the automatic login action for the user when the user logs in successfully.

If desired, create a cookie object and save the username and password for 7 days

If not, delete the original cookie immediately.

7: Write a filter, get the cookie in the filter, and query the database with the user name and password in the cookie. If you can find it, help the user save the user object to the session.

 

be careful:

The so-called login means that there are user objects in the session.

Partial reference code:

explain:

In the page

User name label: name="username"

Password label: name="password"

Whether to log in automatically: name="autoLogin" value="ok"

 

 

Filter autologinfilter java:

package com.itheima.anli00_filter;

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.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.itheima.anli02_service.UserService;
import com.itheima.anli04_domain.User;

/**
 * filter that completes automatic login
 */
public class AutoLoginFilter implements Filter {

    public void destroy() {
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /*
         * Idea:
         * 
         *  1:Judge whether the user object has been owned in the session. If yes, it proves that the user has logged in and can be released directly. Otherwise, continue to judge the next step;
         *  2:Obtain all cookies carried by the browser and find out the cookie named auto; If there is no cookie, release it directly, otherwise continue to the next step;
         *  3:Obtain the user name and password in the cookie and query the database; If the query is successful, it will be saved to seesion. If not, it will be released directly;
         * 
         */
        
        HttpServletRequest r = (HttpServletRequest)request;
        HttpSession se = r.getSession();
        Object user = se.getAttribute("user");
        if(user==null){
            //You need to continue to the next step
            Cookie[] cs = r.getCookies();
            if(cs!=null){
                //Indicates that there are some cookie s
                Cookie c=null;//Prepare to use c to save the cookie object we want
                for (Cookie cookie : cs) {
                    if(cookie.getName().equals("auto")){
                        c=cookie;
                    }
                }
                //Determine if a cookie was found
                if(c!=null){
                    String value = c.getValue();
                    String[] split = value.split("<itheima>");
                    UserService us = new UserService();
                    User u2 = us.findUserByUsernameAndPassword(split[0],split[1]);
                    if(u2!=null){
                        //Save the session for this user
                        se.setAttribute("user",u2);
                    }
                }
            }
        }
        //Release
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
    }

}

LoginServlet.java

package com.itheima.anli01_web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.anli02_service.UserService;
import com.itheima.anli04_domain.User;

/**
 * servlet for user login
 */
public class LoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println(request);
        //1: Reference transfer
        String un = request.getParameter("username");
        String ps = request.getParameter("password");
        String au = request.getParameter("autoLogin");
        //2: Call business layer
        UserService  us = new UserService();
        User u = us.findUserByUsernameAndPassword(un,ps);
        //3: To save, you must save the user to the session object,
        if(u==null){
            //Explain that the user name or password is wrong, and return to login JSP, let the user log in again
            request.setAttribute("msg","Wrong user name or password");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;//End method
        }
        //4: Description: the user is found and saved in the session
        request.getSession().setAttribute("user", u);
        //Determine whether the user wants us to complete the automatic login function 
        Cookie c = new Cookie("auto",un+"<itheima>"+ps);
        c.setPath("/");
        if("ok".equals(au)){
            //Indicates that the user wants to log in automatically and set the cookie to 7 days
            c.setMaxAge(60*60*24*7);
        }else{
            //Note that the user does not want to log in automatically, and set the cookie to 0 seconds
            c.setMaxAge(0);
        }
        response.addCookie(c);
        //The forwarded shopping website can let users go shopping
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

2 filter summary

2.1 Filter life cycle

The life cycle of filter is the process from the creation of filter to the death of filter.

There are three life cycle methods for Filter:

init() initialization

doFilter() performs filtering

destroy (death)

 

doFilter() method: as long as the path can be matched successfully, it will be executed one by one, even if multiple filters match the path. The order of execution is only the same as that of web The configuration order of filter mapping in XML is related to the configuration order. It is executed one by one from top to bottom.

init() method: the filter object will be created as tomcat starts.

destroy() method: it dies when the tomcat server stops normally.

 

2.2 multiple filter order problems:

The order is only the same as on the web XML is related to the configuration order.

2.4 FilterConfig object (understand)

On the web When configuring the init param attribute and attribute value in the filter tag in XML, you can use the FilterConfig object to obtain these initialization configuration parameters.

For example:

<filter>
    <display-name>AutoLoginFilter</display-name>
    <filter-name>AutoLoginFilter</filter-name>
    <filter-class>com.itheima.anli00_filter.AutoLoginFilter</filter-class>
    <init-param>
        <param-name>aaa</param-name>
        <param-value>111</param-value>
    </init-param>
</filter>

There are in the api of Java EE.

Common API s:

Getinitparameter (property name);

2.5 configuration of URL pattern in filter

There are three configurations in filter:

1: Perfect match / xxx

2: Directory matching (wildcard matching) / * (most used)

3: Suffix matches * xxx (occasionally used)

be careful:

The three matching methods, regardless of priority, will be executed as long as they are successfully matched with the path, and the execution order is only the same as that of web XML is related to the configuration order.

2.6 interception mode of filter

In filter mapping, you can also not use URL pattern.

Use servlet name tag instead (understand, not commonly used)

For example:

 

About filtering method:

 

3 case 3 - Chinese coding filter

3.1 requirements

When the user accesses any servlet in the project, there is no need to process Chinese parameters or Chinese response in the servlet, which can ensure the normal operation of parameters and response data. (random code is not allowed)

3.2 technical analysis

There are three methods to obtain parameters in the servlet: getParameter , getParameterValues , getParameterMap

As long as these three methods are enhanced, the result of Chinese parameter garbled problem can be realized.

When responding, you only need to set the content type header of the response before calling getWriter or getOutputStream.

This can be done using filters.

3.3 techniques for enhancing a class's methods

Method 1: inherit and rewrite methods.

Disadvantages:

The subclass and the parent class are completely bound together. The coupling degree is too high and the code is not flexible. (in this case, the coupling with tomcat is too high, so it's difficult to change the server without tomcat)

Benefits:

Simple, easy to write, fast.

Mode 2: decorator mode

(ps: all kinds of design patterns, no matter what they are, are only used when extracting tool classes)

Decorator mode means that class A and class B are brother classes. When developing interfaces in the future, the methods in class a will be used to replace the methods in class B. then it can be called a decorator B. A is the decorator and B is the decorator.

 

Benefits:

The code flexibility is relatively high. As long as the interface is not replaced, the subclass can be replaced.

Premise of use:

The decorator must be able to use the object of the decorator, and need to implement the same interface as the decorator.

Code steps:

1: Write a class that implements the same interface as the decorator. (become brothers)

2: Define a member variable of interface type in the class to save the decorated object.

3: Write the enhanced method. (enhancement method)

In this case, because the HttpServletRequest interface is directly used, there are too many methods that need to be rewritten. Therefore, we choose to inherit the HttpServletRequestWrapper class to generate a relationship with the HttpServletRequest interface.

3.4 filter code implementation:

package com.itheima.anli00_filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Set;

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;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/**
 * We use decorator mode to enhance the reqeust object
 */
public class MyEncodingFilter implements Filter {
    public void destroy() {
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //1: Convert request and response to sub interface types
        HttpServletRequest r = (HttpServletRequest)request;
        HttpServletResponse res = (HttpServletResponse)response;
        //2: Obtain the request method. If it is a get request, use the decorator mode to solve the garbled code. If it is a post request, directly face the original request object and call setCharacterEncoding method to solve the garbled code
        String method = r.getMethod();
        //3: First solve the problem of response garbled code
        res.setContentType("text/html;charset=utf-8");
        if("GET".equalsIgnoreCase(method)){
            //Explain who needs to use decoration
            MyRequest z=new MyRequest(r);
            //Release and pass the decorated object
            chain.doFilter(z, res);
        }else{
            //Can be solved directly
            r.setCharacterEncoding("utf-8");
            chain.doFilter(r, res);
        }
    }
    public void init(FilterConfig fConfig) throws ServletException {
    }
}

class MyRequest extends HttpServletRequestWrapper{
    //Define a member variable of interface type, which is used to save the decorated object
    private HttpServletRequest request ;
    //In order to solve the problem that when the method is called many times, the first time is not disordered, but then the code is disordered, we need to define a flag to make the conversion process execute only once
    private boolean flag = true;//Conversion is possible by default
    public MyRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    //Enhancement methods;
    //1: Enhanced getParameterMap
    public Map<String, String[]> getParameterMap() {
        //1: First use request to get the parameters passed by the original browser
        Map<String, String[]> map = request.getParameterMap();
        //2: At this time, if there are Chinese parameters in the map, it must be garbled!!! The original request can be solved directly by considering only the get request
        if(flag){
            Set<String> set = map.keySet();
            for (String key : set) {
                String[] vs = map.get(key);
                //Process the parameters in the array. After processing, you need to save the parameters back to the array
                for(int i=0;i<vs.length;i++){
                    //As long as each element of the array is modified, the elements in the array in the map will naturally change (Chinese garbled code has been solved)
                    try {
                        vs[i]=new String(vs[i].getBytes("iso8859-1"),"utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        throw new RuntimeException();
                    }
                }
            }
            //Change flag to false
            flag = false;
        }
        //Return the map that has solved the garbled code
        return map;
    }
    //Rewrite the getParameterValues method. The data in this method can be obtained directly from the map, because the map has solved the garbled code
    @Override
    public String[] getParameterValues(String name) {
        return getParameterMap().get(name);
    }
    @Override
    public String getParameter(String name) {
        String[] vs = getParameterValues(name);
        if(vs==null){
            return "";
        }
        return vs[0];
    }
}

 

Keywords: Java filter

Added by c4onastick on Fri, 04 Mar 2022 21:59:13 +0200