监听提升程序效率
业务需求 : 在实现用户注册的业务时,需要使用JDBC和MySQL打交道。在这个过程中,最耗时的是连接对象的创建,如何简短程序耗时呢?
Ref : 连接数据库通过console实现简单的java登录操作
根据业务需求,我们引入ServletContextListener这个监听接口,其监听的是全局作用域对象(ServletContext)的初始化和销毁时刻。而全局作用域对象在Http服务器启动时初始化,在服务器关闭时销毁。因此我们可以将JDBC连接对象存储在全局对象中。
监听的步骤
- 实现ServletContextListener接口的实现类
public class OneListener implements ServletContextListener
- 重写contextInitialized和contextDestroyed方法
//监听器监听到全局作用域对象的初始化时调用该方法
public void contextInitialized(ServletContextEvent sce) {
JDBCUtil util=new JDBCUtil();
Map map=new HashMap();
for (int i = 0; i <20 ; i++) {
try {
Connection con=util.getConnection();
System.out.println("创建连接"+con);
//使用con的地址作为key
map.put(con,true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
// map是局部变量,为了保存它,将它放到全局作用域对象中,其生命周期是服务器的启动到关闭
ServletContext application= sce.getServletContext();
application.setAttribute("connKey",map);
}
//监听销毁时刻
public void contextDestroyed(ServletContextEvent sce) {
ServletContext application= sce.getServletContext();
Map map=(Map)application.getAttribute("connKey");
//获得map所有的keySet
Iterator it= map.keySet().iterator();
//set中的对象是无序的,不能被遍历,可以获得其迭代器
while (it.hasNext()){
Connection con=(Connection)it.next();
if(con!=null){
System.out.println("销毁连接"+con);
}
}
}
- 在WEB-INF的web.xml中注册监听
<listener>
<listener-class>com.company.listener.OneListener</listener-class>
</listener>
在JDBC中使用创建的连接对象
程序设计原则:对扩展开放,对修改关闭。 因此修改原来JDBCUtil工具类的代码需要采用方法重载的方式。
public Connection getConnection(HttpServletRequest req) throws SQLException {
Connection con=null;
//通过请求对象获得全局作用域对象
ServletContext application=req.getServletContext();
Map map=(Map)application.getAttribute("connKey");
Iterator it=map.keySet().iterator();
while (it.hasNext()){
con=(Connection)it.next();
//迭代map的keySet,如果con的值为true则代表未使用,将其返回并修改键值对为false表示正在使用。
if((boolean)map.get(con)){
map.put(con,false);
break;
}
}
return con;
}
public void close(Connection conn, Statement ps,HttpServletRequest req ){
if (ps!=null){
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
ServletContext application=req.getServletContext();
Map map=(Map)application.getAttribute("connKey");
map.put(conn,true);
}
//重载DAO中注册向数据库添加数据的方法
public int add(Users user, HttpServletRequest req) {
Connection conn = null;
PreparedStatement ps = null;
int rs=0;
try {
//使用重载的方法
conn = util.getConnection(req);
String sql = "insert into t_userInfo(userName,password,sex,email) values(?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, user.getUserName());
ps.setString(2, user.getPassword());
ps.setString(3, user.getSex());
ps.setString(4, user.getEmail());
rs = ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//使用重载的方法
util.close(conn,ps,req);
}
return rs;
}
HttpServletRequest req的传递路径:
controller(Servlet)=>DAO(add方法)=>JDBCUtil(getConnection和close方法)