Ajax实现关键字联想和自动补全功能及遇到坑

遇到的小坑

  • 回调函数相对window.onload的摆放位置
  • 给回调函数addData传数据时,如何操作才能将数据传进去

代码实现

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>ajax实现关键字联想和自动补全</title>
 <style>
 *{
 margin: 0;
 padding: 0;
 box-sizing: border-box;
 }
 #keyWords{
 margin-top: 10px;
 margin-left: 10px;
 width: 300px;
 height: 25px;
 font-size: 20px;
 padding-left: 5px;
 }
 #dataDiv{
 background-color: wheat;
 width: 300px;
 margin-left: 10px;
 display: none;
 }
 #dataDiv p{
 padding-left: 10px;
 padding-top: 7px;
 padding-bottom: 3px;
 cursor: pointer;
 }
 #dataDiv p:hover{
 background-color: cornflowerblue;
 color: white;
 }
 </style>
</head>
<body>
 <!--
 需求:
 1. 给定文本输入框,显示层,显示层里的显示栏
 2. 当用户在文本框里输入数据时,发生keyup事件时,将文本框里的数据,以ajax请求方式提交的到后端
 3. 后端对前端提交的关键字,在数据库里进行模糊查询
 4. 将后端查询到的数据以json格式传给前端
 5. 前端解析后端传来的数据,将数据显示在提示栏里
 6. 当用户点击提示中的某条提示信息时,将提示栏里的信息赋给输入框,隐藏提示层
 注意:1. 凡是输入框里发生keyup事件时,都要进行ajax请求提交,实时获取提示信息
 2. 输入框信息为空时,也要隐藏提示层
 -->
 <script>
 window.onload = function (){
 //获取dom对象
 input_txt = document.getElementById("keyWords")
 div_data = document.getElementById("dataDiv")
 //为输入框绑定keyup事件
 input_txt.onkeyup = function (){
 //输入框为空,隐藏提示层
 if(this.value.trim() == ""){
 div_data.style.display = "none"
 }else{
 //每当keyup时,发送ajax请求,传递文本框内数据
 var xmlHttpRequest = new XMLHttpRequest();
 xmlHttpRequest.onreadystatechange = function (){
 if(this.readyState == 4){
 if(this.status == 200){
 //解析后端传来的json数据:[{"content" : "data"}, {}, {}]
 var jsonArray = JSON.parse(this.responseText)
 var html = ""
 for(var i = 0; i < jsonArray.length; i++){
 var perData = jsonArray[i].content
 //为p标签绑定单击事件,将数据以字符串的形式传给回调函数
 html += "<p onclick='addData(\""+perData+"\")'>"+perData+"</p>"
 }
 div_data.innerHTML = html
 div_data.style.display = "block"
 }else{
 alert("异常状态码: " + this.status)
 }
 }
 }
 xmlHttpRequest.open("GET", "/ajax/ajaxAutoComplete?keyWords="+this.value+"", true)
 xmlHttpRequest.send()
 }
 }
 }
 function addData(perData){
 //完成自动补全
 input_txt.value= perData
 //隐藏提示层
 div_data.style.display = "none"
 }
 </script>
 <input type="text" id="keyWords">
 <div id="dataDiv">
 <!--
 <p>java</p>
 <p>jsp</p>
 <p>service</p>
 <p>servlet</p>
 <p>docker</p>
 <p>linux</p>
 -->
 </div>
</body>
</html>

后端代码

package com.examples.ajax.servlet;
import com.alibaba.fastjson.JSON;
import com.examples.ajax.beans.KeyWords;
import com.examples.ajax.utils.DBUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/ajaxAutoComplete")
public class AjaxRequest13 extends HttpServlet {
 @Override
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 //获取前端传来的关键字
 String keyWords = request.getParameter("keyWords");
 //连接数据库,进行模糊查询
 Connection conn = null;
 PreparedStatement ps = null;
 ResultSet rs = null;
 //封装关键字对象
 List<KeyWords> keyWordsList = new ArrayList<>();
 try {
 conn = DBUtils.getConnection();
 String sql = "select content from tb_search where content like ?";
 ps = conn.prepareStatement(sql);
 ps.setString(1, keyWords + "%");
 rs = ps.executeQuery();
 while(rs.next()){
 String content = rs.getString("content");
 //封装成关键字对象
 KeyWords keyWordsObj = new KeyWords(content);
 //将关键字对象封装
 keyWordsList.add(keyWordsObj);
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 DBUtils.close(conn, ps, rs);
 }
 //后端数据json化
 String jsonKeyWordsArray = JSON.toJSONString(keyWordsList);
 //返回后端数据
 response.getWriter().write(jsonKeyWordsArray);
 }
}

用到的实体类

package com.examples.ajax.beans;
public class KeyWords {
 private String content;
 public KeyWords() {
 }
 public KeyWords(String content) {
 this.content = content;
 }
 public String getContent() {
 return content;
 }
 public void setContent(String content) {
 this.content = content;
 }
}

自己封装的jdbc工具类

package com.examples.ajax.utils;
import java.sql.*;
import java.util.ResourceBundle;
/**
 * 封装自己的jdbc工具类
 */
public class DBUtils {
 static ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
 static String driver;
 static String url;
 static String username;
 static String password;
 static {
 driver = bundle.getString("driver");
 url = bundle.getString("url");
 username = bundle.getString("username");
 password = bundle.getString("password");
 try {
 Class.forName(driver);
 } catch (ClassNotFoundException e) {
 throw new RuntimeException(e);
 }
 }
 private DBUtils(){}
 public static Connection getConnection() throws SQLException {
 return DriverManager.getConnection(url, username, password);
 }
 public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
 if(rs != null){
 try {
 rs.close();
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }
 }
 if(ps != null){
 try {
 ps.close();
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }
 }
 if(conn != null){
 try {
 conn.close();
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }
 }
 }
}

数据库表:

一张表: tb_search
数据表描述: 除了id, 就一个字段 content varchar(255) not null

效果展示:

自己在远程数据库上用docker运行了一个mysql数据库,查询速度比较慢,但演示关键字联想和自动补全功能的测试目的已经达到

作者:nefu-wangxun原文地址:https://www.cnblogs.com/nefu-wangxun/p/16493414.html

%s 个评论

要回复文章请先登录注册