第5章:作为Web应用:属性和监听者/5.2 Servlet监听器

  • 监听器接口汇总

  1. 上下文相关
    1. 初始化完成或者销毁监听器:ServletContextListener
    2. 新增、删除或者替换一个属性监听器:ServletContextAttributeListener(属性相关)
  2. 会话有关:
    1. 跟踪并发用户数量、跟踪活动的会话监听器:HttpSessionListener
    2. 对象绑定到会话或者对象从会话删除监听器:HttpSessionBindingListener
    3. 对象所绑定的会话从一个JVM迁移到另外一个JVM时通知:HttpSessionActivationListener
    4. 增加、删除或者替换一个会话属性监听器:HttpSessionAttributeListener(属性相关)
  3. 请求相关:
    1. 请求到来时监听器:ServletRequestListener
    2. 增加、删除或者替换一个请求属性监听器:ServletRequestAttributeListener(属性相关)
  • 上下文监听器(ServletContextListener)--监听器触发时机

  1. ServletContextListener接口:
  2. 作用:在初始化ServletContext对象时触发的一个事件,可用于在这个时刻创建一些全局对象,比如数据库连接对象。由于ServletContext初始化时Servlet还没有形成,也就是不会接受外面的请求,所以该事件常用于在请求到来之前初始化一些对象
  3. 触发时机:
    1. 容器在初始化完成ServletContext对象后
    2. 读取web.xml文件,如果发现监听类实现了ServletContextListener接口(比如:MyServletContextListener类),则分别生成两个对象
      1. 生成监听类对象
        1. 类来源:用户自定义类:比如 MyServletContextListener
        2. 类实现的接口:ServletContextListener
        3. 构造方法:默认无参数构造方法
      2. 生成事件类对象
        1. 类来源:容器自动生成
        2. 类实现的接口:ServletContextEvent
        3. 构造方法:参数为ServletContext对象的构造方法
  4. 触发后效果:用户自定义监听类(比如:MyServletContextListener )就拥有了ServletContext对象,进而可以通过ServletContext对象设置某些属性到上下文中
  • 上下文监听器(ServletContextListener)--实例讲解

  1. 实例操作
  2. 实体对象类
    package model;
    
    public class Dog {
       
       private String string;
       public Dog(String str){
    	   string = str;
       }
       public String getBeer(){
    	   return string;
       }
    }
    
    
  3. 实现ServletContextListener接口的类MyServletContextListener ,生成实体对象并保存到ServletContext属性中
    package listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import model.Dog;
    
    public class MyServletContextListener implements ServletContextListener{
    
    	@Override
    	public void contextInitialized(ServletContextEvent sce){
    		ServletContext servletContext =  sce.getServletContext();
    		Dog dog = new Dog(servletContext.getInitParameter("dog-desc"));
    		//设置servletContext属性,在servlet类中可以获取
    		servletContext.setAttribute("dog",  dog);
    		System.out.println("日志测试:在创建完成servletContext时会触发调用监听类");
    	}
    	@Override
    	public void contextDestroyed(ServletContextEvent sce){
    		
    	}
    }
    
    
  4. 新建listenersc.html,跳转到MyServletListener类的POST方法
    <html>
    <body>
    	<h1 align="center">Beer Selection Page</h1>
    	<form method="POST" action="MyServletListener.do">
    		Select beer characteristics
    		<p>
    			Color: <select name="color" size="1">
    				<option value="light">one</option>
    				<option value="amber">two</option>
    				<option value="write">three</option>
    				<option value="black">four</option>
    			</select> <br>
    			<br>
    		<center>
    			<input  type="SUBMIT">
    		</center>
    	</form>
    </body>
    </html>
  5. MyServletListenerTest类从ServletContext 属性中获取实体对象,并且回显属性到界面
    package web;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import model.Dog;
    
    public class MyServletListenerTest extends HttpServlet {
    
    	/**
    	 * Constructor of the object.
    	 */
    	public MyServletListenerTest() {
    		super();
    	}
    
    	/**
    	 * Destruction of the servlet. <br>
    	 */
    	public void destroy() {
    		super.destroy(); // Just puts "destroy" string in log
    		// Put your code here
    	}
    
    	/**
    	 * The doGet method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to get.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		response.setContentType("text/html");
    		PrintWriter out = response.getWriter();
    		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    		out.println("<HTML>");
    		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    		out.println("  <BODY>");
    		out.print("    This is ");
    		out.print(this.getClass());
    		out.println(", using the GET method");
    		out.println("  </BODY>");
    		out.println("</HTML>");
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * The doPost method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to post.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		response.setContentType("text/html");
    		PrintWriter out = response.getWriter();
    		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    		out.println("<HTML>");
    		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    		out.println("  <BODY>");
    		out.print("    This is ");
    		out.print(this.getClass());
    		out.println(", using the POST method");
    		
    		//从ServletContext中获取Dog的属性并且打印在界面
    		ServletContext servletContext = getServletContext();
    		try {
    			Dog dog = (Dog)servletContext.getAttribute("dog");
    			String str = "";
    			str = dog.getBeer();
    			//打印Dog对象
    			out.println("Dog:" + str);
    		} catch (Exception e) {
    			// TODO: handle exception
    			System.out.println("获取Dog对象失败");
    		}
    		out.println("  </BODY>");
    		out.println("</HTML>");
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * Initialization of the servlet. <br>
    	 *
    	 * @throws ServletException if an error occurs
    	 */
    	public void init() throws ServletException {
    		// Put your code here
    	}
    
    }
    
    
  6. 配置web.xml
    <!-- 上下文设置 -->
    
         <context-param>
    
               <param-name>dog-desc</param-name>
    
               <param-value>my dog test</param-value>
    
         </context-param>
    
         
    
         <!-- 设置监听类 -->
    
         <listener>
    
              <listener-class>listener.MyServletContextListener</listener-class>
    
         </listener>
  7. 测试:
    1. tomcat启动的试试就进行了初始化
    2. 地址:http://localhost:8089/myWeb3/listenersc.html
    3. 结果:
  • 上下文属性监听器(ServletContextAttributeListener)--触发时机:

  1. ServletContextAttributeListener接口: 
  2. 作用:监听ServletContex对象的属性增加、删除、或者替换的触发
  3. 触发时机:当ServletContex对象调用以下几个方法时都会触发:
    1. 新增:public void setAttribute(String, Object)
    2. 删除:public void removeAttribute(String)
    3. 替换:public void setAttribute(String, Object) 对重复的值就是替换
  4. 触发结果:可获取属性的名称,属性的值对应的对象
  • 上下文属性监听器(ServletContextAttributeListener)--实例讲解

  1. 定义类MyServletContextAttributeListener实现ServletContextAttributeListener接口
    package listener;
    
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    
    import model.Dog;
    
    public class MyServletContextAttributeListener implements ServletContextAttributeListener{
    
    	 public void attributeAdded(ServletContextAttributeEvent scab){
    		   System.out.println("attributeAdded:dog被这个方法调用时触发:getServletContext().setAttribute"); 
    		   String name = scab.getName();
    		   if(name.equals("dog")){
    			   Dog dog = (Dog)scab.getValue();
    			   System.out.println("从新增属性事件中获取属性对象:Dog,它的值是:"+ dog.getBeer());
    		   }
    		   
    	   }
    	   
    	   public void attributeRemoved(ServletContextAttributeEvent scab){
    		   System.out.println("attributeRemoved:dog被这个方法调用时触发:getServletContext().RemoveAttribute"); 
    	   }
    	   
    	   public void attributeReplaced(ServletContextAttributeEvent scab){
    		   System.out.println("attributeReplaced:dog被这个方法调用时触发:getServletContext().setAttribute"); 
    	   }
    }
    
    
  2. 从web.xml中定义监听类
    <!-- 设置监听类 -->
    
         <listener>
    
              <listener-class>listener.MyServletContextAttributeListener</listener-class>
    
         </listener>
  3. 测试重复调用ServletContext的setAttribute/removeAttribute方法,看触发情况
    1. 方法调用:
      //设置servletContext属性,在servlet类中可以获取
      
                 servletContext.setAttribute("dog",  dog);
      
                 //这次应该是替换
      
                 servletContext.setAttribute("dog",  dog);
      
              //删除属性
      
                 servletContext.removeAttribute("dog");
      
                 //又新增属性
      
                 servletContext.setAttribute("dog",  dog);
    2. 测试结果:

      attributeAdded:dog被这个方法调用时触发:getServletContext().setAttribute

      从新增属性事件中获取属性对象:Dog,它的值是:my dog test

      attributeReplaced:dog被这个方法调用时触发:getServletContext().setAttribute

      attributeRemoved:dog被这个方法调用时触发:getServletContext().RemoveAttribute

      attributeAdded:dog被这个方法调用时触发:getServletContext().setAttribute

      从新增属性事件中获取属性对象:Dog,它的值是:my dog test

      attributeAdded:dog被这个方法调用时触发:getServletContext().setAttribute

  • 会话跟踪监听器(HttpSessionListener)---触发时机

  1. HttpSessionListener接口:  
  2. 作用:新增会话或者销毁会话的时候触发
  3. 触发时机:
    1. 新增会话:请求参数HttpServletRequest request调用 getSession() 方法时触发新增会话
  4. 触发结果:可进行会话保存等操作
  • 会话跟踪监听器(HttpSessionListener)--实例讲解

  1. 定义类MyHttpSessionListener实现HttpSessionListener接口
    package listener;
    
    import java.util.Enumeration;
    
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class MyHttpSessionListener implements HttpSessionListener {
    
    	@Override
    	public void sessionCreated(HttpSessionEvent se) {
    		// TODO Auto-generated method stub
    		
            HttpSession httpSession = se.getSession();
            
            System.out.println("新创建session:" + httpSession.getId());
            Enumeration<String> enumeration= httpSession.getAttributeNames();
            while(enumeration.hasMoreElements()){
            	System.out.println(enumeration.nextElement());
            }
    	}
    
    	@Override
    	public void sessionDestroyed(HttpSessionEvent se) {
    		// TODO Auto-generated method stub
    
    	}
    
    }
    
    
  2. 从web.xml中定义监听类
    <!-- 设置会话创建/销毁监听类 -->
    
         <listener>
    
              <listener-class>listener.MyHttpSessionListener</listener-class>
    
         </listener>
  3. 测试在任何的servlet类中调用request.getSession()方法,只看到创建一个会话
    1. 从BeerSelect类中创建
      1. BeerSelect类的doPost方法获取session
        System.out.println("======进来本界面即<<BeerSelect.java>>创建会话======");
                   request.getSession();
        
      2. 测试结果:

        ======进来本界面即<<BeerSelect.java>>创建会话======

        新创建session:3B82DAB9952B1100C22588E747B8ADEF

        ======进来本界面<<<MyServletListenerTest.java>>>即创建会话======

    2. 从MyServletListenerTest类中创建
      1. MyServletListenerTest类的doPost方法获取session
        System.out.println("======进来本界面<<<MyServletListenerTest.java>>>即创建会话======");
        
                   request.getSession();
      2. 测试结果:

        ======进来本界面<<<MyServletListenerTest.java>>>即创建会话======

        新创建session:3DF0918D468CD76A25DFA94440CD2265

        ======进来本界面即<<BeerSelect.java>>创建会话======

  • 对象绑定到会话监听器(HttpSessionBindingListener)--触发时机

  1. HttpSessionBindingListener接口: 
  2. 作用:某个对象作为参数传入session.setAttribute或者session.RemoveAttribute方法移除该对象时触发该对象进行相关操作,
  3. 触发时机:
    1. 新增会话:某个对象作为参数传入session.setAttribute
    2. 删除会话:session.RemoveAttribute方法移除该对象时触发
  4. 触发结果:比如把该对象保存起来
  • 对象绑定到会话监听器(HttpSessionBindingListener)--实例讲解

  1. 自定义类MyHttpSessionBindingListener实现HttpSessionBindingListener接口
    package listener;
    
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.HttpSessionBindingListener;
    
    public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
    
    	private String strString ;
    	
    	public MyHttpSessionBindingListener(String str){
    		strString = str;
    	}
    	
    	@Override
    	public void valueBound(HttpSessionBindingEvent event) {
    		// TODO Auto-generated method stub
            System.out.println("MyHttpSessionBindingListener类被绑定:它的传入参数为:"+
            		strString + "它的属性名称为:"+ event.getName());
    	}
    
    	@Override
    	public void valueUnbound(HttpSessionBindingEvent event) {
    		// TODO Auto-generated method stub
    		 System.out.println("MyHttpSessionBindingListener类被取消绑定:它的传入参数为:"+
    	        		strString + "它的属性名称为:"+ event.getName());
    	}
    
    }
    
    
  2. 通过session.setAttribute方法设置自定义对象
    HttpSession session = request.getSession();
    
               System.out.println("<<BeerSelect.java>>设置属性:");
    
               String name = "HttpSessionBindingListener——NAME";
    
               session.setAttribute(name, new MyHttpSessionBindingListener(" OKOKOK "));
  3. 通过session.RemoveAttribute方法取消自定义对象
    System.out.println("<<BeerSelect.java>>取消属性:");
    
               session.removeAttribute(name);
  4. 测试:
    1. 设置时触发绑定事件

      <<BeerSelect.java>>设置属性:

      MyHttpSessionBindingListener类被绑定:它的传入参数为: OKOKOK 它的属性名称为:HttpSessionBindingListener——NAME

    2. 取消时触发取绑定事件

      <<BeerSelect.java>>取消属性:

      MyHttpSessionBindingListener类被取消绑定:它的传入参数为: OKOKOK 它的属性名称为:HttpSessionBindingListener——NAME

  5. 注意:如果被对象被重置,也就是属性名称不变,但是对象变了,这时候HttpSessionBindingListener会受到两个事件,一个是绑定事件,另外一个是原对象的取消事件

》》》》》未完:易学笔记--Servlet和JSP--入门就看这一篇就够了》》》》》

猜你喜欢

转载自blog.csdn.net/u011830122/article/details/83714603