此内容均为老师课上的课件内容。(写下来是为了方便以后自己查看)
在web.xml中配置ServletConfig
引入:下面这个servlet编译、布署,它的response会输出一个html页面,页面上会显示一个Email地址:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class EmailShowServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("lyuComputer@163.com");
}
}
- 上面代码属于硬编码,它把以后可能会变动的数据写到程序代码中,这种方式不好。
- 如果将来Email地址将来发生改变,就要修改上面的servlet中的代码,然后将该servlet重新编译,重新布署。
- 如果此Email地址是公共服务邮箱,该网站有100个servlet都要显示这个地址,那么就需要修改100个servlet,重新编译100个servlet....
解决之道:把Eamil地址写到servlet初始化参数中。
- servlet有初始化参数,可以利用。
- 给定一个参数名和参数值,只要把它配置在web.xml的servlet元素就行。
- web.xml代码:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>week7</servlet-name>
<servlet-class>EmailShowServlet</servlet-class>
<init-param>
<param-name>adminEmail</param-name>
<param-value>lyuComputer@163.com</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>week7</servlet-name>
<url-pattern>/emailPage</url-pattern>
</servlet-mapping>
</web-app>
- servlet的代码要改一改,不用最初的硬编码,采用读取配置参数的方式。
public class EmailShowServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
ServletConfig sc = getServletConfig();//获得ServletConfig对象
out.println(sc.getInitParameter("adminEmail"));//注意此行的adminEmail是web.xml中的什么?
}
}
对上面代码的解释
- 容器初始化一个servlet时,会为这个servlet建一个唯一的ServletConfig对象。通过此对象可以获取web.xml中配置的初始化参数。
- 容器从web.xml读出servlet初始化参数,并把这些参数交给ServletConfig,然后把ServletConfig传递给servlet的init()方法。
- servlet初始化参数只能读一次,就是在容器初始化servlet的时候。
在web.xml中配置ServletContext
引入:上面的解决方法前进了一步,但是还有问题:
- 如果想让Web应用的所有部分(注意:日常真正Web应用并不仅有一个servlet)都能访问这个email地址,利用上面的初始化参数,必须在配置文件中为每个servlet都要配置初始化参数。这样太麻烦了,而且可维护性很差。
- 我们需要一个更全局的东西。
解决之道:上下文初始化参数
- 当Tomcat启动的时候,就会创建一个ServletContext对象。它代表着当前web站点。所有servlet都共享着一个ServletContext对象,所以Servlet之间可以通过ServletContext实现通讯。
- 所以:Web应用的所有servlet和JSP都自动能够访问上下文参数,我们不必操心为每个servlet配置,如果值有变化,只需在一个地方修改就行了。
- 在web.xml,加上context-param元素。
<servlet>
<servlet-name>week7</servlet-name>
<servlet-class>EmailShowServlet</servlet-class>
</servlet>
<context-param>
<param-name>adminEmail</param-name>
<param-value>1125234@qq.com</param-value>
</context-param>
- 在servlet代码中:
response.setContentType("text/html");
PrintWriter out = response.getWriter();
ServletContext sc = getServletContext();
out.println(sc.getInitParameter("adminEmail"));
上面两种方案的小总结:
- 每个servlet有一个ServletConfig。只对本servlet可见。
- 每个Web应用有一个ServletContext,而且Web应用中的所有部分都能访问它。所以,它是全局的。
ServletContextListener能帮我们做更多的事情
- 刚才的实验,上下文参数只能是String类型的数据,有很大的局限性。你不能把一个Dog对象硬塞到web.xml中。
- 思路:建立一个单独的类,它想监听上下文初始化事件,这样能得到上下文初始化参数,并在应用为客户提供服务之前运行一些代码。它能监听ServletContext一生中的两个关键事件,初始化(创建)和撤销。这个类要实现javax.servlet.ServletContextListener。
一个简单的ServletContextListener实现
- 我们要把String初始化参数转换为一个真正的对象(一个Dog),监听者的任务是得到有关狗品种(Beagle、Poodle等)的上下文初始化参数,然后使用这个String来构造一个Dog对象。监听者再把这个Dog对象存放到一个ServletContext属性中,以便servlet获取。
- 关键是,servlet现在能访问一个共享的应用对象(这是一个共享的Dog),而且不必读取上下文参数。
- 重点是使用初始化参数来创建一个对象,让应用的所有部分都能共享这个对象。
建立和使用一个上下文监听者
- 容器怎样发现和使用监听者?
- 就像告诉容器Web应用其他部分的有关情况一样,要用同样的办法配置监听者。就是通过web.xml。
- 过程:
- 监听者对象向ServletContextEvent对象请求应用ServletContext对象的一个引用。
- 监听者使用这个ServletContext引用得到"breed"的上下文初始化参数,这是一个String,表示狗的品种。
- 监听者使用这个狗品种String构造一个Dog对象。
- 监听者使用ServletContext引用在ServletContext中设置Dog属性。
- 这个Web应用的测试servlet从ServletContext得到Dog对象,并调用这个Dog的getBreed()方法。(我们只是实验,想证明可以得到dog,并调用它的办法)。
建立和使用一个上下文监听者
- 要监听ServletContext事件,需要编写一个实现ServletContextListener的监听者类,把它放在WEB-INF/classes目录中,并在部署描述文件放一个元素来告诉容器。
- 监听者对象 类模版如下形式:
import javax.servlet.*;
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent event){
//Code
}
public void contextDestroyed(ServletContextEvent event){
//Code
}
}
- web.xml加入listener元素
<listener>
<listener-class>
com.example.MyServletContextListener
</listener-class>
</listener>
针对于上面的解决方案,开始正式创建
- 需要3个类和一个web.xml。
- ServletContextListener.java
- 这个类实现了ServletContextListener,它得到上下文初始化参数,创建Dog,并把Dog设置为上下文属性。
-
Dog.java
- Dog类只是一个普通的Java类,它的任务是作为一个属性值,由ServletContextListener实例化,并设置在ServletContext中,以便servlet获取。
-
ListenerTesterServlet.java
- 这个类是一个Servlet,它的任务是验证监听者的工作。为此,这个Servlet会从上下文得到Dog属性,然后调用Dog的getBreed(),并把结果打印到响应(以便我们在浏览器上看到)。
import javax.servlet.*;
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent event){
ServletContext sc = event.getServletContext();//由事件得到ServletContext
String dogBreed = sc.getInitParameter("breed");//使用上下文得到初始化参数
Dog d = new Dog(dogBreed);//建立一个新的Dog
sc.setAttribute("dog",d);//使用上下文来设置一个属性,这个属性就是Dog。现在应用的其他部分就能得到这个属性(Dog) 的值
}
public void contextDestroyed(ServletContextEvent event){
//Code
}
}
public class Dog{
private String breed;
public Dog(String breed){
this.breed = breed;
}
public String getBreed(){
return breed;
}
}
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class ListenerTesterServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("test context attribute set by listener<br>");
out.println("<br>");
Dog dog = (Dog)getServletContext().getAttribute("dog");
out.println("Dog's breed is: " + dog.getBreed());
}
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>ListenerTester</servlet-name>
<servlet-class>ListenerTesterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListenerTester</servlet-name>
<url-pattern>/ListenerTest.do</url-pattern>
</servlet-mapping>
<context-param>
<param-name>breed</param-name>
<param-value>Great Dane</param-value>
</context-param>
<listener>
<listener-class>
MyServletContextListener
</listener-class>
</listener>
</web-app>
- 上面的代码都写完了,我们要对servlet进行编译,部署到tomcat中去。
- 然后浏览器访问,看看可不可以。