We have discussed the init () method in servlet & JSP (2), and mentioned that the init () method contains a parameter of the type servletconfig, the servlet container uses this parameter to pass configuration information to the servlet. Servlet uses the servletconfig object to obtain the initialization parameters provided in name-value pairs from the Web application configuration information. In addition, you can use the servletconfig object to obtain the servletcontext object describing the servlet runtime environment. With this object, the servlet can communicate with its servlet container. Now let's take a closer look at why the servletconfig parameter is used and how to use it.
For example, I want my email address to be displayed on a web page generated by Servlet, but my email may be changed, but I don't want to recompile my servlet code because of this, how can I change it? I want to configure my email address in the deployment description file (dd) instead of hardcoding it into the servlet class. That is, I do not want to do this:
PrintWriter out = response.getWriter();out.println("shan@email.com");
Hard-coded email addresses are not good, because if I want to change the email address, I need to re-compile the servlet class. This is very troublesome, so we can. XML) to make the following deployment:
<servlet><servlet-name>TestServlet</servlet-name><servlet-value>com.shan.web.TestServlet</servlet-value><init-param><param-name>email</param-name><param-value>shan@email.com</param-value></init-param></servlet>
Add the following statement to the servlet code:
out.println(getServletConfig().getInitParameter("email"));
The getservletconfig () method returns a servletconfig. The getinitparameter ("email") method returns the parameter value "email. When the container is initially a servlet, a unique servletconfig will be created for the servlet. The container reads servlet initialization parameters from DD, passes these parameters to servletconfig, and then passes servletconfig to the Init () method of servlet. Note: The getservletconfig () method cannot be called from the servlet constructor, because it is not a complete servlet until the container calls the init () method.
So what happens when the container initializes servlet parameters?
1) when the container creates a servlet, it reads the DD, including the servlet initialization parameter <init-param>.
2) The container creates a new servletconfig for this servlet.
3) create a string name/value pair for each servlet initialization parameter.
4) The container provides servletconfig with reference to the initialization parameters of name/value pairs.
5) The container creates a new instance of the servlet class.
6) The container calls the servlet Init () method and passes in the reference of servletconfig.
From this process, we can see that when the container creates a servlet, it reads DD and creates a name/value pair for servletconfig. Then, the container will no longer read the initialization parameters. Therefore, it is too clumsy to change the email address in the servlet lifecycle. But it is better than hard encoding. To change the email address, redeploy the application.
Can JSP get servlet initialization parameters?
Servletconfig is used for servlet configuration instead of jspconfig. Therefore, if you want other parts of the application to use the servlet initialization parameter information you configured in the DD, you need to use the servlet & JSP tasks (4) the request forwarding mechanism is described in. You only need to set an attribute in the request to receive the message from the JSP that forwarded the request.
String email = getServletConfig().getInitParameter("email");request.setAttribute("email",email);RequestDispatcher rd=request.getRequestDispatcher("/test.jsp");rd.fordward(request,response);
However, we may need to use this address throughout the application. One way is to let the servlet read the initialization parameters and save them so that other parts of the application can be used. However, in this way, we must know which servlet to run during application deployment, and if you change the application, everything will be screwed up. Therefore, this is not acceptable.
In view of this, we use context initialization parameters. It is similar to the servlet initialization parameter, except that the context initialization parameter is available for the entire web application rather than a servlet. Therefore, both Servlet and JSP can access context initialization parameters. We need to make the following changes in Web. xml:
<servlet><servlet-name>TestServlet</servlet-name><servlet-value>com.shan.web.TestServlet</servlet-value></servlet><context-param><param-name>email</param-name><param-value>shan@email.com</param-value></context-param>
Note: <context-param> is applicable to the entire web application, so it is not nested in <servlet>.
Add the following statement to the servlet code:
out.println(getServletContext().getInitParameter("email"));
Or
ServletContext context = getServletContext();out.println(context.getInitParameter("email"));
Note the differences between servlet initialization parameters and context initialization parameters. The entire web application has only one servletcontext, and all parts of the web application can access it. However, each servlet in the application has its own servletconfig. When deploying a web application, the container will create a servletcontext (Note: If your application is distributed across multiple servers, the Web application can actually have multiple servletcontext, A servletcontext does correspond to only one application, provided that the application is in one JVM .), This context is available for each Servlet and JSP in the Web application.
Speaking of this, what if we want the app initialization parameter to be a database datasource?
The context initialization parameter can only be string. After all, we cannot insert an object into the XML deployment description file. If the entire web application has a main method, you can add some code that runs before servlet or JSP. Although the servlet does not have the main method, there is a listener (listener ). What we want is to listen to an initialization event, so that we can get the context initialization parameters and run some code before the application serves the customer. However, which part of the application can be used as the listener? We don't want a servlet to do this kind of work. After all, its task is not this.
What we need is actually a servletcontextlistener. It can listen to two key events in the life of servletcontext: initialization (creation) and revocation. It can:
You are notified when the context is initialized (when the application is deployed.
- Obtain the context initialization parameters from servletcontext.
- Create a database connection using the initialization parameter lookup name
- The database connection is used as a property so that all parts of the web application can be accessed.
You will be notified when the context is revoked (the application is deploy or terminated.
- Close the database connection.
Instance, a simple servletcontextlistener
Because we do not want to create a database, we do not use the database connection example. Our instance will convert the string initialization parameter to an object-dog. The listener's task is to obtain the context initialization parameters (Tibetan mastiff, matsushi, Samo, Chinese Rural dog, etc.) for the dog breed, and then use this string to construct a dog object, the listener then saves the dog object to a servletcontex attribute for the servlet to get it. The key to the problem is that servlet can access a shared application object (DOG) without reading context parameters. Therefore, it does not matter whether the shared application object is a database link.
Create a listener class:
package com.shan.listen;import com.shan.model.Dog;import javax.servlet.*;public class MyServletContextListener implements ServletContextListener {public void contextInitialized(ServletContextEvent event) {ServletContext context = event.getServletContext();String dogBreed = context.getInitParameter("breed");Dog dog = new Dog(dogBreed);context.setAttribute("dog",dog);}public void contextDestroyed(ServletContextEvent event) {}}
Among them, the dog class code is as follows:
package com.shan.model;public class Dog {private String breed = null;public Dog(String breed) {this.breed = breed;}public String getBreed(){return breed;}}
Compile the servlet class with the following code:
Package COM. shan. web; import COM. shan. model. dog; import Java. io. *; import javax. servlet. *; import javax. servlet. HTTP. *; public class testlistenerservlet extends httpservlet {public void doget (httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {response. setcontenttype ("text/html; charset = gb2312"); printwriter out = response. getwriter (); out. println ("A listener sets the context attribute test:"); out. println ("<br/>"); dog = (DOG) getservletcontext (). getattribute ("dog"); out. println ("dog breed:" + dog. getbreed (); out. close ();} public void dopost (httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {doget (request, response );}}
Note: The forced conversion type (DOG) cannot be forgotten ).
Finally, write the deployment description file web. xml.
<? XML version = '1. 0' encoding = 'utf-8'?> <Web-app xmlns = "http://java.sun.com/xml/ns/javaee" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: schemalocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version = "3.0" metadata-complete = "true"> <servlet-Name> testlistenerservlet </servlet-Name> <servlet-class> com. shan. web. testlistenerservlet </servlet-class> </servlet> <servlet-mapping> <servlet-Name> testlistenerservlet </servlet-Name> <URL-pattern>/listentest. DO </url-pattern> </servlet-mapping> <context-param> <param-Name> breed </param-Name> <param-value> Tibetan mastiff </param- value> </context-param> <listener-class> COM. shan. listen. myservletcontextlistener </listener-class> </listener> </Web-app>
Does the XML Element seem to indicate the type of the event to be listened? In fact, the container will check the class and pay attention to the listener interface (or multiple interfaces, One listener can implement multiple listener interfaces) to identify the types of events to listen.
The process for establishing a web application is the same as described earlier. The only change is that a new Java package COM. shan. listen is used to store the listener class. The last deployment is the same as the previous one.
However, we also need to execute the following statement to compile the above class (first switch to the project directory ):
javac -d classes src\com\shan\model\Dog.java
javac -classpath D:\apache-tomcat-7.0.33\lib\servlet-api.jar;classes -d classes src\com\shan\listen\MyServletContextListener.java
javac -classpath D:\apache-tomcat-7.0.33\lib\servlet-api.jar;classes -d .\classes src\com\shan\web\TestListenerServlet.java
Start tomcat to deploy the application. The test results are as follows:
Figure 1 instance running result
Let's discuss the entire scenario. It can be divided into the following steps:
1) The container reads the deployment description file of the application, including the <listen> and <context-param> elements.
2) The container creates a new servletcontext for the application, and all parts of the application share the context.
3) The container creates a string name/value pair for each context initialization parameter. It is assumed that there is only one parameter.
4) The container submits the reference of the name/value parameter to servletcontext.
5) The container creates a new instance of the myservletcontextlistener class.
6) The container calls the contextinitialized () method of the listener and passes in a new servletcontextevent. This event object has a servletcontext reference, so the event processing code can get context initialization parameters from the event context.
7) the listener sends a reference to the servletcontextevent to the servletcontext.
8) the listener sends the context initialization parameter "breed" to servletcontext ".
9) the listener uses initialization parameters to construct a new dog object.
10) the listener sets dog as an attribute in servletcontext.
11) create a new servlet for the container (that is, use the initialization parameter to create a new servletconfig, provide a reference to the servletconfig, and then call the servlet Init () method ).
12) the servlet gets a request and requests the attribute "dog" from the servletcontext ".
13) the servlet calls getbreed () on the dog and outputs the result to httpresponse.
In addition to the context listener interface, there are other listener interfaces.
Scenario |
Listener Interface |
Event Type |
You want to know whether an attribute is added, deleted, or replaced in the context of a Web application. |
Javax. servlet. servletcontextattributelistener Attributeadded Attributeremoved Attributereplaced |
Servletcontextattributeevent |
You want to know the number of concurrent users. That is to say, you want to track the active sessions |
Javax. servlet. http. httpsessionlistener Sessioncreated Sessiondestroyed |
Httpsessionevent |
Every time a request arrives, you want to know to create a log. |
Javax. servlet. servletrequestlistener Requestinitialized Requestdestroyed |
Servletrequestevent |
When do you want to add, delete, or replace a request attribute? |
Javax. servlet. servletrequestattributelistener Attributeadded Attributeremoved Attributereplaced |
Servletrequestattributeevent |
You have an attribute class (the objects indicated by this class will be placed in an attribute), and you want this type of object to be bound to a session or be notified when the session is deleted. |
Javax. servlet. http. httpsessionbindinglistener Valuebound Valueunbound |
Httpsessionbindingevent |
When do you want to add, delete, or replace a session attribute? |
Javax. servlet. http. httpsessionattributelistener Attributeadded Attributeremoved Attributereplaced |
Httpsessionbindingevent (Note: The names here are inconsistent !) |
You want to know whether a context is created or revoked |
Javax. servlet. servletcontextlistener Contextinitialized Contextdestroyed |
Servletcontextevent |
You have an attribute class and want to be notified when the session bound to this class object is migrated to another JVM. |
Javax. servlet. http. httpsessionactivationlistener Sessiondidactivate Sessionwillpassivate |
Httpsessionevent (Note: The names here are inconsistent !) |
Reprinted please indicate the source: http://blog.csdn.net/iAm333