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.