Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)

Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)

内容比较长、是完整的开发过程,可以根据目录查看感兴趣的地方。


目录

    • 核心思路
    • 开发环境
    • 完成结果
    • 一、前端页面编写
    • 二、导入相关依赖包
    • 三、创建数据库
    • 四、构建Servlet相关类
      • 1、实体类:Student.java
      • 2、Servlet连接数据库父类:SQL.java
      • 3、Student数据表操作类:StudentSQL.java
    • 五、具体功能实现
      • 1、页面内容的加载
      • 2、添加学生记录
      • 3、编辑学生记录
      • 4、删除学生记录
    • 六、拓展与完善
      • 1、数据有效性
      • 2、搜索框
    • 七、一点感想
    • 八、完整源代码下载

核心思路

  • 前端HTML页面,构成JSP页面
  • 后端Servlet管理
  • 后端使用JDBC连接数据库

开发环境

  • Dreamweaver CC 2018
  • Eclipse EE
  • MySQL 5.7

完成结果

  • 实现学生信息管理系统,能够对学生信息进行查看、增加、修改、删除、搜索、排序等功能;
  • 不包含任何框架,如JQurry;

一、前端页面编写

使用DW CC2018将整个系统的页面静态的编写出来。完成情况如下图所示:
Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第1张图片
HTML的部分没有太大的问题,在这里也不再赘述和放置源码。
静态页面编写完成后,即可在Eclipse中新建JSP文件,将HTML代码放入。

二、导入相关依赖包

在整个系统中将会需要用到的第三方包有下列几个:
Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第2张图片
这些包都可以在Maven的第三方包下载网页下载。

三、创建数据库

在MySQL数据库中提前放入我们所需要的数据。
这里根据我的需要构建如下数据表:
Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第3张图片
并放入几行数据。

四、构建Servlet相关类

在构建服务端Servlet之前,我们需要根据java类的功能创建如下三个包:

  • Servlet包(用来存放Servlet类)
  • dao包(用来存放使用第三方库的接口或类)
  • entity包(实体包,用来存放实体类对象)

Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第4张图片
这样分有一个好处就是分门别类,结构比较清晰。

下面我们分别说明各个类的作用及内容

1、实体类:Student.java

我们首先建立一个实体类方便我们对数据库中每一行的数据对象进行管理。
Student类的内容可以和数据库中的字段一一对应。

public class Student {
	private String id;
	private String name;
	private String classes;
	private String phone;
	private String mail;
	private float grade_web;
	private float grade_learning;
	
	
	public Student(String id, String name, String classes, String phone, String mail, float grade_web,
			float grade_learning) {
		
		this.id = id;
		this.name = name;
		this.classes = classes;
		this.phone = phone;
		this.mail = mail;
		this.grade_web = grade_web;
		this.grade_learning = grade_learning;
	}
	
	//set和get函数省略

}

2、Servlet连接数据库父类:SQL.java

在这个类中我们会使用JDBC来连接数据库。

// 连接数据库要使用的量
private static String dbUrl = "jdbc:mysql://localhost:3306/studentinfo?characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";
// 登录数据库的用户名
private static String name; 
// 登录数据库的密码
private static String password;
// 数据库驱动
private static String jdbcName = "com.mysql.jdbc.Driver";

private Connection connection = null;

在这其中我们先初始化以上几个变量。其中dburl中 “localhost:3306”是数据库配置时分配的端口号;“studentinfo”是我们要连接的数据库的名称。
然后我们需要初始化登录MySQL时的用户名和密码;

连接数据库:

// 初始化连接数据库
	protected Connection connectSQL() {
		connection = null;
		try {
			// 加载数据库驱动
			Class.forName(jdbcName);
			// 建立连接
			connection = DriverManager.getConnection(dbUrl, name, password);
			System.out.println("MySQL数据库连接成功");
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("MySQL数据库连接失败");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("数据库驱动异常");
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("连接数据库时其他异常");
		}

		return connection;
	}

