目录
一、Listener介绍
监听器介绍
什么是监听器
监听机制相关概念
web监听器介绍
二、监听域对象的生命周期
实现步骤
1.创建监听器,实现监听器接口
2.添加监听器类信息
3.启动项目,查看servletContext对象创建信息
4.关闭项目,查看ServletContext对象销毁信息
5.创建测试页面
6.设置监听超时信息
7.重启项目,查看结果
三、 监听域对象的属性变更
实现步骤
1.创建测试页面
2.创建监听器
3.添加监听信息
四、JDBC
1.什么是JDBC
2.JDBC编程步骤
1.装载相应数据库的JDBC驱动并进行初始化
2.建立JDBC和数据库之间的Connection连接
3.创建Statement或者PreparedStatement接口,执行SQL语句
4.使用Statement 执行SQL语句
5.操作ResultSet结果集
6.关闭连接,释放资源
具体步骤
1.搭建数据库环境
2.创建项目环境,导入数据库驱动
3.编写JDBC程序
Javaweb中的监听器是用于监听web常见对象HttpServletRequest,HttpSession,ServletContext
监听器的作用
1.监听web对象创建与销毁.
2.监听web对象的属性变化
3.监听session绑定javaBean操作.
1.事件----一件事情
2.事件源—产生这件事情的源头
3.注册监听—将监听器与事件绑定,当事件产生时,监听器可以知道,并进行处理。
4.监听器—对某件事情进行处理监听的一个对象
1.javaweb监听器介绍
1.监听web对象创建与销毁的监听器
1.ServletContextListener
2.HttpSessionListener
3.ServletRequestListener
2.监听web对象属性变化
1.ServletContextAttributeListener
2.HttpSessionAttributeListener
3.ServletRequestAttributeListener
3.监听session绑定javaBean
1.HttpSessionBindingListener
2.HttpSessionActivationListener
2.javaweb监听器创建步骤
1.创建一个类,实现指定的监听器接口
2.重写接口中的方法.
3.在web.xml文件中配置监听
3.演示监听对象创建与销毁
1.ServletContext对象的创建与销毁监听
ServletContext对象的创建与销毁分析:ServletContext对象是服务器开启时创建。服务器关闭时销毁。
2.HttpSession对象的创建与销毁监听
1.HttpSession对象的创建与销毁分析:
1.session对象创建:取决于请求中是否有jsessinid,如果有,可能会获取一个已经存在的session对象。如果没有,会创建一个新的session对象.
2.销毁session:
1.默认超时 30分钟
2.关闭服务器
3.invalidate()方法
4.setMaxInactiveInterval(int interval) 可以设置超时时间
4.HttpServletRequest对象的创建与销毁监听
1.HttpServletRequest对象的创建与销毁分析:request对象是发送请求时创建,当响应产生时,销毁.
5.监听步骤:
1.创建一个类,实现指定的监听器接口
2.重写接口中的方法
3.在web.xml文件中对监听器进行注册。
要想对Servlet域对象的生命周期进行监听,需要实现域对应的3.ServletContextListener,HttpSessionLister和ServletRequestListener接口
package cn.itcast.chapter08.listener; import javax.servlet.*; import javax.servlet.http.*; public class MyListener implements ServletContextListener, HttpSessionListener,ServletRequestListener { public void contextInitialized(ServletContextEvent arg0) { System.out.println("ServletContext对象被创建了"); } public void contextDestroyed(ServletContextEvent arg0) { System.out.println("ServletContext对象被销毁了"); } public void requestInitialized(ServletRequestEvent arg0) { System.out.println("ServletRequest对象被创建了"); } public void requestDestroyed(ServletRequestEvent arg0) { System.out.println("ServletRequest对象被销毁了"); } public void sessionCreated(HttpSessionEvent arg0) { System.out.println("HttpSession对象被创建了"); } public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("HttpSession对象被销毁了"); } }
一个完整的Servlet事件监听器包括Listener类和<listener>配置信息,而一个web.xml中可以配置多个监听器。同一种类型的监听器也可以配置多个,触发的时候服务器会顺序执行各个监听器的相应方法。
查看HttpSessionListener和ServletRequestListener监听器的运行效果,创建myjsp.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <html> <head> <title>this is MyJsp.jsp page</title> </head> <body> 这是一个测试监听器的页面 </body> </html>
<session-timeout>标签指定的超时必须为一个整数。如果这个整数为0或负整数,则session永远不会超时;如果这个数是正整数,则项目中的session将在指定分钟后超时。
zai
再次刷新
再次访问myjsp.jsp页面,在控制台窗口中会再次输出ServletRequest对象被创建与被销毁的信息,但不会创建新的用了HttpSession对象。这是因为Web容器会为每次访问请求都创建一个新的ServletRequest对象,而对于同一个浏览器在会话期间的后续访问是不会再创建新的HttpSession对象的。
HttpSession对象被销毁了,Web服务器调用了监听器对象的sessionDestroyed()方法。
观察各个对象域对象属性性监听器的作用
实现接口所有方法
package cn.itcast.chapter08.listener; import javax.servlet.*; import javax.servlet.http.*; public class MyAttributeListener implements ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener { public void attributeAdded(ServletContextAttributeEvent sae) { String name = sae.getName(); System.out.println("ServletContext添加属性:" + name + "=" + sae.getServletContext().getAttribute(name)); } public void attributeRemoved(ServletContextAttributeEvent sae) { String name = sae.getName(); System.out.println("ServletContext移除属性: " + name); } public void attributeReplaced(ServletContextAttributeEvent sae) { String name = sae.getName(); System.out.println("ServletContext替换属性:" + name + "=" + sae.getServletContext().getAttribute(name)); } public void attributeAdded(HttpSessionBindingEvent hbe) { String name = hbe.getName(); System.out.println("HttpSession添加属性:" + name + "=" + hbe.getSession().getAttribute(name)); } public void attributeRemoved(HttpSessionBindingEvent hbe) { String name = hbe.getName(); System.out.println("HttpSession移除属性: " + name); } public void attributeReplaced(HttpSessionBindingEvent hbe) { String name = hbe.getName(); System.out.println("HttpSession替换属性:" + name + "=" + hbe.getSession().getAttribute(name)); } public void attributeAdded(ServletRequestAttributeEvent sra) { String name = sra.getName(); System.out.println("ServletRequest添加属性:" + name + "=" + sra.getServletRequest().getAttribute(name)); } public void attributeRemoved(ServletRequestAttributeEvent sra) { String name = sra.getName(); System.out.println("ServletRequest移除属性: " + name); } public void attributeReplaced(ServletRequestAttributeEvent sra) { String name = sra.getName(); System.out.println("ServletRequest替换属性:" + name + "=" + sra.getServletRequest().getAttribute(name)); } }
4.启动项目,查看结果
可以看出,在ServletContext、HttpSession和ServletRequest 3个域对象中.
分别完成了增加、替换和删除username属性值的操作。
JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、更新、新增和删除的操作。
访问MySQL数据库需要用到第三方的类,这些第三方的类,都被压缩在一个.Jar的文件里。mysql-connector-java-5.0.8-bin.jar包可以在网上下载,或者在MySQL的安装目录下找到。通常下载到该jar包之后将其放到在项目的lib目录下
导包步骤: 右键project->property->java build path->libaries->add external jars
如果没有完成上述步骤的导包操作,后面会抛出ClassNotFoundException
通过初始化驱动类com.mysql.jdbc.Driver,该类就在 mysql-connector-java-5.0.8-bin.jar中。如果你使用的是oracle数据库那么该驱动类将不同。
注意:Class.forName需要捕获ClassNotFoundException.
try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。
这里需要提供:数据库服务端的IP地址:127.0.0.1 (这是本机,如果连接其他电脑上的数据库,需填写相应的IP地址)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称 test(根据你自己数据库中的名称填写)
编码方式 UTF-8
账号 root
密码 root(如果你在创建数据库的时候没有使用默认的账号和密码,请填写自己设置的账号和密码)
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8", "root", "root"); //(string url,string user,string pwd) //jdbc:mysql://hostname:port/databasename //(hostname可以为localhost或127.0.0.1)
Connection是与特定数据库连接回话的接口,使用的时候需要导包,而且必须在程序结束的时候将其关闭。getConnection方法也需要捕获SQLException异常。
public static void main(String[] args) throws SQLException { Connection conn = null; PreparedStatement preStmt = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc"; String username = "root"; String password = "root"; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } conn = null; }
通过Connection对象获取Statement对象Connection创建Statement的方式有如下3种。
基本的Statement
statement stmt=conn.createStatement();
Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,然而查询略显复杂。在Statement中使用字符串拼接的方式,该方式存在句法复杂,容易犯错等缺点,具体在下文中的对比中介绍。所以Statement在实际过程中使用的非常的少,所以具体的放到PreparedStatement那里给出详细代码。
字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号和双引号的混用,极易出错。
Statement s = conn.createStatement(); // 准备sql语句 // 注意: 字符串要用单引号' String sql = "insert into t_courses values(null,"+"'数学')"; //在statement中使用字符串拼接的方式,这种方式存在诸多问题 s.execute(sql); System.out.println("执行插入语句成功");
与 Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement。除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。
注意:
使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了statement拼接字符串的繁琐之外,还能够提高性能。每次SQL语句都是一样的,java类就不会再次编译,这样能够显著提高性能。
String sql = "update t_course set course_name =? where course_id=?";
Statement s = conn.createStatement(); // 准备sql语句 // 注意: 字符串要用单引号' String sql = "INSERT INTO users(name,password,email,birthday)" + "VALUES(?,?,?,?)"; //在statement中使用字符串拼接的方式,这种方式存在诸多问题 s.execute(sql); System.out.println("执行插入语句成功");
后面需要用到PreparedStatement接口创建的pstmt的set方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
preStmt = conn.prepareStatement(sql); preStmt.setString(1, "zl"); preStmt.setString(2, "123456"); preStmt.setString(3, "zl@sina.com"); preStmt.setString(4, "1789-12-23"); preStmt.executeUpdate();
增删改都使用pstmt.executeUpdate();语句进行SQL语句的提交
所有的Statement 都有如下3种执行SQL语句的方法。
以 executeQuery()方法为例,其使用方式如下。
//执行SQL语句,获取结果集 ResultSetResultSet rs = stmt.executeQuery (sql);
如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象里保存了
SQL语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果。
每次操作数据库结束后都要关闭数据库连接,释放资源,包括关闭ResultSet、Statement
和Connection等资源。
至此,JDBC程序的大致实现步骤已经讲解完成。接下来,依照上面所讲解的步骤来演示
JDBC的使用。该程序从users表中读取数据,并将结果打印在控制台,
在MySQL中创建一个名称为jdbc的数据库,然后在该数据库中创建一个users表
数据库和表的SQL语句如下所示。
CREATE DATABASE jdbc; USE jdbc; CREATE TABLE users ( id INT PRIMARY KEY AUTO INCREMENT,name VARCHAR(40), password VARCHAR(40), email VARCHAR(60), birthday DATE )CHARACTER SET utf8 COLLATE utf8_general_ci;
数据库和表创建成功后,再向users表中插入3条数据,插入的SQL语句如下所示。
INSERT INTO users (NAME,PASSWORD, email,birthday)VALUES('zs','123456', 'zs0sina.com', '1980-12-04'); INSERT INTO users(NAME,PASSWORD,email,birthday) VALUES('lisi', '123456', 'lisi0sina.com','1981-12-04');INSERT INTO users (NAME,PASSWORD,email,birthday) VALUES('wangwu','123456', 'wangwu@sina.com','1979-12-04');
导入下载好的MySQL数据库驱动文件
创建Example01,用于读取数据库中的users表,并将结果输出控制台
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Date; public class Example01 { public static void main(String[] args) throws SQLException { Statement stmt = null; ResultSet rs = null; Connection conn = null; try { // 1. 注册数据库的驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.通过DriverManager获取数据库连接 String url = "jdbc:mysql://localhost:3306/jdbc"; String username = "root"; String password = "root"; conn = DriverManager.getConnection (url, username, password); // 3.通过Connection对象获取Statement对象 stmt = conn.createStatement(); // 4.使用Statement执行SQL语句。 String sql = "select * from users"; rs = stmt.executeQuery(sql); // 5. 操作ResultSet结果集 System.out.println("id | name | password | email | birthday"); while (rs.next()) { int id = rs.getInt("id"); // 通过列名获取指定字段的值 String name = rs.getString("name"); String psw = rs.getString("password"); String email = rs.getString("email"); Date birthday = rs.getDate("birthday"); System.out.println(id + " | " + name + " | " + psw + " | " + email + " | " + birthday); } } catch (ClassNotFoundException e) { e.printStackTrace(); } finally{ // 6.回收数据库资源 if(rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } }
首先注册了MySQL数据库驱动,通过DriverManager获取一个Connection对象,然后使用Connection对象创建一个Statement对象,Statement对象通过executeQuery()方法执行SQL语句,并返回结果集ResultSet。接下来,通过遍历ResultSet得到最终的查询结果,最后关闭连接,回收了数据库资源。
程序执行成功后,控制台的打印结果如图所示
注意:
虽然使用 DriverManager.registerDriver(new com.mysql.jdbc.Driver())方法也可以完成注
册,但此方式会使数据库驱动被注册两次。这是因为Driver类的源码已经在静态代码块中完成了
数据库驱动的注册。所以,为了避免数据库驱动被重复注册,只需在程序中使用Class.forName()
方法加载驱动类即可。
由于数据库资源非常宝贵,数据库允许的并发访问连接数量有限,因此,当数据库资源使用
完毕后,一定要记得释放资源。为了保证资源的释放,在Java程序中,应该将最终必须要执行的操作放在 finally 代码块中。
创建Example02的类,在类中使用PreparedStatement对象对数据库进行插入数据的操作,预编译信息储存在PreparedStatement对象,提高数据访问效率
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement ; import java.sql.SQLException; public class Example02 { public static void main(String[] args) throws SQLException { Connection conn = null; PreparedStatement preStmt = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc"; String username = "root"; String password = "root"; // 创建应用程序与数据库连接的Connection对象 conn = DriverManager.getConnection(url, username, password); // 执行的SQL语句 String sql = "INSERT INTO users(name,password,email,birthday)" + "VALUES(?,?,?,?)"; // 创建执行SQL语句的PreparedStatement 对象 preStmt = conn.prepareStatement(sql); preStmt.setString(1, "zl"); preStmt.setString(2, "123456"); preStmt.setString(3, "zl@sina.com"); preStmt.setString(4, "1789-12-23"); preStmt.executeUpdate(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { // 释放资源 if (preStmt != null) { try { preStmt.close(); } catch (SQLException e) { e.printStackTrace(); } preStmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } } }
首先通过Connection对象的prepareStatement()方法生成PreparedStatement对象,然后调用PreparedStatement对象的setXxx()方法,给SQL语句中的参数赋值,最后通讨调executeUpdate()方法执行SQL语句。
文件运行成功后,会在users表中插入一条数据。进入MySQL数据库,使用SELECT句查看users表,查询结果如9-5所示。