上週末聽了在用友工做的兩個學長的一個小講座,雖然時間不長,但仍是有些收穫的,其中一個開發部的經理就提到了一些小的技術點,其中就包括dwr,回家後上網查了查相關資料,瞭解到dwr是一個java開源框架,它的誕生就是爲了下降開發ajax的難度,原理相似於在javascript中調用java類,因而就使用dwr技術模擬Google首頁作了個練習。因爲正直全國哀悼日,頁面效果與各大網站相同,採用灰色樣式,在這裏祝願遭受災難的親人們早日重建家園。
後臺數據庫爲Oracle:javascript
--建立查詢信息表 create table searchInfo ( id number not null primary key,--編號 content varchar2(100) not null,--查詢內容 count number not null--查詢次數 ) --建立序列 create sequence seq_searchInfo; --建立插入數據的存儲過程 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導入到WEB-INF/lib目錄下,而後在web.xml文件中配置DWRServlet
css
<?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目錄下建立dwr.xml文件,並對javascript要調用的類進行聲明並公開方法,固然默認公開所有方法,須要提到的是,若類方法的參數或返回值爲Bean,則還須要使用convert標籤
html
<?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進行測試,若測試成功,將顯示可用的類及其方法
建立控制器ServletX.java,本例中只是判斷用戶的搜索操做是否成功,並以控制檯的形式輸出
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 } }
建立與數據庫表對應的實體Bean,SearchInfo.java文件
web
package entity; /** *//** * 搜索信息表實體 * @author 非凡DZ * */ public class SearchInfo { private int id;//編號 private String content;//查詢內容 private int count;//查詢次數 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; } }
建立對數據庫表searchInfo進行操做的類OperSearchInfo.java及方法
ajax
package operation; import java.sql.*; import java.util.*; import db.DataBase; import entity.SearchInfo; /** *//** * 該類包含對searchInfo表全部操做 * @author 非凡DZ * */ public class OperSearchInfo { /** *//** * 用戶點擊搜索按鈕後執行 * @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("關閉鏈接異常"+ex.getMessage()); ex.printStackTrace(); } } return flag; } /** *//** * 得到與界面文本框中信息類似的前10條信息 * @param content 界面文本框中的數據 * @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("關閉鏈接異常"+ex.getMessage()); ex.printStackTrace(); } } return aryResult; } }
Translation類用於處理數據傳輸的編碼問題
sql
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用於得到數據庫鏈接
數據庫
package db; import java.sql.*; /** *//** * 該類用於獲取數據庫鏈接 * @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頁面
oracle
<%@ 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> <mce:style type="text/css"><!-- html {}{ filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); } --></mce:style><style type="text/css" mce_bogus="1"> html {}{ filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); } </style> <mce:script type='text/javascript' src="/ajaxTest/dwr/interface/history.js" mce_src="ajaxTest/dwr/interface/history.js"></mce:script> <mce:script type='text/javascript' src="/ajaxTest/dwr/engine.js" mce_src="ajaxTest/dwr/engine.js"></mce:script> <mce:script type='text/javascript' src="/ajaxTest/dwr/util.js" mce_src="ajaxTest/dwr/util.js"></mce:script> <mce:script language="javascript"><!-- /**//*處理用戶相關搜索*/ function change(data){ //獲得表格中的行數 var count = document.getElementById('tab').rows.length; //若是表中存在行,將全部行刪除 if(count >0){ for(var i=count-1;i>=0;i--){ document.getElementById('tab').deleteRow(i); } } //若是存在相關搜索記錄 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" mce_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" mce_style="border:none;background:#FFFFFF;text-align:right"" +" value='"+data[i].count+"結果"+"' align='right'/>"; objTd2.align = 'right'; } }else{ document.getElementById('Related').style.display = 'none'; } } /**//*關閉歷史查詢記錄*/ function myClose(){ document.getElementById('Related').style.display = 'none'; } /**//*鼠標在相關搜索內容上方時執行*/ function overChangeColor(object){ var histories = document.getElementsByName('txtHistory'); for(var i=0;i<histories.length;i++){ //若是當前鼠標停留在某一行上 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'; } /**//*鼠標離開相關搜索內容上方時執行*/ 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'; } /**//*鼠標點擊相關搜索內容時執行*/ 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;//記錄鼠標懸浮所在行 var flag = false;//標識是否有已經變色的行 if(count > 0 && (nKeyCode == 38 || nKeyCode == 40)){//若是存在相關搜索信息 var histories = document.getElementsByName('txtHistory'); for(var i=0;i<histories.length;i++){ //若是當前鼠標停留在某一行上 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{//搜索框內容發生改變時(手動使其變化,而非經過上下鍵) var str = document.frm.content.value; history.getHistory(str,change); } } // --></mce:script> </head> <body> <b>模擬搜索引擎</b> <br /> <form action="ServletX" name="frm" method="post"> <img alt="逝者安息,生者堅強" src="images/daonian.gif" mce_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:;" mce_href="javascript:;" onclick='myClose()' style="display:none" mce_style="display:none">關閉</a> </div> </form> </body> </html>