Ajax应用---实现自动提示功能

本文示例通过Ajax技术实现自动提示功能,确保内容与服务器数据库同步。在实现过程中,遇到了由于服务器配置导致的GBK与UTF-8编码不匹配造成的乱码问题。解决方案包括修改`server.xml`配置或使用`URLDecoder.decode()`方法进行解码。分析了Tomcat中GET方法的乱码原因,并解释了为何`getQueryString()`在特定情况下能避免乱码。
摘要由CSDN通过智能技术生成

本例主要利用Ajax实现如下图的自动提示功能,且内容始终和服务器端数据库内容一致:
这里写图片描述
核心代码如下:

1. JSP文件用于显示基本界面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Auto-Complete</title>
</head>
<script type="text/javascript" charset="GBK" src="js3.js" ></script>
<body>
<table style="border-collapse: collapse;" bordercolor="#666666" 
cellspacing="0" cellpadding="2" width="400" bgcolor="#f5efe7" border="0">
    <tr>
        <td align="center" height="20" colspan="3">
        <b>学员信息搜索</b>
        </td>
    </tr>
    <tr>
        <td height="20">输入学生姓名:</td>
        <td height="20">
            <input type="text" size="15" id="name" onkeyup="findNames();" height="20">
            <div style="position:absolute" id="popup">
                <table id="complete_table" bgcolor="#FFFAFA" border="0" cellspacing="0" cellpadding="0">
                <tbody id="complete_body" style="cursor:pointer"></tbody>
                </table>
            </div>
        </td>
        <td height="20"><img alt="图片加载失败" src="images/search.png" height="20" onclick="search();"></td>
    </tr>
    <tr>
        <td height="20" align="left">学员情况:</td>
        <td id="pos_1" height="80">
            <textarea id="content"></textarea>
        </td>
    </tr>
</table>
</body>
</html>

2. JS文件实现‘服务器-客户端’通信操作

var XMLHttpReq;
var completeDiv;
var inputField;
var completeTable;
var completeBody;

function createXMLHttpRequest() {
    if (window.XMLHttpRequest) {// Mozilla 浏览器
        XMLHttpReq = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE 浏览器
        try {
            XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
            } 
        }
    }
}
//搜索请求函数
function search(){
    var sortName = document.getElementById("name");
    createXMLHttpRequest();
    var url = "autoComplete?action=search&name="+encodeURI(inputField.value);
    XMLHttpReq.open("GET",url,true);
    XMLHttpReq.onreadystatechange = processSearchResponse;
    XMLHttpReq.send(null);
}
function processSearchResponse(){
    if (XMLHttpReq.readyState == 4) {// 判断对象状态,4则说明服务器响应已完成,可以访问了
        if (XMLHttpReq.status == 200) {// 信息已经成功返回,开始处理信息
            var res = XMLHttpReq.responseXML.getElementsByTagName("res");
            if (res.length>0){
                document.getElementById("content").value = res[0].firstChild.data;
            }
        } else {
            window.alert("您所请求的页面有异常!");
        }
    }
}
//查找匹配的名字
function findNames(){
    inputField = document.getElementById("name");//获取输入的字符
    completeTable = document.getElementById("complete_table");//显示查询结果的表
    completeDiv = document.getElementById("popup");//显示查询结果表的显示区域
    completeBody = document.getElementById("complete_body");//显示查询结果表的主体
    if(inputField.value.length>0&&inputField.value!=" "){
        createXMLHttpRequest();
        var url = "autoComplete?action=match&name="+encodeURI(inputField.value);
        XMLHttpReq.open("GET",url,true);
        XMLHttpReq.onreadystatechange = processMatchResponse;
        XMLHttpReq.send(null);
    }else{
        clearNames();//如果未输入则清除显示区域内容
    }
}
function processMatchResponse() {
    if (XMLHttpReq.readyState == 4) {// 判断对象状态,4则说明服务器响应已完成,可以访问了
        if (XMLHttpReq.status == 200) {// 信息已经成功返回,开始处理信息
            setNames(XMLHttpReq.responseXML.getElementsByTagName("res"));
        } else {
            window.alert("您所请求的页面有异常!");
        }
    }
}
//生成与输入内容匹配行
function setNames(names){
    clearNames();
    var size = names.length;//可能的名字有很多个,获取其数目
    setOffsets();//设置显示的位置
    var row,cell,txtNode;
    for(var i=0;i<size;i++){
        var nextNode = names[i].firstChild.nodeValue;//获取文本节点的值
        row = document.createElement("tr");
        cell= document.createElement("td");

        cell.setAttribute("bgcolor","#FFFAFA");
        cell.onclick = function(){completeField(this)};

        txtNode = document.createTextNode(nextNode);
        cell.appendChild(txtNode);
        row.appendChild(cell);
        completeBody.appendChild(row);
    }
}
//设置显示位置
function setOffsets(){
    completeTable.style.width = inputField.offsetWidth+"px";//提示框宽度和输入框一致
    var left = calculateOffset(inputField,"offsetLeft");
    var top = calculateOffset(inputField,"offsetTop")+inputField.offsetHeight;
    completeDiv.style.border = "black 1px solid";//设置区域的边框是黑实线
    completeDiv.style.left = left +"px";
    completeDiv.style.top = top +"px";
}
//计算显示位置
function calculateOffset(field,attr){
    var offset = 0;
    while(field){
        offset+=field[attr];//返回当前元素左边缘距离offsetParent属性返回元素的距离,单位是像素。
        field = field.offsetParent;
    }
    return offset;
}
//填写输入框
function completeField(cell){
    inputField.value = cell.firstChild.nodeValue;
    clearNames();
}
//清除自动完成的行
function clearNames(){
    var end = completeBody.childNodes.length;
    for(var i=end-1;i>=0;i--){
        completeBody.removeChild(completeBody.childNodes[i]);
    }
    completeDiv.style.border = "none";
}

