上周末聽了在用友工作的兩個學(xué)長的一個小講座,雖然時間不長,但還是有些收獲的,其中一個開發(fā)部的經(jīng)理就提到了一些小的技術(shù)點(diǎn),其中就包括dwr,回家后上網(wǎng)查了查相關(guān)資料,了解到dwr是一個java開源框架,它的誕生就是為了降低開發(fā)ajax的難度,原理類似于在javascript中調(diào)用java類,于是就使用dwr技術(shù)模擬Google首頁做了個練習(xí)。由于正直全國哀悼日,頁面效果與各大網(wǎng)站相同,采用灰色樣式,在這里祝愿遭受災(zāi)難的親人們早日重建家園。
運(yùn)行效果如圖:

后臺數(shù)據(jù)庫為Oracle:
--創(chuàng)建查詢信息表
create table searchInfo
(
id number not null primary key,--編號
content varchar2(100) not null,--查詢內(nèi)容
count number not null--查詢次數(shù)
)
--創(chuàng)建序列
create sequence seq_searchInfo;
--創(chuàng)建插入數(shù)據(jù)的存儲過程
create or replace procedure proc_add(vContent varchar2,vResult out varchar2)
as
vCount number;
begin
select count(*) into vCount from searchInfo where content = vContent;
if vCount = 0 then
insert into searchInfo values(seq_searchInfo.Nextval,vContent,1);
else
update searchInfo set count = count + 1 where content = vContent;
end if;
vResult := 'success';
exception
when others then
vResult := 'fail';
end;
首先需要把dwr.jar導(dǎo)入到WEB-INF\lib目錄下,然后在web.xml文件中配置DWRServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet>
<description>
This is the description of my J2EE component
</description>
<display-name>
This is the display name of my J2EE component
</display-name>
<servlet-name>ServletX</servlet-name>
<servlet-class>control.ServletX</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletX</servlet-name>
<url-pattern>/ServletX</url-pattern>
</servlet-mapping>
</web-app>

接著需要在WEB-INF\lib目錄下創(chuàng)建dwr.xml文件,并對javascript要調(diào)用的類進(jìn)行聲明并公開方法,當(dāng)然默認(rèn)公開全部方法,需要提到的是,若類方法的參數(shù)或返回值為Bean,則還需要使用convert標(biāo)簽
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
<dwr>
<allow>
<create creator="new" javascript="history">
<param name="class" value="operation.OperSearchInfo" />
<include method="getHistory" />
</create>
<convert converter="bean" match="entity.SearchInfo">
<param name="include" value="content,count" />
</convert>
</allow>
</dwr>
兩個xml文件配置好后,可以在地址欄中輸入
http://localhost:9527/工程名/dwr進(jìn)行測試,若測試成功,將顯示可用的類及其方法
創(chuàng)建控制器ServletX.java,本例中只是判斷用戶的搜索操作是否成功,并以控制臺的形式輸出
package control;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import operation.*;


