当前页面: 开发资料首页 → Java 专题 → 构建更有效的WEB应用
摘要: 构建更有效的WEB应用
//schema.sql
connect to trdata;
create table trentry (ID integer not null , NAME char(25), DESCR varchar(128), views integer with default 0, constraint p_trentry primary key (ID));
//PropSamples.java
package train;
import java.util.*;
import java.sql.*;
public class PropSamples {
public static String GetString(int size, Random rand) {
StringBuffer strBuff = new StringBuffer();
for (int i = 0; i < size; i++) {
char b = (char) (rand.nextInt(25) + 65);
strBuff.append(b);
}
return strBuff.toString();
}
public void Process() throws SQLException {
String sqlString = "insert into trentry values(?,?,?,?)";
Connection connection = Util.getDBConnection();
PreparedStatement stmt = connection.prepareStatement(sqlString);
Random rand = new Random();
for (int i = 1; i <= 250000; i++) {
stmt.clearParameters();
stmt.setInt(1, i);
stmt.setString(2, GetString(25, rand));
stmt.setString(3, GetString(128, rand));
stmt.setInt(4, 0);
stmt.execute();
if (i%1000 == 0) {
connection.commit();
System.out.println(i + " rows committed");
}
}
}
public static void main(String[] args) throws SQLException{
PropSamples propSamples = new PropSamples();
propSamples.Process();
}
}
// ClassicServlet.java
package train;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
public class ClassicServlet
extends HttpServlet {
int mEntryLength = 250000;
Random mRand;
public void init() throws ServletException {
mRand = new Random(System.currentTimeMillis());
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
PrintWriter out = response.getWriter();
Statement stmt = null;
Connection connection = null;
String name = "";
String descr = "";
int views = 0;
int id = 0;
boolean isError = false;
synchronized (mRand) {
id = mRand.nextInt(mEntryLength);
}
try {
connection = Util.getDBConnection();
stmt = connection.createStatement();
String sqlStr = "Select id, name, descr, views from trentry where id =" + id;
ResultSet rs = stmt.executeQuery(sqlStr);
while (rs.next()) { //retrieves data from from DB
name = rs.getString("NAME");
descr = rs.getString("DESCR");
id = rs.getInt("ID");
views = rs.getInt("VIEWS");
}
Statement stmtViews = connection.createStatement();
String sqlViewStr = "update trentry set views = views+1 where id =" + id;
stmtViews.executeUpdate(sqlViewStr); //updates number of the page views
}
catch (SQLException ex) {isError = true;}
finally {
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.commit();
connection.close();
}
}
catch (SQLException ex1) {isError = true;}
}
if (isError) {
out.println("System error");
}
else { //Delivers html page to browser
out.println("");
out.println("ID: " + id + "
");
out.println("Name: " + name + "
");
out.println("Description: " + descr + "
");
out.println("Views: " + views + "
");
out.println("</body>");
}
}
}
statement.addBatch(); //Load the first passenger
statement.addBatch(); // Load the second passenger
…
statement.executeBatch(); //Train is departing
//TrainServlet.java
package train;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class TrainServlet extends HttpServlet {
int mEntryLength=250000;
Dispatcher mDispatcher;
Random mRand;
public void init() throws ServletException {
mRand = new Random(System.currentTimeMillis());
mDispatcher = new Dispatcher();
Thread ht = new Thread(mDispatcher); //Instantiate and execute in the separate thread.
ht.start();
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int id=0;
synchronized(mRand){
id=mRand.nextInt(mEntryLength);
}
Job job = new Job(String.valueOf(id)); //Each concurrent request creates job instance.
job.mJobThread = Thread.currentThread(); //Job should know the thread of the request.
PrintWriter out = response.getWriter(); //Job should know the output stream of the browser.
job.mOut = out;
mDispatcher.AddJob(job); //Job is sent to the dispatcher.
//Dispatcher is a container for all concurrent jobs.
try {
Thread.sleep(100000); //Let's wait until database interaction is finished.
System.out.println("Error: Request is timed out"); //Too bad. 100 seconds was not enough.
}
catch (InterruptedException ex2) {
//Success! Members of the Job instances are populated.
}
job.Marshall(); // Let's display the page in the browser.
}
}
//Job.java
package train;
import java.io.*;
public class Job {
String mName;
String mDescr;
int mViews;
String mID;
PrintWriter mOut;
Thread mJobThread;
boolean mHasFailed = false;
//Sorry, no getters and setters to save space
public Job(String id) {
mID = id;
}
public void Marshall(){ // displays html page
mOut.println("<body>");
if(mHasFailed){
mOut.println("System error");
}else{
mOut.println("ID: "+mID+"
");
mOut.println("Name: "+mName+"
");
mOut.println("Description: "+mDescr+"
");
mOut.println("Views: "+mViews+"
");
}
mOut.println("</body>");
}
}
//Dispatcher.java
package train;
import java.util.*;
public class Dispatcher
implements Runnable {
private List mCurrentJobBatch = new ArrayList(); //Batch container
private int mJobBatchMaxSize = 5; //Maximum number of the jobs in the batch
private int mIntervalTime = 50; //Maximum time to wait before batch execution
public synchronized void AddJob(Job job) {
mCurrentJobBatch.add(job);
if (mCurrentJobBatch.size() == mJobBatchMaxSize) {
ProcessJobBatch(); //If batch is full, execute
}
}
private synchronized void ProcessJobBatch() {
if (mCurrentJobBatch.size() == 0) { return; }
Worker worker = new Worker(mCurrentJobBatch);
Thread ht = new Thread(worker);
ht.start();
mCurrentJobBatch = new ArrayList();
}
public void run() {
try {
while (true) {
Thread.sleep(mIntervalTime);
ProcessJobBatch(); // Each mIntervalTime milliseconds execute batch
}
}
catch (InterruptedException ex) { }
}
}
//Worker.java
package train;
import java.util.*;
import java.sql.*;
public class Worker
implements Runnable {
List mJobs;
Map mJobMap; //Helper member for mapping the jobs
protected Worker(List jobs) {
mJobs = jobs;
mJobMap = new HashMap();
}
private void Process() {
boolean isError = false;
StringBuffer sqlBuff = new StringBuffer(
"Select id,name ,descr,views from trentry where id in ");
StringBuffer whereClause = CreateWhereClause(); //
sqlBuff.append(whereClause);
/* Now SQL statement is fully formed and looks like:
Select id,name ,descr,views from trentry where id in (3343,22222,5555).
This will allow us to fetch several user requests in one shot */
Connection connection = null;
Statement stmt = null;
try {
connection = Util.getDBConnection();
stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sqlBuff.toString());
System.out.println(sqlBuff.toString());
Map result = new HashMap();
while (rs.next()) {
int id = rs.getInt("ID");
String name = rs.getString("NAME");
String descr = rs.getString("DESCR");
int views = rs.getInt("VIEWS");
Job job = (Job) mJobMap.get(String.valueOf(id));
//Populate instance of the Job with data retrieved from database
job.mName = name;
job.mDescr = descr;
job.mViews = views;
}
String sqlViewStr = "update trentry set views = views+1 where id in " +
whereClause;
// The same trick for Update statement
stmt.executeUpdate(sqlViewStr);
}
catch (SQLException ex) {
isError = true;
}
finally {
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
if (isError) {
connection.rollback();
}
else {
connection.commit();
}
connection.close();
}
}
catch (SQLException ex1) { isError = true; }
}
FinishJobs(isError);
return;
}
private StringBuffer CreateWhereClause() {
StringBuffer clause = new StringBuffer("(");
for (int i = 0; i < mJobs.size(); i++) {
Job job = (Job) mJobs.get(i);
String id = job.mID;
if (i != 0) {
clause.append(",");
}
clause.append(id);
mJobMap.put(id, job);
}
clause.append(")");
return clause;
}
private void FinishJobs(boolean isError) {
for (int i = 0; i < mJobs.size(); i++) {
Job job = (Job) mJobs.get(i);
if (isError) {
job.mHasFailed=true; //Rudimentary error handling
}
job.mJobThread.interrupt();
/* Wake up the TrainServlet to deliver the page to the browser */
}
}
public void run() {
Process();
}
}