3. 服务器端的java文件

package servletdemo;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mysql.fabric.Response;

@WebServlet("/AutoCompleteAction")
public class AutoCompleteAction extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public AutoCompleteAction() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String action = request.getParameter("action");
        //String name = request.getParameter("name");
        String queryStr = URLDecoder.decode(request.getQueryString() , "utf-8");  
        String[] paramPairs = queryStr.split("&");  
        String name = paramPairs[1].split("=")[1];

        response.setContentType("text/xml;charset=UTF-8");
        response.setHeader("Cache-Control", "no-cache");

        PrintWriter out = response.getWriter();
        out.println("<response>");
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/DB_student?useUnicode=true&characterEncoding=GBK";
            String user = "root";
            String password = "admin";
            Connection con = DriverManager.getConnection(url,user,password);
            Statement stat = con.createStatement();
            ResultSet rs = null;
            if("match".equals(action)){
                String sql ="select * from stuscore where name like '"+name+"%'";
                rs = stat.executeQuery(sql);
                while(rs.next()){
                    out.println("<res>"+rs.getString("name")+"</res>");
                }
            }else if("search".equals(action)){
                String sql ="select grade from stuscore where name='"+name+"'";
                rs = stat.executeQuery(sql);
                if(rs.next()){
                    out.println("<res>"+rs.getString("grade")+"</res>");
                }
            }
            rs.close();
            stat.close();
            con.close();
        }catch (Exception e) {
            e.printStackTrace();
        }
        out.println("</response>");
        out.close();
    }
}

这里开始是发现server.xml里面配置了
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="gbk"/>里的URIEncoding="gbk",导致使用
String name = request.getParameter("name");时服务器使用gbk对utf-8编码的url进行解码,故产生乱码,将URIEncoding="gbk"去掉或者改成URIEncoding="utf-8"即可。
使用下面方法则可以不管server.xml里配置了什么都可以正常解码:
`String queryStr = URLDecoder.decode(request.getQueryString() , “utf-8”);

原因分析:

`首先get方法用request.setCharacterEncoding(“UTF-8”)来解决乱码问题是不行的,因为在Tomcat5.0以上版本中,默认情况下使用ISO- 8859-1对URL提交的数据和表单中GET方式提交的数据进行重新编解码。使用getParameter时,Tomcat默认是用iso-8859-1先将原本utf-8编码的url使用iso-8859-1进行解码,故使用getParameter时会得到乱码;(疑问:为什么上面测试时可以将URIEncoding去掉也可以正确解码,是否说明默认解码方式为utf-8?)
而对于getQueryString,tomcat没有对其进行decode操作,保留了原有的urlencoding编码方式,所以在后面的使用过程中,如果利用utf-8对其解码,就不会出现乱码。

4. xml文件配置

<servlet>
     <servlet-name>AutoCompleteAction</servlet-name>
     <servlet-class>servletdemo.AutoCompleteAction</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>AutoCompleteAction</servlet-name>
     <url-pattern>/autoComplete</url-pattern>
</servlet-mapping>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值