public class ServletX extends HttpServlet
{

private static final long serialVersionUID = 1L;


public ServletX()
{
super();
}


public void destroy()
{
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException
{
String model = request.getParameter("model");

if(model.equals("search"))
{
String content = Translation.transCode(request.getParameter("content"));
OperSearchInfo obj = new OperSearchInfo();

if(obj.search(content))
{
System.out.println("success");

}else
{
System.out.println("fail");
}
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException
{
this.doGet(request, response);
}


public void init() throws ServletException
{
// Put your code here
}
}

創(chuàng)建與數(shù)據(jù)庫表對應(yīng)的實(shí)體Bean,SearchInfo.java文件
package entity;


/** *//**
* 搜索信息表實(shí)體
* @author 非凡DZ
*
*/

public class SearchInfo
{
private int id;//編號
private String content;//查詢內(nèi)容
private int count;//查詢次數(shù)

public String getContent()
{
return content;
}

public void setContent(String content)
{
this.content = content;
}

public int getCount()
{
return count;
}

public void setCount(int count)
{
this.count = count;
}

public int getId()
{
return id;
}

public void setId(int id)
{
this.id = id;
}
}

創(chuàng)建對數(shù)據(jù)庫表searchInfo進(jìn)行操作的類OperSearchInfo.java及方法
package operation;

import java.sql.*;
import java.util.*;
import db.DataBase;
import entity.SearchInfo;

/** *//**
* 該類包含對searchInfo表所有操作
* @author 非凡DZ
*
*/

public class OperSearchInfo
{

/** *//**
* 用戶點(diǎn)擊搜索按鈕后執(zhí)行
* @param content
* @return
*/

public boolean search(String content)
{
boolean flag = false;
DataBase db = new DataBase();
Connection con = db.getConnection();
CallableStatement cs = null;

try
{
cs = con.prepareCall("{call proc_add(?,?)}");
cs.setString(1, content);
cs.registerOutParameter(2, java.sql.Types.CHAR);
cs.execute();

if(cs.getString(2).equals("success"))
{
flag = true;
}

}catch(Exception e)
{
System.out.println("proc異常"+e.getMessage());
e.printStackTrace();

}finally
{

try
{
con.close();

}catch(Exception ex)
{
System.out.println("關(guān)閉連接異常"+ex.getMessage());
ex.printStackTrace();
}
}
return flag;
}

/** *//**
* 獲得與界面文本框中信息相似的前10條信息
* @param content 界面文本框中的數(shù)據(jù)
* @return 相似信息
*/

public ArrayList getHistory(String content)
{
DataBase db = new DataBase();
Connection con = db.getConnection();
ResultSet rs = null;
ArrayList<SearchInfo> aryResult = new ArrayList<SearchInfo>();
String sql = "select content,count from searchInfo where content"
+" like ? and rownum <= 10 order by count desc";

try
{

if(!content.equals(""))
{
PreparedStatement pstn = con.prepareStatement(sql);
pstn.setString(1, content+"%");
rs = pstn.executeQuery();

while(rs.next())
{
SearchInfo info = new SearchInfo();
info.setContent(rs.getString(1));
info.setCount(rs.getInt(2));
aryResult.add(info);
}
}

}catch(Exception e)
{
System.out.println("獲得歷史查詢信息異常"+e.getMessage());
e.printStackTrace();

}finally
{

try
{
con.close();

}catch(Exception ex)
{
System.out.println("關(guān)閉連接異常"+ex.getMessage());
ex.printStackTrace();
}
}
return aryResult;
}
}

Translation類用于處理數(shù)據(jù)傳輸?shù)木幋a問題
package operation;

import java.io.*;


/** *//**
* 該類用于解決編碼問題
* @author 非凡DZ
*
*/

public class Translation
{

public Translation()
{
}


public static String transCode(String str)
{
String temp = null;

if(str == null)
{
temp = "";
}

try
{
temp = new String(str.getBytes("iso8859-1"), "utf-8");

} catch (UnsupportedEncodingException ex)
{
}
return temp;
}
}

DataBase用于獲得數(shù)據(jù)庫連接
package db;

import java.sql.*;

/** *//**
* 該類用于獲取數(shù)據(jù)庫連接
* @author 非凡DZ
*
*/

public class DataBase
{
private Connection con;
private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:thin:@localhost:1521:daizhenghenry";
private String uid = "daizheng";
private String pwd = "daizheng";

public Connection getConnection()
{

try
{
Class.forName(driver);
con = DriverManager.getConnection(url, uid, pwd);

}catch(Exception e)
{
System.out.println("連接異常"+e.getMessage());
e.printStackTrace();
}
return con;
}
}

最后是jsp頁面

<%
@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>模擬搜索引擎</title>

<style type="text/css">
html

{
}{
filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}
</style>
<script type='text/javascript' src='/ajaxTest/dwr/interface/history.js'></script>
<script type='text/javascript' src='/ajaxTest/dwr/engine.js'></script>
<script type='text/javascript' src='/ajaxTest/dwr/util.js'></script>

<script language="javascript">

/**//*處理用戶相關(guān)搜索*/

function change(data)
{
//得到表格中的行數(shù)
var count = document.getElementById('tab').rows.length;
//如果表中存在行,將所有行刪除

if(count >0)
{

for(var i=count-1;i>=0;i--)
{
document.getElementById('tab').deleteRow(i);
}
}
//如果存在相關(guān)搜索記錄

if(data.length > 0)
{
document.getElementById('Related').style.display = '';
document.getElementById('x').style.display = '';

for(var i=0;i<data.length;i++)
{
var objTr = document.getElementById('tab').insertRow();
var objTd1 = objTr.insertCell(0);
objTd1.innerHTML = "<input readonly type='text' "
+"size='35' name='txtHistory' style='border:none;background:#FFFFFF'"
+" value='"+data[i].content+"' onmouseover='overChangeColor(this)'"
+" onmouseleave='leaveChangeColor(this)' "
+"onclick='clickHistory(this)'>";
var objTd2 = objTr.insertCell(1);
objTd2.innerHTML = "<input type='text' name='result' readonly"
+" size='15' style='border:none;background:#FFFFFF;text-align:right'"
+" value='"+data[i].count+"結(jié)果"+"' align='right'/>";
objTd2.align = 'right';
}

}else
{
document.getElementById('Related').style.display = 'none';
}
}

/**//*關(guān)閉歷史查詢記錄*/

function myClose()
{
document.getElementById('Related').style.display = 'none';
}

/**//*鼠標(biāo)在相關(guān)搜索內(nèi)容上方時執(zhí)行*/

function overChangeColor(object)
{
var histories = document.getElementsByName('txtHistory');

for(var i=0;i<histories.length;i++)
{
//如果當(dāng)前鼠標(biāo)停留在某一行上

if(histories[i].style.background == '#ccffcc')
{
histories[i].style.background = '#FFFFFF';
var tdObj1 = histories[i].parentElement;//td
var trObj1 = tdObj1.parentElement;//tr
var childObj1 = trObj1.childNodes(1);
var x1 = childObj1.childNodes(0);
x1.style.background = '#FFFFFF';
break;
}
}
object.style.background = '#CCFFCC';
var tdObj = object.parentElement;//td
var trObj = tdObj.parentElement;//tr
var childObj = trObj.childNodes(1);
var x = childObj.childNodes(0);
x.style.background = '#CCFFCC';
}

/**//*鼠標(biāo)離開相關(guān)搜索內(nèi)容上方時執(zhí)行*/

function leaveChangeColor(object)
{
object.style.background = '#FFFFFF';
var tdObj = object.parentElement;//td
var trObj = tdObj.parentElement;//tr
var childObj = trObj.childNodes(1);//td
var x = childObj.childNodes(0);//input
x.style.background = '#FFFFFF';
}

/**//*鼠標(biāo)點(diǎn)擊相關(guān)搜索內(nèi)容時執(zhí)行*/

function clickHistory(object)
{
document.frm.content.value = object.value;
document.getElementById('Related').style.display = 'none';
frm.submit();
}

/**//*用戶在搜索框中按鍵事件處理*/

function keySelectHistory()
{
var nKeyCode = window.event.keyCode;

if(nKeyCode == 38 || nKeyCode == 40)
{
var count = document.getElementById('tab').rows.length;
var tempRowId;//記錄鼠標(biāo)懸浮所在行
var flag = false;//標(biāo)識是否有已經(jīng)變色的行

if(count > 0 && (nKeyCode == 38 || nKeyCode == 40))
{//如果存在相關(guān)搜索信息
var histories = document.getElementsByName('txtHistory');

for(var i=0;i<histories.length;i++)
{
//如果當(dāng)前鼠標(biāo)停留在某一行上

if(histories[i].style.background == '#ccffcc')
{
tempRowId = i;
flag = true;
break;
}
}

if(!flag)
{
tempRowId = 0;
}

if(nKeyCode == 38)
{//向上鍵

if(tempRowId > 0)
{
leaveChangeColor(histories[tempRowId]);
overChangeColor(histories[tempRowId - 1]);
document.frm.content.value = (histories[tempRowId - 1]).value;

}else
{
leaveChangeColor(histories[0]);
overChangeColor(histories[count - 1]);
document.frm.content.value = (histories[count - 1]).value;
}

}else if(nKeyCode == 40)
{//向下鍵

if(tempRowId == 0 && histories[0].style.background != '#ccffcc')
{
overChangeColor(histories[0]);
document.frm.content.value = histories[0].value;

}else if(tempRowId < count -1)
{
leaveChangeColor(histories[tempRowId]);
overChangeColor(histories[tempRowId + 1]);
document.frm.content.value = (histories[tempRowId + 1]).value;

}else
{
leaveChangeColor(histories[tempRowId]);
overChangeColor(histories[0]);
document.frm.content.value = histories[0].value;
}
}
}

}else
{//搜索框內(nèi)容發(fā)生改變時(手動使其變化,而非通過上下鍵)
var str = document.frm.content.value;
history.getHistory(str,change);
}
}
</script>
</head>
<body>
<b>模擬搜索引擎</b>
<br />
<form action="ServletX" name="frm" method="post">
<img alt="逝者安息,生者堅(jiān)強(qiáng)" src="images\daonian.gif" />
<br />
<br />
<input type="hidden" name="model" value="search" />
<input type="text" size="55" name="content"
onkeyup="keySelectHistory()" />
<input type="submit" value="搜索" />
<div id="Related"
style="border:1px solid #f990033;display:'none';width:335;">
<table id="tab" cellpadding="0" border="0" cellspacing="0">
</table>
<a id="x" href='javascript:;' onclick='myClose()'
style="display:none">關(guān)閉</a>
</div>
</form>
</body>
</html>

盡情享受dwr為我們開發(fā)ajax帶來的暢爽吧!