Java Learning day56_Web Component

Posted by cainy1982 on Fri, 01 Oct 2021 18:35:26 +0200

Web Component

Listener

Monitor.

In the early EE specification, there was only one component of the servlet, followed by two other components, listener and filter.

There are three components in JavaEE: Servlet (developing dynamic web resources), Listener (listener), and Filter (filter)


Listeners on the web:

Listenee: such as a ServletContext object

Listeners: Written listeners

Listen for events: creation and destruction of ServletContext objects

Trigger Event: Call the corresponding method in the listener


Use (Master)

1. Write a class to implement the ServletContextListener interface

2. Configure the Listener (web.xml annotation)

<listener>
    <listener-class>com.cskaoyan.listener.MyServletContextListener</listener-class>
</listener>

Or notes

package com.cskaoyan.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletContextListener implements ServletContextListener {

    /**
     * Execute this code logic when the servletContext is created
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("context init");
    }

    /**
     * Execute this code logic when the servletContext object is destroyed
     * @param servletContextEvent
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("context destroy");
    }
}

You don't need to access any addresses to perform this.

What's the use?

In fact, we can write the code logic that was written in the init method of the servlet and set load-on-startup=1 in the listener. It's more appropriate.

If you previously wanted to set up a piece of code that did not depend on whether the current servlet was accessed, you could set an init to run as the application loaded. Write this code logic inside the init.

This code logic is not really very closely related to the current servlet. For example, shopping cart cases, instantiate goods. It can be written in indexServlet or GoodsServlet, as long as init load-on-startup=1 is set.

This code can actually be thought of as a global code. Global code is best not written in a serlvet. Because if you write in a serlvet, it is easy to assume that the code logic is closely related to the current servlet.

It should be written in the listener.

You can think that at the beginning, there were only servlet s and only those global codes could be written in the sevlet init, and listeners appeared in later versions, so it is recommended that these codes be written logically in the listener.


Principle (no uniform requirements)

How does listener work?

This piece of code that the ServletCotontext object was created should have been written long ago. The listener we wrote was written later. How can we make the old code more than a decade ago call the code you wrote?

Baby crying, teasing

What does Dad do?

What does mother do

package com.cskaoyan.listener.test;

public class Baby {
    private Dad dad;

    private Mom mom;

    public Baby(Dad dad, Mom mom) {
        this.dad = dad;
        this.mom = mom;
    }

    public void cry(){
        dad.boil();
        mom.feed();
    }
}
package com.cskaoyan.listener.test;

public class Dad {

    public void boil(){
        System.out.println("Dad's Hot Milk");
    }
}
package com.cskaoyan.listener.test;

public class Mom {

    public void feed(){
        System.out.println("Mom feeding");
    }
}
package com.cskaoyan.listener.test;

public class MainTest {

    public static void main(String[] args) {
        Baby baby = new Baby(new Dad(),new Mom());
        baby.cry();
    }
}

But Mom and Dad are both only children and have to work. No one cares for their children on weekdays. Grandpa and Grandma will look after them.

But what if the references maintained in Baby are Mom and Dad?

You also need to bring Grandpa and Grandma back at the weekend

Grandpa and Dad are out to work, Grandma and Mom are at home

package com.cskaoyan.listener.test.update;

public interface Family {

    void action();
}
package com.cskaoyan.listener.test.update;

public class Dad implements Family {
    @Override
    public void action() {
        System.out.println("Dad's Hot Milk");
    }
}
package com.cskaoyan.listener.test.update;

public class Mom implements Family {
    @Override
    public void action() {
        System.out.println("Mom feeding");
    }
}
package com.cskaoyan.listener.test.update;

public class Grandpa implements Family {
    @Override
    public void action() {
        System.out.println("Grandpa coaxed the baby");
    }
}
package com.cskaoyan.listener.test.update;

public class Grandma implements Family {
    @Override
    public void action() {
        System.out.println("Grandmother holds baby");
    }
}
package com.cskaoyan.listener.test.update;

import java.util.ArrayList;
import java.util.List;

public class Baby {

    private List<Family> members = new ArrayList<>();

    public void add(Family family){
        this.members.add(family);
    }

    public void cry(){
        for (Family member : members) {
            member.action();
        }
    }
}
package com.cskaoyan.listener.test.update;

public class MainTest {

    public static void main(String[] args) {
        Baby baby = new Baby();
//        baby.add(new Dad());
//        baby.add(new Mom());
        baby.add(new Grandma());
        baby.add(new Grandpa());
        baby.cry();
    }
}

The ServletContextListener interface is Family

MyServletContextListener

Is an implementation class

Baby is actually the ServletContext currently used in tomcat

ServletContext{
	List<ServletContextListener> listeners;
	
	add()----{listeners.add(listener)}
	
	
	init(){
		listeners.for{listener.contextInitialized()}
	}
	
	destroy(){
		listners.for{listener.contextDestroyed()}
	}


}

Packaging Design Mode

Listener Design Mode

Agent Design Mode

Essentially, they are polymorphic


Filter

concept

Filters, interceptors.

Send me a message while playing a game***

For example, ancient cities, city gates, access to and out of the city need to pass through the city gates. The city gates are like filter s

The filter is in front of the servlet and passes through the filter before the request reaches the servlet

Pass through the filter again before the response is returned to the client

Filter associated servlet


Development and Use

1. Write a class to implement the Filter interface and implement the method

2. Declare the Filter

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/filter1")
public class FirstFilter implements Filter {

    /**
     * Load directly as the application starts
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
    }

    /**
     * service method similar to servlet, filter is accessed once
     * The method is then executed once
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter");
    }

    /**
     * Application is uninstalled, server is shut down
     */
    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

With the introduction of the filter, we know that the request will pass through the filter before it reaches the servlet, and we created a servlet to access it

However, it was found that the request did not pass through a filter.

The fitler is not associated with a servlet at this time.

How does a filter relate to a servlet?

The simplest way is through a url-pattern, and the simplest way is to give the url-pattern of the servlet to the filter.


Notes for Filter

1. The filter can set the same url-pattern as the servlet, which is fully allowed.

By default, the filter performs an intercept operation, and if you want the filter to be able to release the request, you need to set a line of code

package com.cskaoyan.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/servlet1")
public class FirstFilter implements Filter {

    /**
     * Load directly as the application starts
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
    }

    /**
     * service method similar to servlet, filter is accessed once
     * The method is then executed once
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter");
        //This line of code is important for further release of the request, and if it is not, the filter performs an intercept operation
        //If this line of code exists, then the filter is performing the release operation
        //For example, access your home page without logging in
        //The logic of this line of code is more complex: it actually calls the next component recursively
        // Pipeline design mode, responsibility chain design mode (no requirement)
        filterChain.doFilter(servletRequest, servletResponse);
    }

    /**
     * Application is uninstalled, server is shut down
     */
    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

2. Can the same url-pattern be set between the filter and the filter?

Completely possible.

*3. Can filters be set/

Completely possible.

In fact, it is necessary to set /* for a filter. Assuming that the code formatting the filter is written in the filter, if the filter is set /*, it only needs to write one code, and no servlet s need to be reset later.

4. Since filter s can set the same url-pattern and also participate in the processing of specific requests, what is the order of execution?

For example, a filter has /* a filter has / servlet1

So when I access / servlet1, both filter s are involved in the execution of the request, so what is the order of execution?

If multiple filter s join a request, the order of execution follows

1. If it is web.xml, follow the sequence of filter-mapping declarations

<filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern>/servlet1</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2. If it is a comment, follow the ASCII order of the first letter of the class name

Note: There is no relationship between coverage and url-pattern priority.

What is the practical use?

For example, there is a back-end management system (where administrators maintain data) and a front-end system (the system jd.com used by users).

Set up two filter s, one for the background management system and the other for the foreground user system

In addition, you can set a filter with a global encoding format

CharacterEncodingFilter /*

AdminFilter /admin/*

MallFilter /mall/*

CharacterEncodingFilter ,AdminFilter

Assuming that AdminFilter needs a logic to read request parameters, if AdminFilter is first and CharacterEncoding Filter is later, does the code logic in CharacterEncoding Filter have any effect?

CharacterEncodingFilter, MallFilter


Request processing after introducing Filter

To access http://localhost/app/servlet1 For example, explain the execution process of the request

1. Enter the corresponding address, domain name resolution, establish a TCP connection, send an HTTP request message, and send it to the target machine

2. Received by the Connector program listening on port 80, it resolves to a reqeust object and provides a response object

3. Give it to engine, host, and host to select an application called / app. If it finds one, hand the two objects over to the application for processing.

4. The valid path the application gets is / servlet1. First look for a suitable filter to handle the request (/ /servlet1) in the current application. When two filters are found to handle the request at the same time, they will be added to a list in the order of filters. After the filter finishes searching, it will look for a suitable servlet (/servlet1)The request can be processed, and the servlet that can handle the request can be added to the back of the list of chains (only one servlet will be found, only one will be found with the highest priority, and if no servlet is found, it will be given to the default Servlet, which must eventually have a servlet)*

5. Call each component on the list in turn, and execute the doFilter method of the filter and the service method of the servlet in turn. The method requires a request, response object, which happens to be two objects, passing these two objects as parameters to the corresponding method to execute

6. When all the methods of these components are executed and the entire request processing is completed, the Connector reads the data in the response to generate a response message.

In fact, the whole request processing process is the process in which different components operate request and response in turn.

case

Topics: Java JavaEE