模擬Google首頁(dwr實現ajax) 彈出補全搜索結果

上週末聽了在用友工做的兩個學長的一個小講座,雖然時間不長,但仍是有些收穫的,其中一個開發部的經理就提到了一些小的技術點,其中就包括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>
相關文章
相關標籤/搜索