配置文件中的相关元素和监听器

下面这个Servlet编译、布署,它的response会输出一个html页面,页面上会显示一个Email地址:

package com.example.web;//确保与前面创建的开发结构和部署结构匹配

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.xmlservlet元素就行。
  • 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>Chapter5</servlet-name>
    <servlet-class>com.example.web.EmailShowServlet</servlet-class>

    <init-param>
      <param-name>adminEmail</param-name>
      <param-value>lyuComputer@163.com</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Chapter5</servlet-name>
    <url-pattern>/emailPage</url-pattern>
  </servlet-mapping>
</web-app>
  • Servlet的代码要改一改,不用最初的硬编码,采用读取配置参数的方式。

以下,是对上面代码的解释:

  • 容器初始化一个servlet时,会为这个servlet建一个唯一的ServletConfig对象
  • 容器从web.xml读出servlet初始化参数,并把这些参数交给ServletConfig,然后把ServletConfig传递给servlet的init()方法。
  • servlet初始化参数只能读一次,就是在容器初始化servlet的时候。

上面的解决方法前进了一步,但是还有问题:

  • 如果想让Web应用的所有部分(注意:我们的日常真正Web应用并不只有一个Servlet)都能访问这个email地址,利用初始化参数,必须在配置文件中为每个servlet都要配置初始化参数。这样太麻烦了,而且可维护性很差。
  • 我们需要一个更全局的东西。

解决之道:上下文初始化参数

  • 上下文参数与servlet初始化参数很类似,只不过上下文参数对整个Web应用可见,而不只针对一个servlet。
  • Web应用的所有servlet和JSP都自动能够访问上下文参数,我们不必操心为每个servlet配置,如果值有变化,只需在一个地方修改就行了。
  • web.xml的关键代码,去掉上面的init-param元素,加上context-param元素。

<servlet>
    <servlet-name>Chapter5</servlet-name>
    <servlet-class>com.example.web.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。
  • 每个Web应用有一个ServletContext,而且Web应用中的所有部分都能访问它。所以,它是全局的。

上面的配置参数,只能是String类型。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()方法。

建立和使用一个上下文监听者

  • 要监听ServletContext事件,需要编写一个实现ServletContextListener的监听者类,把它放在WEB-INF/classes目录中,并在部署描述文件放一个元素来告诉容器。

  • 监听者对象 类模版如下形式:


package com.example.web;
import javax.servlet.*;
public class MyServletContextListener implements ServletContextListener{
    public void contextInitialized(ServletContextEvent event){
        //Code
	ServletContext sc = event.getServletContext();
        String dogBreed = sc.getInitParameter("breed");
        Dog d = new Dog(dogBreed);
        sc.setAttribute("dog", d);
    }
    public void contextDestroyed(ServletContextEvent event){
        //Code
    }
}
  • web.xml加入listener元素
 <listener>
    <listener-class>
      com.example.MyServletContextListener
    </listener-class>
  </listener>

针对于上面的解决方案,开始正式创建

  • 需要3个类和一个web.xml。
  • 为了便于编译和测试,我们把所有类都放在同一个包中:com.example
  • ServletContextListener.java
    • 这个类实现了ServletContextListener,它得到上下文初始化参数,创建Dog,并把Dog设置为上下文属性。
  • Dog.java

    • Dog类只是一个普通的Java类,它的任务是作为一个属性值,由ServletContextListener实例化,并设置在ServletContext中,以便servlet获取。
  • ListenerTester.java

    • 这个类是一个Servlet,它的任务是验证监听者的工作。为此,这个Servlet会从上下文得到Dog属性,然后调用Dog的getBreed(),并把结果打印到响应(以便我们在浏览器上看到)。
package com.example.web;

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
    }
}

package com.example.web;

public class Dog{
    private String breed;

    public Dog(String breed){
        this.breed = breed;
    }

    public String getBreed(){
        return breed;
    }
}
package com.example.web;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class ListenerTester 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>com.example.ListenerTester</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>
      com.example.MyServletContextListener
    </listener-class>
  </listener>
</web-app>
  • 上面的代码都写完了,我们要对Servlet进行编译,部署到tomcat中去。
  • 然后浏览器访问,看看可不可以。






©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页