提高Servlet從數(shù)據(jù)庫(kù)中讀取記錄的性能
在這個(gè)例子中,我們將學(xué)習(xí)如何提高Web應(yīng)用程序從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)記錄的性能。要實(shí)現(xiàn)這個(gè)工作,我們將employess表的數(shù)據(jù)預(yù)先從數(shù)據(jù)庫(kù)中讀取出來并存儲(chǔ)在一個(gè)集合中,以在servlet中重用這個(gè)集合。因此,當(dāng)使用到這個(gè)employess表的數(shù)據(jù)時(shí),只需要從ServletContext獲取即可,而不需要連接數(shù)據(jù)庫(kù)中查詢表的數(shù)據(jù)記錄。這樣就能提高數(shù)據(jù)的讀取性能。
要運(yùn)行此應(yīng)用程序,需要?jiǎng)?chuàng)建具有一些記錄的表。完整的SQL語(yǔ)句如下 -
DROP TABLE IF EXISTS `employees`;
CREATE TABLE `employees` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL DEFAULT '',
`age` int(3) unsigned NOT NULL DEFAULT '0',
`address` varchar(254) DEFAULT NULL,
`salary` float(8,2) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of employees
-- ----------------------------
INSERT INTO `employees` VALUES ('1', '李小春', '23', '??谑腥嗣翊蟮?800號(hào)', '8900.00');
INSERT INTO `employees` VALUES ('2', '張輝', '28', '廣州天河區(qū)珠村市場(chǎng)', '15800.00');
INSERT INTO `employees` VALUES ('3', '林賢弟', '25', '廣州白云區(qū)龍?zhí)链?20號(hào)', '18990.00');
在這個(gè)例子中,我們創(chuàng)建了6個(gè)代碼文件。它們分別如下 -
bean類,包含幾個(gè)屬性及其getter和setter方法,此類用于表示數(shù)據(jù)庫(kù)表:employees。打開Eclipse,創(chuàng)建一個(gè)動(dòng)態(tài)Web項(xiàng)目:ImprovingFetchRecords,其完整的目錄結(jié)構(gòu)如下所示 -

以下是這個(gè)項(xiàng)目中的幾個(gè)主要的代碼文件。
文件:index.html -
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Servlet從數(shù)據(jù)庫(kù)讀取記錄性能優(yōu)化</title>
</head>
<body style="text-algin: center;">
<a href="servlet1">從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)</a>|
<a href="servlet2">讀取存儲(chǔ)的數(shù)據(jù)</a>
</body>
</html>
員工信息Bean類:Employees.java -
package com.yiibai;
public class Employees {
private int id;
private String name;
private String address;
private int age;
private float salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
}
文件:MyListener.java -
這是是一個(gè)監(jiān)聽類。當(dāng)部署項(xiàng)目時(shí),默認(rèn)情況下會(huì)調(diào)用ServletContextListener的contextInitialized方法。 在這里,將查詢獲取employees表的記錄,并將數(shù)據(jù)記錄在添加存儲(chǔ)到ArrayList類對(duì)象中。 最后,表的所有記錄將存儲(chǔ)在ArrayList類對(duì)象(集合)。 最后,將ServletConext對(duì)象中的ArrayList對(duì)象作為屬性存儲(chǔ),以便可以在Servlet中獲取并使用它。
package com.yiibai.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.yiibai.Employees;
import java.sql.*;
import java.util.ArrayList;
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent e) {
String jdbcDriver = "com.mysql.jdbc.Driver";
String dbURL = "jdbc:mysql://localhost/testdb";
// Database credentials
String dbUser = "root";
final String passwd = "123456";
Connection con = null;
ArrayList list = new ArrayList();
try {
Class.forName(jdbcDriver);
con = DriverManager.getConnection(dbURL, dbUser, passwd);
PreparedStatement ps = con.prepareStatement("SELECT * FROM `employees`");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Employees emp = new Employees();
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
emp.setAddress(rs.getString("address"));
emp.setAge(rs.getInt("age"));
emp.setSalary(rs.getFloat("salary"));
list.add(emp);
}
rs.close();
ps.close();
//con.close();
} catch (Exception ex) {
System.out.print(ex);
}
// storing the ArrayList object in ServletContext
ServletContext context = e.getServletContext();
context.setAttribute("con", con);
context.setAttribute("datalist", list);
}
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("project undeployed...");
}
}
文件:MyServlet1.java -
MyServlet1從servlet上下文對(duì)象獲取信息并打印它。
package com.yiibai;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
long before = System.currentTimeMillis();
ServletContext context = getServletContext();
try {
Connection con = (Connection) context.getAttribute("con");
PreparedStatement ps;
ps = con.prepareStatement("SELECT * FROM `employees`");
ResultSet rs = ps.executeQuery();
out.print("員工數(shù)據(jù)信息如下所示:<hr/>");
while (rs.next()) {
out.print("" + rs.getInt("id") + ", " + rs.getString("name") + ", " + rs.getString("address"));
out.println("<br/>");
}
//con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long after = System.currentTimeMillis();
out.print("<br>總用時(shí) :" + (after - before));
out.close();
}
}
文件:MyServlet2.java -
它與MyServlet1相同,從servlet上下文對(duì)象獲取信息并打印它。
package com.yiibai;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
long before = System.currentTimeMillis();
ServletContext context = getServletContext();
List list = (List) context.getAttribute("datalist");
out.print("員工數(shù)據(jù)信息(從ServletContext中預(yù)存儲(chǔ)讀取)如下所示:<hr/>");
Iterator itr = list.iterator();
while (itr.hasNext()) {
Employees e = (Employees) itr.next();
out.print("" + e.getId() + ", " + e.getName() + ", " + e.getAddress());
out.println("<br/>");
}
long after = System.currentTimeMillis();
out.print("<br>總用時(shí):" + (after - before));
out.close();
}
}
文件:web.xml -
這個(gè)文件中配置包含有關(guān)servlet和監(jiān)聽器的信息。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>ImprovingFetchRecords</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.yiibai.listener.MyListener</listener-class>
</listener>
<servlet>
<servlet-name>MyServlet1</servlet-name>
<servlet-class>com.yiibai.MyServlet1</servlet-class>
</servlet>
<servlet>
<servlet-name>MyServlet2</servlet-name>
<servlet-class>com.yiibai.MyServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MyServlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
</web-app>
在編寫上面代碼后,部署此Web應(yīng)用程序(在項(xiàng)目名稱上點(diǎn)擊右鍵->”Run On Server…”),打開瀏覽器訪問URL: http://localhost:8080/ImprovingFetchRecords/ ,如果沒有錯(cuò)誤,應(yīng)該會(huì)看到以下結(jié)果 -
注意:將需要將MySQL驅(qū)動(dòng)程序庫(kù)加到WEB-INFO/lib目錄下。

點(diǎn)擊“從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)”鏈接,應(yīng)該會(huì)看到以下結(jié)果 -
點(diǎn)擊“讀取存儲(chǔ)的數(shù)據(jù)”鏈接,應(yīng)該會(huì)看到以下結(jié)果 -
