作用域对象
Servlet上下文监听器
Servlet会话监听器
Servlet请求监听器
一:对象作用域
作用域对象 |
属性操作方法 |
作用域范围说明 |
ServletContext(上下文) |
void setAttribute(String, Object) Object getAttribute(Sting) void removeAttribute(String) Enumeration getAttributeNames() |
整个Web应用程序 |
HttpSession(会话) |
一个会话交互过程 |
|
ServletRequest(请求) |
一次请求过程 |
1.1ServletContext应用上下文
例子:页面访问量的统计程序
主要的代码块:
1 ServletContext sc=getServletContext(); 2 Integer count=(Integer)sc.getAttribute("counter"); 3 if(count==null){ 4 count=new Integer(1); 5 }else{ 6 count=new Integer(count.intValue()+1); 7 } 8 sc.setAttribute("counter", count); 9 resp.getWriter().print("该页面被访问的次数是:"+count); 10 resp.getWriter().close();
提示:上下文作用域中设置的属性在整个Web应用中被共享,只要服务器不被关闭,Web应用中任何一部分都能访问到该属性。所以线程是不安全的。
1.2 HttpSession 会话作用域
例子:在线多人登录
主要的代码块:
count
1 PrintWriter pw=resp.getWriter(); 2 ServletContext sc=getServletContext(); 3 HttpSession sess=req.getSession(); 4 String name = req.getParameter("username"); 5 List<String> userList=(List) getServletContext().getAttribute("userList"); 6 if(userList==null){ 7 userList=new ArrayList<String>(); 8 } 9 if(name!=null){ 10 name=new String(name.getBytes("iso-8859-1"),"utf-8"); 11 System.out.println("================="+name); 12 userList.add(name); 13 sess.setAttribute("username",name); 14 getServletContext().setAttribute("userList", userList); 15 req.getRequestDispatcher("/count1").forward(req, resp); 16 17 } 18 else{ 19 pw.print("<html>"); 20 pw.print("<head></head>"); 21 pw.print("<body><h1>在线书店登录</h1>"); 22 pw.print("<form action='/day13/count'>"); 23 pw.print("username:<input type='text' name='username'/><br/>"); 24 pw.print("<input type='submit' value='submit'/></form></body>"); 25 pw.print("</html>"); 26 } 27 pw.flush(); 28 pw.close(); 29
count1
1 PrintWriter pw=resp.getWriter(); 2 HttpSession sess=req.getSession(); 3 List<String> userList=(List) getServletContext().getAttribute("userList"); 4 String name=(String) sess.getAttribute("username"); 5 String action=req.getParameter("action"); 6 if(action==null){ 7 pw.print("用户"+name+"欢迎你!【<a href='count1?action=loginout'>注销</a>】<br/>"); 8 Iterator<String> i=userList.iterator(); 9 while(i.hasNext()){ 10 String name1=i.next(); 11 pw.print("<p>当前用户有:"+name1+"</p>"); 12 } 13 14 }else if(action.equals("loginout")){ 15 sess.invalidate(); 16 userList.remove(name); 17 getServletContext().setAttribute("userList", userList); 18 19 } 20
提示:每一个会话只能访问当前会话作用域中设置的属性。但是当我们使用特殊的浏览器窗口打开方式使用相同的Session来访问该设置的属性。也就是说多个线程访问相同的会话属性。所以线程也是不安全的。
1.3 ServletRequest 请求作用域
系统的资源消耗
属性可以保存在请求作用域范围中
二:监听器概述
监听session,request,application这三个对象里存取数据的变化
监听器对象可以在事情发生前、发生后可以做一些必要的处理
Servlet监听器主要目的是给Web应用增加事件处理机制,以便更好地监视和控制Web应用的状态变化
Servlet监听器接口和相对应的监听器事件类
事件类型 |
描述 |
Listener接口 |
|
ServletContext 事件 |
生命周期 |
Servlet上下文刚被创建并可以开始为第一次请求服务,或者Servlet上下文将要被关闭发生的事件 |
ServletContextListener |
属性改变 |
Servlet上下文内的属性被增加、删除或者替换时发生的事件 |
ServletContextAttributeListener |
|
HttpSession 事件 |
生命周期 |
HttpSession被创建、无效或超时时发生 |
HttpSessionListener HttpSessionActivationListener |
会话迁移 |
HttpSession被激活或钝化时发生 |
||
属性改变 |
在HttpSession中的属性被增加、删除、替换时发生 |
HttpSessionAttributeListener HttpSessionBindingListener |
|
对象绑定 |
对象被绑定到或者移出HttpSession时发生。 |
||
ServletRequest 事件 |
生命周期 |
在Servletr请求开始被Web组件处理时发生 |
ServletRequestListener |
属性改变 |
在ServletRequest对象中的属性被增加、删除、替换时发生 |
ServletRequestAttributeListener |
三:监听Web应用程序范围内的事件
Web应用启动和销毁事件
Web应用程序的属性发生改变的事件(包括增加、删除、修改)。
定义了ServletContextListener和ServletContextAttributeListener两个接口
监听器需要在web.xml定义监听器:
<listener>
<listener-class>com.cy.listener.servletContext</listener-class>
</listener>
1)ServletContextListener接口的方法如下:
例子:由监听器管理共享数据库连接
1 package com.cy.listener; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 import javax.servlet.ServletContextEvent; 8 import javax.servlet.ServletContextListener; 9 10 public class ServletContext implements ServletContextListener { 11 12 @Override 13 public void contextDestroyed(ServletContextEvent arg0) { 14 //应用程序被销毁 15 try { 16 Connection c=(Connection) arg0.getServletContext().getAttribute("connection"); 17 c.close(); 18 } catch (SQLException e) { 19 20 e.printStackTrace(); 21 } 22 23 } 24 25 @Override 26 public void contextInitialized(ServletContextEvent arg0) { 27 //应用程序被加载及初始化 28 try { 29 //连接数据库 30 Class.forName("com.mysql.jdbc.Driver"); 31 Connection con=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/books","root","root"); 32 arg0.getServletContext().setAttribute("connection", con); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 } 36 37 } 38 39 }
2)ServletContextAttributeListener接口方法:
1 package com.cy.listener; 2 3 import javax.servlet.ServletContextAttributeEvent; 4 import javax.servlet.ServletContextAttributeListener; 5 6 public class MyServletContext implements ServletContextAttributeListener { 7 8 @Override 9 public void attributeAdded(ServletContextAttributeEvent event) { 10 System.out.println("添加一个ServletContext属性"+event.getName()+"========="+event.getValue());//回传属性的名称 值 11 } 12 13 @Override 14 public void attributeRemoved(ServletContextAttributeEvent event) { 15 System.out.println("删除一个ServletContext属性"+event.getName()+"========="+event.getValue()); 16 } 17 18 @Override 19 public void attributeReplaced(ServletContextAttributeEvent event) { 20 System.out.println("某个ServletContext属性被改变"+event.getName()+"========="+event.getValue()); 21 } 22 23 }
1 package com.cy.listener; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class Test extends HttpServlet{ 11 12 private static final long serialVersionUID = 1L; 13 14 @Override 15 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 16 throws ServletException, IOException { 17 resp.setContentType("text/html;charset=utf-8"); 18 getServletContext().setAttribute("username", "tiger"); 19 getServletContext().setAttribute("username", "kitty"); 20 getServletContext().removeAttribute("username"); 21 } 22 23 @Override 24 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 25 throws ServletException, IOException { 26 doPost(req, resp); 27 } 28 29 }
结果:
添加一个ServletContext属性username=========tiger
某个ServletContext属性被改变username=========tiger
删除一个ServletContext属性username=========kitty
四:监听会话范围内事件
1)HttpSessionBindingListener接口
注意:HttpSessionBindingListener接口是唯一不需要在web.xml设定的listener;
当我们的类实现了HttpSessionBindingListener接口后,只要这个对象加入Session范围(即调用HttpSession对象的setAttribute方法的时候)或从Session对象移出(即调用HttpSession对象的removeAttribute方法的时候或Session超时时)容器就会通知这个对象,分别会自动调用下列两个方法:
–void valueBound(HttpSessionBindingEvent event):当对象正在绑定到Session中,Servlet容器调用该方法来通知该对象
–void valueUnbound(HttpSessionBindingEvent event):当从Session中删除对象时,Servlet容器调用该方法来通知该对象
HttpSessionBindingEvent类提供如下方法:
public String getName():返回绑定到Session中或从Session中删除的属性名字。
public Object getValue():返回被添加、删除、替换的属性值
public HttpSession getSession():返回HttpSession对象
2)HttpSessionAttributeListener接口
监听HttpSession中的属性的操作
–当在Session中增加一个属性时,激发attributeAdded(HttpSessionBindingEvent event) 方法;
–当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent event)方法;
–当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent event) 方法。
3)HttpSessionListener接口
监听HttpSession对象的创建和销毁操作
-当创建一个Session时,激发session Created(HttpSessionEvent event)方法
–当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent event)方法
例子:可用于在线人数的统计
主要代码:
1 package com.cy; 2 3 public class OnlineCounter { 4 private static int online=0; 5 6 public static int getOnlie(){ 7 return online; 8 } 9 public static void raise(){ 10 online++; 11 } 12 public static void reduce(){ 13 online--; 14 } 15 16 } 17 18 19 package com.cy; 20 21 import javax.servlet.http.HttpSessionEvent; 22 import javax.servlet.http.HttpSessionListener; 23 24 public class OnlineConter implements HttpSessionListener{ 25 26 @Override 27 public void sessionCreated(HttpSessionEvent arg0) { 28 OnlineCounter.raise(); 29 } 30 @Override 31 public void sessionDestroyed(HttpSessionEvent arg0) { 32 OnlineCounter.reduce(); 33 } 34 35 } 36 37 38 package com.cy; 39 40 import java.io.IOException; 41 42 import javax.servlet.ServletException; 43 import javax.servlet.http.HttpServlet; 44 import javax.servlet.http.HttpServletRequest; 45 import javax.servlet.http.HttpServletResponse; 46 import javax.servlet.http.HttpSession; 47 48 public class TestServlet extends HttpServlet { 49 @Override 50 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 51 throws ServletException, IOException { 52 resp.setContentType("text/html;charset=utf-8"); 53 HttpSession sess=req.getSession(); 54 sess.setMaxInactiveInterval(10); 55 resp.getWriter().print("当前在线人数为:"+OnlineCounter.getOnlie()); 56 } 57 58 @Override 59 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 60 throws ServletException, IOException { 61 doPost(req, resp); 62 } 63 64 65 }
五:监听请求生命周期内事件
请求作用域范围内的生命周期事件用于管理整个request生命周期的状态和资源
ServletRequestListener接口
–public void requestDestroyed(ServletRequestEvent event):当请求被销毁时被处理。
–public void requestInitialized(ServletRequestEvent event):当请求被创建时被处理
ServletRequestAttributeListener接口
–public void attributeAdded(ServletRequestAttributeEvent event) :当在请求作用域中添加一个属性的时候调用该方法。
–public void attributeRemoved(ServletRequestAttributeEvent event) :当在请求作用域中删除一个属性时调用
–public void attributeReplaced(ServletRequestAttributeEvent event) :当在请求作用域中替换一个属性值的时候调用
总结:
1 在Servlet中3个对象作用域分别由ServletContext、ServletRequest和HttpSession接口来处理
2 上下文作用域中设置的属性是线程不安全的
3 对于同一个客户的多个请求,Session会跨这些请求持久存储
4 设置在上下文和会话作用域中的对象,会非常消耗系统的资源
5 请求作用域范围仅仅作用在与一个请求相关的两个资源之间
6 应用程序事件监听器是实现一到多个Servlet事件监听器接口的类。它们在Web应用程序部署的时候,被Web容器初始化和注册
7 ServletContext监听器用于管理应用程序JVM级别保存的资源或状态。
8 HTTP会话监听器用于管理从同一客户端或用户发送的一系列请求的资源或状态。
9 Request请求监听器用于管理Request请求生命周期内的状态