关闭数据库:

	// 关闭数据库连接
	protected static void closeSQL(Connection con, PreparedStatement pstmt, ResultSet rs) {
		try {
			if (rs != null)
				rs.close();
			if (pstmt != null)
				pstmt.close();
			if (con != null)
				con.close();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("MySQL关闭失败");
		}
		System.out.println("MySQL关闭成功");
	}

数据库操作:

	//数据库操作
	public int executeUpdate(String sql, Object[] obj) { // sql:sql语句,obj:obj对象
		connection = connectSQL();
		PreparedStatement pstmt = null;
		try {
			pstmt = prepareStatement(connection, sql, obj);
			int i = pstmt.executeUpdate();
			return i;
		} catch (SQLException e) {
			e.printStackTrace();
			return 0;
		} finally {
			closeSQL(connection, pstmt, null);
		}

	}

	protected PreparedStatement prepareStatement(Connection con,String sql,Object []obj){		
		PreparedStatement pstmt=null;
				try {
					int index=1;
					pstmt = con.prepareStatement(sql);
						if(pstmt!=null&&obj!=null){
							for (int i = 0; i < obj.length; i++) {			
								pstmt.setObject(index, obj[i]);	
									index++; 
							}
						}
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
		 return pstmt;
	}

通过上述三个部分的内容我们已经可以连接数据库、关闭数据库和对数据库进行操作了。接下来就是针对每一个数据表进行对应需要的功能了。

3、Student数据表操作类:StudentSQL.java

这个类需要继承上面建立的SQL类,作为其子类。
因为上面这个父类其实可以看做是一个接口,并没有细化到每一个数据表的每一个操作。因此我们需要在这个StudentSQL类中实现一些我们需要的方法函数,如对Student数据表的增删查改等方法。

根据我们系统的需要我们可以构造一下几个方法:

(1)遍历数据、显示数据表中所有信息

根据SQL里的方法我们直接构造出这样的方法:

	public List<Student> search(String sql,Object...params){
		List<Student> list =new ArrayList<Student>();
		Connection con=this.connectSQL();
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		try {
			pstmt=this.prepareStatement(con, sql, params);
			rs=pstmt.executeQuery();
			while(rs.next()){
				Student student=new Student(rs.getString(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getString(5),rs.getFloat(6),rs.getFloat(7));
				list.add(student);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			closeSQL(con, pstmt, rs);
		}
		return list;
	}
	
	//遍历数据库
	public List<Student> findall(){
		String sql="SELECT * FROM student";
		return search(sql);
	}

接下来的其他对数据库的操作都可以根据这个来改写了

(2)条件查询、查询是否存在该条记录
在这个数据表中每一条记录有一个唯一主键:学号id,我们可以根据这唯一主键进行条件搜索,以此判断是否存在该条记录。

	//查询记录是否存在
	public boolean findone(Student student) {
		String sql="select * from student where id="+student.getId();
		List<Student> list=search(sql);
		if(list.isEmpty()) {
			System.out.println("不存在对应记录");
			return false;	
		}
		else {
			System.out.println("存在该条记录");
			return true;
		}
	

(3)新增一条记录
在新增记录的时候需要注意的一点是,如果学号id已存在,即数据库中已存在该条记录,那么应该无法插入,因此,在插入前我们先进行一步判断,判断该记录是否存在,若不存在,则插入。

	//新增记录
	public int insert(Student student){	
		boolean existed=findone(student);
		if (!existed) {	//不存在该条记录
			String sql="INSERT INTO student (id,name,class,phone,mail,grade_web,grade_learning) VALUE(?,?,?,?,?,?,?)";
			return executeUpdate(sql, new Object[]{student.getId(),student.getName(),student.getClasses(),student.getPhone(),student.getMail(),student.getGrade_web(),student.getGrade_learning()});
		}
		else 
			return 0;
	}

(4)修改一条记录
同样在修改一条记录的时候我们也需要进行记录存在与否的判断,只有存在该条记录我们才能进行修改。

	//修改记录
	public int update(Student student) {
		boolean existed=findone(student);
		if (existed) {	//存在该条记录
			String sql="update student set id=?,name=?,class=?,phone=?,mail=?,grade_web=?,grade_learning=? where id=?";
			return executeUpdate(sql, new Object[]{student.getId(),student.getName(),student.getClasses(),student.getPhone(),student.getMail(),student.getGrade_web(),student.getGrade_learning(),student.getId()});
		}
		else 
			return 0;
	}

(5)删除一条记录
与修改一条记录的思路相同,判断存在性、删除。

	//删除记录
	public int delete(Student student) {
		boolean existed=findone(student);
		if (existed) {	//存在该条记录
			String sql="delete from student where id=?";
			return executeUpdate(sql, new Object[]{student.getId()});
		}
		else 
			return 0;
	}

(6)条件查询、根据一个字段值进行查询
根据某一个字段和一个关键词来进行搜索,类似于上面查询记录是否存在的升级版。

	//条件查询函数
	public List<Student> find_condition(String row,String condition) {
		String sql = "select * from student where "+ row + " = \"" + condition + "\"";
		return search(sql);
	}

我对数据库不是很熟悉,不知道MySQL可不可以进行全局搜索,即不需要字段进行关键词的匹配搜索。有哪位大佬知道的,可以分享一下,一起讨论,学习。

一个与数据库相关的类就已经构造完成了。接下来就是构造Servlet类,以此作为服务端主体。接下来,我会根据具体功能结合前端JSP的内容进行分析。

五、具体功能实现

1、页面内容的加载

当页面在首次加载的时候就应该默认显示出所有记录,即当页面元素全部加载完毕之后前端需要发送一个请求给服务端,服务端根据请求内容(这里就是遍历数据库并返回所有结果)返回给客户端结果。我采用的方式是Ajax发送请求的方式。

通过调用JS里面 window.onload() 函数就可以完成加载完页面元素时的下一步操作。

//页面初始化加载,显示全部记录
window.onload = function(){	
	var whole_page=document.getElementById("whole_page");	//获取页面id
	whole_page.style.width=(window.screen.availWidth-15)+"px";	//设置页面宽度和高度为屏幕可用高度和宽度
	whole_page.style.height=window.screen.availHeight+"px";
					
	requestAjax("show_all_student");		//Ajax请求			
}

通过requestAjax函数进行Ajax请求。

Ajax请求的具体操作很简单,网上也有很多教程和例子,我就直接放上我的代码了。

//ajax请求
var req;
function requestAjax(param){
	
	var url="ShowServlet?control="+param;  //将信息连接成字符串,作为发送请求的参数  
	if(window.XMLHttpRequest) { 
		 //IE7, Firefox, Opera支持 
		 req = new XMLHttpRequest(); 
	}
	else if(window.ActiveXObject) { 
		 //IE5,IE6支持 
		 req = new ActiveXObject("Microsoft.XMLHTTP"); 
	} 

	req.open("POST", url, true); 
	//onreadystatechange属性存有处理服务器响应的函数,有5个取值分别代表不同状态 

	req.onreadystatechange = callback; 	//回调函数
	//send函数发送请求 
	req.send(null); 
}

在Ajax请求之后返回的内容和操作都将在callback回调函数中进行。
我们先看服务端接受ajax请求。
在上面Ajax请求中,我们可以看到url是ShowServlet,也就是会向ShowServlet发送请求。
问号?后面的是请求所带的参数,参数以键值对的形式存在:健名=键值,此时我的参数为:control=show_alll_student 就可以被发送给服务端。
接下来我们还设置了请求的方式:在req.open函数中设置了以POST请求的方式。服务器端就将在doPost()函数中接收请求。

需要注意的是:我们在传参和后面传递值得时候都需要注意一点就是 编码方式要统一,建议都采用UTF-8的编码方式进行传值,否则会出现中文乱码的情况。
首先设置编码方式:
request.setCharacterEncoding(“utf-8”);
response.setCharacterEncoding(“utf-8”);
response.setContentType(“text/html;charset=utf-8”);

在通过getParameter方法获取传递过来的参数。

String control=request.getParameter("control");

List<Student> list = null;


if(control==null) {
	return;
}
else if(control.equals("show_all_student"))	//显示全部
	list=studentSQL.findall();

通过这样的方式我们就可以将我们所需要的记录保存到一个ArrayList中了,可这样的对象数组的形式我们是无法传递回客户端的。因此,我们要做出一定的改变。
一个方法就是将这些数据转化成JSON数据,再转化成JSONString,这样就可以传递JSONString了。

我们可以通过JSONArray的数据结构保存多个JSON对象。

for(Student student:list) {

	JSONObject json = new JSONObject();
	json.put("id", student.getId());
	json.put("name", student.getName());
	json.put("classes", student.getClasses());
	json.put("phone", student.getPhone());
	json.put("mail",student.getMail());
	json.put("grade_web", student.getGrade_web());
	json.put("grade_learning", student.getGrade_learning());
	
	jsonArray.add(json);
}

PrintWriter out = response.getWriter();
out.print(jsonArray);
out.flush();
out.close();

这样,服务端的工作就结束了,已经将值传递出去了。现在轮到客户端来接收这些数据了。

var dataspan=document.getElementById("data");
var data="";
function callback() { 
	if(req.readyState == 4 && req.status == 200) { 
		var jsonArray_str = req.responseText;			
		
		data=dataspan.innerHTML;

		var jsonArray = JSON.parse(jsonArray_str);
		
		for(json in jsonArray){
			var data_one=""+jsonArray[json].id+""+""+jsonArray[json].name+""+""+jsonArray[json].classes+""+""+jsonArray[json].phone+""+""+jsonArray[json].mail+""+""+jsonArray[json].grade_web+""+""+jsonArray[json].grade_learning+"";
			
			var tail = ' + ' οnclick="popup_window(this)"' + '>编辑    + ' οnclick="delete_note(this)"' + ' >删除';
			data_one=""+data_one+tail+"";
			data+=data_one;
		}
			
		dataspan.innerHTML=data;
	} 
}	

客户端接收到这些JSONString之后又转化成原来的JSONArray,通过遍历我们就能得到我们想要的数据。
要想将这些数据按照网页的内容框架显示出来,我们还需要下面几步调整。

  1. 首先,确定我们要将数据放入到一个表格 中,表头是固定的。name我们提前写好表头:
    <table id="data">
    	<tr>
    		<th rowspan="2">学号</th>
    		<th rowspan="2">姓名</th>
    		<th rowspan="2">班级</th>
    		<th rowspan="2">电话</th>
    		<th rowspan="2">邮箱</th>
    		<th colspan="2">学科成绩</th>
    		<th rowspan="2">操作</th>
    	</tr>
    	<tr>
    		<th>Web技术</th>
    		<th>机器学习</th>
    	</tr>
    </table>
    
    
    1. 有很多种方式将数据放入到这个表格中,我采用的是直接将内容写入到表格的innerHTML中。也就是上面callback函数中,先获取了表格(id=data)的innerHTML,此时还只是表头,接下来,将数据通过data这个String一一写入;最后再放入到表格的innerHTML中。

    到这里,我们的显示数据的过程就已经完成了。
    如果现在我们运行客户端和服务端我们就可以看到一个初始默认显示全部记录的结果。
    Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第5张图片

    2、添加学生记录

    添加学生记录客户端需要有所输入,这时我们采用表单的方式就会方便很多。
    这里我设置了一个div来让用户填写表单,当点击添加学生按钮时,显示div,其余时刻,或div内点击取消时,隐藏div。可以看作是一个简易版的网页弹窗的形式。
    Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第6张图片
    只需要设置display方式就可以了。
    用户就可以根据提示填写表单。最后点击确定提交表单。
    在定义表单时我们就可以定义请求的地址和请求的方式:

    <form class="new_window_form"  method="get" action="ShowServlet">
    

    ShowServlet就可以通过GET方式进行请求。
    在服务端这边,还是一样

    1. 先设置编码方式:
    request.setCharacterEncoding("utf-8");
    response.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    
    1. 接收参数
      通过request.getParameter()方法获取参数,在这里就是表单的内容。获取到单独的一条条String内容后我们可以构造一个Student对象,把数据放入其中,方便管理和下一步的操作。
    String id = request.getParameter("id");
    String name = request.getParameter("name");
    String classes = request.getParameter("class");
    String phone = request.getParameter("phone");
    String mail = request.getParameter("mail");
    float grade_web = Float.parseFloat(request.getParameter("grade_web"));
    float grade_learning = Float.parseFloat(request.getParameter("grade_learning"));
    
    Student student = new Student(id, name, classes, phone, mail, grade_web, grade_learning);
    		
    
    1. 最后调用StudentSQL中的insert函数就可以插入数据库了。然后通过:
    response.sendRedirect("index.jsp");
    

    返回原来的index.jsp。

    3、编辑学生记录

    编辑和新建一样都是需要用户输入来进行操作的,因此还是通过表单的方式进行。只需要动态的方式改变表单的标题和内容就可以了,这样就只需要一个表单。
    同新建不同的是,编辑时,我们需要预留原来的值在表单当中。
    Web开发实训——学生信息管理系统(JSP+Servlet+Ajax+MySQL)_第7张图片
    而我们发现,表格的每一行后面都有一个编辑,那么问题来了:如何区分用户点击的是哪个行的编辑呢?只有确定了用户点击的是哪一行,我们才能将值赋在表单当中。

    这里有两种方法提供参考:

    • 动态赋给编辑一个id;id的值可以为整条记录或是该条记录的学生id号,但这样的方式,在弹出表单的时候还要进行一次Ajax请求来获取表单的其他值的内容。
    • 通过兄弟结点的方式获得表格该行其他列的内容查询相关资料后我们发现,可以通过parentNode和children来获取一个结点的父节点和子节点,这样我们就可以获取到一个结点的兄弟节点,即一个表格的一行的其他内容。

    这里我采用的是第二种方法。

    else{
    	document.getElementById("window_title").innerHTML="编辑一条记录";
    	document.getElementById("submit_btn").value="edit";
    	
    	document.getElementById("id").value = btn.parentNode.parentNode.children[0].textContent;
    	document.getElementById("name").value = btn.parentNode.parentNode.children[1].textContent;
    	document.getElementById("class").value = btn.parentNode.parentNode.children[2].textContent;
    	document.getElementById("phone").value = btn.parentNode.parentNode.children[3].textContent;
    	document.getElementById("mail").value = btn.parentNode.parentNode.children[4].textContent;
    	document.getElementById("grade_web").value = btn.parentNode.parentNode.children[5].textContent;
    	document.getElementById("grade_learning").value = btn.parentNode.parentNode.children[6].textContent;	
    }
    

    获取了该行数据的其他值,用户进行编辑更改,点击确定按钮提交表单。接下来的这些操作就和新建一样了。服务端接收到这些参数后,调用StudentSQL的update函数就可以修改数据库中的值了。

    4、删除学生记录

    删除学生记录不需要用户进行输入我们就可以不用表单的形式,而采用Ajax请求的方式进行删除。

    1. 和编辑一样,我们先获取到一个点击删除的该行的数据,因为删除在数据库操作时只需要用到一个唯一标识符:主键学号id即可,因此我们将学号id通过Ajax请求传递给服务端。
    2. 服务端接收到学号id后,直接调用StudentSQL.delete()方法就可以完成数据库的删除操作了。

    **到目前为止,整个学生信息管理系统的基本功能就已经完成了。接下来就是一些拓展和完善部分**

    六、拓展与完善

    1、数据有效性

    在新建和编辑的时候我们可以验证输入内容的有效性和合法性。如输入的学号是否为正整数纯数字、电话号码、邮箱是否为正确格式的电话号码和邮箱、输入的成绩的值是否在0~100以内,还有一个重要的内容就是输入不能为空。

    验证有效性最简单的方法就是正则表达式。

    //学号正确性判断
    function check_id(element){
    	var id_text=element.value;
    	var id_msg = document.getElementById("id_msg");
    	if(id_text.length==0)
    		id_msg.innerHTML="学号不能为空!";
    	else if(!(/^[0-9]\d*$/.test(id_text)))
    		id_msg.innerHTML="请输入正确的学号!";
    	else
    		id_msg.innerHTML="";
    }
    
    //电话有效性判断
    function check_phone(element){	
    	var phone_msg=document.getElementById("phone_msg");
    	var phone_text=element.value;
    	if(!(/^1[3456789]\d{9}$/.test(phone_text)))
    		phone_msg.innerHTML="请填写正确的手机号码!";			 
    	else
    		phone_msg.innerHTML="";
    }
    
    //邮箱有效性判断
    function check_mail(element){	
    	var mail_msg=document.getElementById("mail_msg");
    	var mail_text=element.value;
    	if(!(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(mail_text)))
    		mail_msg.innerHTML="请填写正确的邮箱地址!";				 
    	else
    		mail_msg.innerHTML="";
    }
    
    //成绩有效性判断
    function check_grade(element){	
    	var web_msg=document.getElementById("web_msg");
    	var learning_msg=document.getElementById("learning_msg");
    	var grade=parseFloat(element.value);
    	if(grade<0.0||grade>100){
    		if(element.id=="grade_web")
    			web_msg.innerHTML="请输入正确的成绩!";
    		else if(element.id=="grade_learning")
    			learning_msg.innerHTML="请输入正确的成绩!";
    	}
    	else{
    		if(element.id=="grade_web")
    			web_msg.innerHTML="";
    		else if(element.id=="grade_learning")
    			learning_msg.innerHTML="";
    	}	
    }
    
    

    在表单填写过程中,可以采用onblur函数来调用以上这些函数,当输入框失去焦点时进行判断。

    <input type="text" autocomplete="off" placeholder="学号" name="id" id="id" onblur="check_id(this)" required />
    

    2、搜索框

    在编写静态页面时,我们就已经设置了一个搜索框,现在我们来实现搜索框的功能。我们这里的搜索框有两种:

    • 数据库搜索框,即在数据库中搜索满足条件的记录,显示对应记录。
    • 另一种是页面搜索框,即搜索页面内容,并将结果高亮显示。

    下面分别实现两种搜索框。

    (1)数据库搜索框
    对数据库进行搜索时,因为只有一个搜索框,没有对应的字段值,无法通过一个“select”和“where”来进行搜索,因此我们在进行数据库搜索的时候就需要遍历数据库的字段名,先遍历字段的名字,在分别赋值给”where“来进行搜索。

    //遍历字段值
    public List<String> getColumn(Object...params){
    	List<String> list=new ArrayList<String>();
    	String sql = "desc student";
    	
    	Connection con=this.connectSQL();
    	PreparedStatement pstmt=null;
    	ResultSet rs=null;
    	try {
    		pstmt=this.prepareStatement(con, sql, params);
    		rs=pstmt.executeQuery();
    		while(rs.next()){
    			String string = rs.getString(1);
    			list.add(string);
    		}
    	} catch (SQLException e) {
    		e.printStackTrace();
    	}finally{
    		closeSQL(con, pstmt, rs);
    	}
    	return list;
    	
    }
    

    接下来在客户端JS中写调用的函数,进行服务端请求,采用表单,Ajax等形式都可以,我这里采用的是Ajax的形式。

    搜索框点击搜索按钮调用onclick函数,在函数中我们就可以进行Ajax请求。

    //数据库搜索功能
    function search_database(){
    	var key = document.getElementById("search_key").value;
    	if(key=="")	{	//页面内容输入为空
    		requestAjax("control=show_all_student");
    		return;
    	}
    	var param = "control=search&value="+key;
    	requestAjax(param);
    }
    

    服务器端一样的响应请求。

    else if(control.equals("search")) {		 //数据库搜索
    	String key = request.getParameter("value");
    	List<String> columnList =studentSQL.getColumn();	//获取字段值
    	for(String column:columnList) {		//遍历搜索
    		List<Student> array = new ArrayList<Student>();
    		array = studentSQL.find_condition(column,key);
    		list.addAll(array);
    	}
    }
    

    这样就可以完成对一个关键词的搜索并保存到一个List中返回给客户端前端显示。

    拓展:
    一般来说我们在进行搜索的时候都希望能有模糊搜索的功能,在进行数据库搜索时可以进行模糊搜索。
    只需要改动一点点就可以了:只需要在数据库操作类StudentSQL类中的条件搜索函数中改成利用正则表达式进行搜索就可以了。

    //条件查询函数
    public List<Student> find_condition(String row,String condition) {
    	String sql = "select * from student where "+ row + " REGEXP \"" + condition + "\"";
    	return search(sql);
    }
    

    如果当我们搜索“2”时,理论上应该是显示“小花”和小刚两条记录。

    但是会出现下面这种情况,原因是一条记录匹配了2次或多次,我们要把重复的记录去掉。
    我们可以利用Set没有重复性的特点,将ArrayList转化为Set,来去重。
    考虑到对象类型的Set集合无法去重,我们先在Student类里重写equals方法hashCode方法

    //重写判断相等
    @Override
    public boolean equals(Object obj) {
    	if (obj == null)
    		return false;
    	if (this == obj)
    		return true;
    	if (obj instanceof Student) {
    		Student student = (Student) obj;
    		// 比较每一个属性值,相等才相等
    		if (student.getId().equals(this.id) 
    				&& student.getName().equals(this.name)
    				&& student.getClasses().equals(this.classes) 
    				&& student.getPhone().equals(this.phone)
    				&& student.getMail().equals(this.mail) 
    				&& student.getGrade_web() == this.grade_web
    				&& student.getGrade_learning() == this.grade_learning)
    			return true;
    	}
    	return false;
    }
    
    // 重写hashCode
    @Override
    @SuppressWarnings("deprecation")
    public int hashCode() {
    	Float float_web = new Float(grade_web);
    	Float float_learning = new Float(grade_learning);
    	return id.hashCode() * name.hashCode() * classes.hashCode() * phone.hashCode() * mail.hashCode() * float_web.hashCode() * float_learning.hashCode();
    }
    

    关于为什么要重写而不能直接使用set的去重功能,具体可以参考这篇博文。

    https://blog.csdn.net/lavorange/article/details/80420087

    经过set去重我们就可以完后曾模糊搜索的功能了。

    else if(control.equals("search")) {		 //数据库搜索
    	String key = request.getParameter("value");
    	List<String> columnList =studentSQL.getColumn();	//获取字段值
    	for(String column:columnList) {		//遍历搜索
    		List<Student> array = new ArrayList<Student>();
    		array = studentSQL.find_condition(column,key);
    		list.addAll(array);
    	}
    	
    	Set<Student> set = new HashSet<Student>(list);	//去重后set集合
    	
    	List<Student> temp_list = new ArrayList<Student>(set);
    	list=temp_list;	
    	
    }
    

    最后向前端输出list内容就可以了。

    (2)页面内容搜索框
    页面内容搜索框就只包含前端的内容了,不需要进行后端的操作。在搜索框中输入关键词,能够将表格中的搜索结果高亮显示出来。

    大概思路如下:
    首先通过innerHTML获取到我们要搜索的区域的所有内容(包含标签代码!!!),然后通过split函数将关键词两边的内容分开,然后给关键词加上style属性,再用join函数合在一起就可以了。

    但是这样做有一个弊端,就是,如果搜索的内容是某些关键词或标签(如搜索“div”、“span”)时,就会出现报错,因为你将代码标签也算作字符串的一部分了。因此要解决这个去掉标签的问题。

    我也没有想到一个很好的方法,网上查到的资料有说可以使用正则表达式来去标签,鉴于当前系统只需要搜索表格内容,即网页内容不复杂,甚至说很单一,因为只有

    两种标签,所以我将标签一同加入到搜索的关键词当中,这样就不会出现搜索内容为标签时报错的情况了。

    理论上是这个样子的,因为还是不太熟悉正则表达式,暂时还没有实现出该功能。

    七、一点感想

    写完一整个系统,真实感受就是全栈式开发好累(其实还是自己太菜了)。学到了许多新东西,但是还是有很多地方不会的,像上面的搜索,还有其他的一些骚操作都没有。路漫漫其修远兮啊。
    花了很长时间写这篇博文记录一下整个开发过程,不断回顾和反思当初一开始没有写好的地方。挺有收获的。

    八、完整源代码下载

    下载地址

    你可能感兴趣的:(Web开发)