【项目需求】
1.查询数据库并将查询结果封装成标准json数据格式,传递到前端显示。
2.前端解析后台传递来的json数据并分页显示。
3.实现动态分页。
【涉及技术】
Mybatis Ajax jQuery HTML5 BootStrap
【开发环境】
IDE:Eclipse J2ee2019-06 WebServer:Apache Tomcat 9.0.13 DB:MySQL8 OS:Windows 10
【开发过程】
1.数据库准备
(1)创建名为test的数据库,建立一张名为student的学生信息表,表设计如下:
2.Mybatis搭建后端持久层
(1)导入依赖包:
(2)创建持久化类:Student
package com.pojo;
public class Student {
private int stuNum;
private String stuName,stuClass,stuSex,academy,profession;
public Student() {}
public Student(int stuNum, String stuName, String stuClass, String stuSex, String academy, String profession) {
this.stuNum = stuNum;
this.stuName = stuName;
this.stuClass = stuClass;
this.stuSex = stuSex;
this.academy = academy;
this.profession = profession;
}
public int getStuNum() {
return stuNum;
}
public void setStuNum(int stuNum) {
this.stuNum = stuNum;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuClass() {
return stuClass;
}
public void setStuClass(String stuClass) {
this.stuClass = stuClass;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public String getAcademy() {
return academy;
}
public void setAcademy(String academy) {
this.academy = academy;
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
@Override
public String toString() {
return "Student [stuNum=" + stuNum + ", stuName=" + stuName + ", stuClass=" + stuClass + ", stuSex=" + stuSex
+ ", academy=" + academy + ", profession=" + profession + "]";
}
}
(3)创建接口:StudentMapper.java
package com.mybatis;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.pojo.Student;
public interface StudentMapper {
//根据起始索引和查询行数查询
public List<Student> selectInPage(@Param("startindx")int start,@Param("mount")int mount) throws Exception;
}
(4)创建映射文件:StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.StudentMapper">
<resultMap type="com.pojo.Student" id="stumap">
<id property="stuNum" column="stu_Num"/>
<result property="stuName" column="stu_Name"/>
<result property="stuClass" column="stu_Class"/>
<result property="stuSex" column="stu_Sex"/>
<result property="academy" column="academy"/>
<result property="profession" column="profession"/>
</resultMap>
<select id="selectInPage" resultMap="stumap">
select * from student limit #{startindx},#{mount}
</select>
</mapper>
(5)创建Mybatis核心配置文件:mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用maybatis的日志控制 -->
<setting name="logImpl" value="LOG4J" />
<setting name="defaultExecutorType" value="BATCH" />
</settings>
<!-- 定义所有的数据库连接,并指定使用哪一个数据源 -->
<environments default="">
<environment id=""><!-- 定义数据源名称 -->
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC" />
<!-- 定义一个数据源,连接方式为数据库连接池方式 -->
<dataSource type="POOLED"><!-- 定义一个数据源,连接方式为数据库连接池方式 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=GMT%2B8" />
<property name="username" value="root" />
<property name="password" value="xlt123456" />
</dataSource>
</environment>
</environments>
<!-- 加载接口 -->
<mappers>
<mapper resource="com/mybatis/StudentMapper.xml"/>
</mappers>
</configuration>
(6)创建日志配置文件:log4j.properties
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] [%d{yyyy-MM-dd HH:mm:ss}] [%t] %c %L %m%n
log4j.rootLogger=DEBUG,console
(7)连通性测试。
创建一个测试类test.java,测试到目前为止,持久层是否能正常工作:
package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mybatis.StudentMapper;
import com.pojo.Student;
public class test {
private SqlSession session = null;
private SqlSessionFactory build;
private List<Student> stuList=new ArrayList<Student>();
@Before
public void init() {
InputStream is;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
build = new SqlSessionFactoryBuilder().build(is);
session = build.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
@After
public void destory() {
if (session != null) {
session.close();
}
}
@Test
public void teststupage() throws Exception {
StudentMapper studao=session.getMapper(StudentMapper.class);
stuList=studao.selectInPage(0, 15);
for(Student stu : stuList) {
System.out.println(stu);
}
}
}
使用jUnit Test运行teststupage()方法,控制台打印出下列信息,说明持久层工作正常:
3.控制层搭建。
(1)创建一个业务辅助类Service.java:
package com.service;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class Service {
SqlSession session=null;
InputStream is;
public Service() {
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
session= build.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
public SqlSession getSession() {
return session;
}
}
(2)创建一个servlet作为控制器StuControl.java:
4.前端开发。
(1)文件部署:
(2)文件编辑。(bootstrap.css是导入的)
主显示页面edit_StuInfo.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="keywords" content="">
<meta name="description" content="">
<script type="text/javascript" src="js/jquery.min.js"></script>
<title>编辑学生信息</title>
<link rel="stylesheet" href="css/bootstrap.css">
<link href="css/editinfopart.css" type="text/css" rel="stylesheet">
<link href="css/editStuInfo.css" type="text/css" rel="stylesheet">
<script src="js/jquery.min.js"></script>
</head>
<body>
<a href="index.jsp"><button type="button"
class="btn btn-mg btn-success">返回首页</button></a>
<h1 align="center">学生信息表</h1>
<div id="preblock">
学号:<input type="text" id="InputSNum" maxlength="8" placeholder="输入学号">
<button id="delbtu" class="btn btn-sg btn-danger">删除学生</button>
<a href="javascript:void(0)" class="addInfo_btn"><button
type="button" class="btn btn-sg btn-success" class="addInfo_btn">新增学生</button></a>
</div>
<br>
<table id="stuInfoTab" class="table table-bordered table-hover">
</table>
<div class="TabSet">
每页显示 <select size="1" id="Pagerow">
<option value="5" selected="selected">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>行,
<button class="btn btn-mg btn-success" id="prepage">上一页</button>
第<input type="text" id="PageNum" maxlength="3" value="1">页
<button class="btn btn-sg btn-success" id="sure">确定</button>
<button class="btn btn-mg btn-success" id="nextpage">下一页</button>
</div>
<!--新增学生信息遮罩层 -->
<div class="bgCover"></div>
<div class="addInfoPage">
<div class="addInfoPage-top">
<h2>新增学生信息</h2>
<span class="addInfoPage-close">X</span>
</div>
<form action="InsertStuInfo" method="post">
<div class="addInfoPage-content">
<div class="addInfoPage-content-right">
学号:<input type="text" class="stu_Num" name="stu_Num" maxlength="8"><br>
姓名:<input type="text" class="stu_Name" name="stu_Name"><br>
学院:<input type="text" class="academy" name="academy"><br>
专业:<input type="text" class="profession" name="profession"><br>
性别:<select size="1" class="stu_Sex" name="stu_Sex">
<option value="1" selected="selected">男</option>
<option value="2">女</option>
</select><span></span>
班级:<select size="1" class="stu_Class" name="stu_Class">
<option value="1" selected="selected">一班</option>
<option value="2">二班</option>
<option value="3">三班</option>
<option value="4">四班</option>
<option value="5">五班</option>
<option value="6">六班</option>
</select><br>
</div>
</div>
<div id="footbtn" class="addInfoPage-foot">
<input type="button" value="取消"
class="addInfoPage-cancel addInfoPage-close" /> <input
type="submit" value="确认" class="addInfoPage-ok" />
</div>
</form>
</div>
<!--编辑学生信息遮罩层 -->
<div class="editbgCover"></div>
<div class="editInfoPage">
<div class="editInfoPage-top">
<h2>编辑学生信息</h2>
<span class="editInfoPage-close">X</span>
</div>
<div class="editInfoPage-content">
<div class="editInfoPage-content-right">
学号:<input type="text" class="editstu_Num" name="stu_Num"><br>
姓名:<input type="text" class="editstu_Name" name="stu_Name" maxlength="4"><br>
性别:<input class="editstu_Sex" maxlength="1"><br>
学院:<input type="text" class="editacademy" name="academy" maxlength="10"><br>
专业:<input type="text" class="editprofession" name="profession" maxlength="9"><br>
班级:<input class="editstu_Class" maxlength="1"><br>
</div>
</div>
<div id="footbtn" class="editInfoPage-foot">
<input type="button" value="取消"
class="editInfoPage-cancel editInfoPage-close" />
<input type="button" value="确认" class="editInfoPage-ok" />
</div>
</div>
<script type="text/javascript" src="js/editInfopart.js"></script>
<script type="text/javascript" src="js/editStuInfo/editStuInfo.js"></script>
</body>
</html>
删除弹窗和新增弹窗的样式文件editinfopart.css编辑:
@charset "UTF-8";
* {
padding: 0px;
margin: 0px;
}
.addInfoPage {
display: none;
width: 500px;
min-height: 470px;
max-height: 750px;
height: 470px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
padding: 10px 25px 25px 25px;
z-index: 130;
border-radius: 10px;
background-color: #fff;
box-shadow: 0 3px 18px rgba(100, 0, 0, .5);
}
.addInfoPage-top {
height: 60px;
width: 100%;
border-bottom: 1px #E5E5E5 solid;
}
.addInfoPage-top h2 {
float: left;
display: black
}
.addInfoPage-top span {
float: right;
cursor: pointer;
font-weight: bold;
display: black;
font-size: 24px;
}
.addInfoPage-foot {
height: 20px;
line-height: 20px;
width: 100%;
border-top: 1px #E5E5E5 solid;
text-align: right;
}
.addInfoPage-cancel, .addInfoPage-ok {
padding: 8px 15px;
margin: 15px 5px;
border: none;
border-radius: 5px;
background-color: #337AB7;
color: #fff;
cursor: pointer;
}
.addInfoPage-cancel {
background-color: #FFF;
border: 1px #CECECE solid;
color: #000;
}
.addInfoPage-content {
height: 300px;
}
.addInfoPage-content-right {
width: 390px;
float: left;
padding-top: 20px;
padding-left: 20px;
text-align: center;
font-size: 24px;
line-height: 30px;
}
.addInfoPage-content-right input{
margin-bottom: 7px;
width:250px;
}
.bgCover {
display: none;
position: absolute;
z-index: 129;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .2);
}
/*编辑学生信息*/
.editInfoPage {
display: none;
width: 500px;
min-height: 470px;
max-height: 750px;
height: 470px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
padding: 10px 25px 25px 25px;
z-index:110;
border-radius: 10px;
background-color: #fff;
box-shadow: 0 3px 18px rgba(50, 0, 0, .5);
}
.editInfoPage-top {
height: 60px;
width: 100%;
border-bottom: 1px #E5E5E5 solid;
}
.editInfoPage-top h2 {
float: left;
display: black
}
.editInfoPage-top span {
float: right;
cursor: pointer;
font-weight: bold;
display: black;
font-size: 24px;
}
.editInfoPage-foot {
height: 20px;
line-height: 20px;
width: 100%;
border-top: 1px #E5E5E5 solid;
text-align: right;
}
.editInfoPage-cancel, .editInfoPage-ok {
padding: 8px 15px;
margin: 15px 5px;
border: none;
border-radius: 5px;
background-color: #337AB7;
color: #fff;
cursor: pointer;
}
.editInfoPage-cancel {
background-color: #FFF;
border: 1px #CECECE solid;
color: #000;
}
.editInfoPage-content {
height: 300px;
}
.editInfoPage-content-right {
width: 390px;
float: left;
padding-top: 20px;
padding-left: 20px;
text-align: center;
font-size: 24px;
line-height: 30px;
}
.editInfoPage-content-right input{
margin-bottom: 7px;
width:250px;
}
.editbgCover {
display: none;
position: absolute;
z-index:109;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .2);
}
主页面样式文件editStuInfo.css:
@charset "UTF-8";
* {
padding: 0px;
margin: 0px;
}
.table {
text-align: center;
}
.TabSet {
text-align: center;
}
.TabSet input {
width: 30px;
}
#footbtn {
text-align: center;
}
#preblock{
text-align: center;
font-weight: boder;
font-size:20px;
}
.editInfoPage-content-right span{
margin-left:50px;
}
分页显示控制文件editStuInfo.js:
$(function(){
//由于首先显示的第一页,故将前一页按钮设置为不可用。
$("#prepage").attr("disabled", true);
//每页几行
var Pagerow=$("#Pagerow").val();
//第几页
var PageNum=$("#PageNum").val();
//查询学生信息
queryStuInfo(Pagerow,PageNum);
//页数确定按钮
$("#sure").click(function () {
surepage();
});
//前一页按钮动作
$("#prepage").click(function () {
prepage();
});
//后一页按钮动作
$("#nextpage").click(function () {
nextpage();
});
//下拉菜单选择显示页数的动作
$('#Pagerow').on('change',function(){
surepage();
});
//输入学号删除的删除按钮
$("#delbtu").click(function(){
delStu();
});
//表格中每一行的删除按钮(动态加载的删除按钮,使用“事件委托”来处理其点击事件)
$("#stuInfoTab").on('click','#delStuInfo',function(){
var td = $(this).parent().parent().find("td");
var stuNumdata = td.eq(1).html();
if(confirm("该操作无法还原,是否继续?")){
delStuData(stuNumdata);
window.location.reload();
}else{
alert("已取消删除操作!");
}
});
});
/我是一条普通分隔线//
//刷新当前数据的确定按钮的核心函数
function surepage(){
if(Number($("#PageNum").val())>=2){
$("#prepage").removeAttr("disabled");
}else{
$("#prepage").attr("disabled", true);
}
//每页显示的行数
var Pagerow=$("#Pagerow").val();
//第几页
var PageNum=$("#PageNum").val();
queryStuInfo(Pagerow,PageNum);
}
//前一页操作按钮的控制函数
function prepage(){
if(Number($("#PageNum").val())<=2){
$("#prepage").attr("disabled", true);
}else{
$("#prepage").removeAttr("disabled");
}
var nowpage=Number($("#PageNum").val()-1);
var Pagerow=$("#Pagerow").val();
$("#PageNum").val(nowpage);
queryStuInfo(Pagerow,nowpage);
}
//下一页按钮控制函数
function nextpage(){
if(Number($("#PageNum").val())>=1){
$("#prepage").removeAttr("disabled");
}else{
$("#prepage").attr("disabled", true);
}
var nowpage=Number($("#PageNum").val())+1;
var Pagerow=$("#Pagerow").val();
$("#PageNum").val(nowpage);
queryStuInfo(Pagerow,nowpage);
}
//Ajax技术提交请求数据,查询json数据类型的学生信息,并将数据遍历显示到表格中。
function queryStuInfo(Pagerow,PageNum){
var index=PageNum*Pagerow-Pagerow;
//加载学生数据信息
$.ajax({
url: "StuControl",//请求servlet
data: { Pagerow:Pagerow,PageNum:index},//传递参数
type: "POST",
dataType: "json",
success: function(result){//响应成功后的,对响应数据进行处理
var table=$("#stuInfoTab");
table.empty();
table.append('<thead><tr><td>序号</td><td>学号</td><td>姓名</td><td>性别</td><td>学院</td><td>专业</td><td>班级</td><td>操作</td></tr></thead>');
var parseJSON = eval(result);
var ht = '';
for (var i = 0; i < parseJSON.length; i++) {
ht = ht + '<tr>';
ht = ht + '<td>' + (i + 1) + '</td>';
ht = ht + '<td>' + parseJSON[i].stuNum + '</td>';//注意属性来自于Student类,属性错误会导致显示结果为undefined
ht = ht + '<td>' + parseJSON[i].stuName + '</td>';
ht = ht + '<td>' + parseJSON[i].stuSex + '</td>';
ht = ht + '<td>' + parseJSON[i].academy + '</td>';
ht = ht + '<td>' + parseJSON[i].profession + '</td>';
ht = ht + '<td>' + parseJSON[i].stuClass + '</td>';
ht = ht + "<td><button class='btn btn-sg btn-info' id='editStuInfo'>编辑</button> <button class='btn btn-sg btn-danger' id='delStuInfo'>删除</button></td>";
ht = ht + '</tr>';
}
table.append(ht);
},
});
}
//输入学号进行删除的文本框对应的删除按钮的控制函数
function delStu(){
var delStuNum=$("#InputSNum").val();
var stuNum = $.trim(delStuNum);
if ((/^20([1-9])\d{5}$/).test(delStuNum)) {
if(confirm("该操作无法还原,是否继续?")){
$.ajax({
url: "DelStu",//删除操作请求的servlet
data: { stuNum:stuNum},
type: "POST",
datatype: "txt",
success: function(data){
alert(data);
},
});
}
}else{
alert("请输入合法学号如:20000000");
}
}
//表格中删除按钮的控制函数
function delStuData(stuNum){
$.ajax({
url: "DelStu",
data: { stuNum:stuNum},
type: "POST",
datatype: "txt",
success: function(data){
alert(data);
},
});
}
新增操作和修改操作控制文件:editInfopart.js
$(document).ready(function () {
//隐藏新增学生弹窗
$('.addInfoPage-close').click(function () {
$('.bgCover,.addInfoPage').hide();
});
//显示新增学生弹窗
$('.addInfo_btn').click(function () {
$('.bgCover,.addInfoPage').show();
});
//隐藏编辑学生弹窗
$(".editInfoPage").on('click','.editInfoPage-close',function(){
$('.editbgCover,.editInfoPage').hide();
});
//显示编辑学生弹窗
$("#stuInfoTab").on('click','#editStuInfo',function(){
$('.editbgCover,.editInfoPage').show();
//从表格中获得该行数据自动填入弹窗后仅设置学号输入框不可用
var td = $(this).parent().parent().find("td");
var stuNumdata = td.eq(1).html();
var stunume = td.eq(2).html();
var sex = td.eq(3).html();
var stuAcademy = td.eq(4).html();
var editprofession = td.eq(5).html();
var stuclass = td.eq(6).html();
$(".editstu_Num").val(stuNumdata);
$(".editstu_Name").val(stunume);
$(".editstu_Sex").val(sex);
$(".editacademy").val(stuAcademy);
$(".editprofession").val(editprofession);
$(".editstu_Class").val(stuclass);
$(".editstu_Num").attr('readonly',true);
});
//编辑完毕后 点击确定按钮时检查编辑内容的格式 正确则提交到后台
$(".editInfoPage-ok").click(function(){
var stunumb = $(".editstu_Num").val();
var stunume=$(".editstu_Name").val();
var sex=$(".editstu_Sex").val();
var stuAcademy=$(".editacademy").val();
var editprofession=$(".editprofession").val();
var stuclass= $(".editstu_Class").val();
if(stunume==''||sex==''||stuAcademy==''||editprofession==''||stuclass==''){
alert("输入的任何信息都不能为空!")
}else{
$.ajax({
url: "updateInfo",//请求修改学生信息的servlet
data: { stu_Num:stunumb,stu_Name:stunume,stu_Sex:sex,academy:stuAcademy,profession:editprofession,stu_Class:stuclass,},
type: "post",
datatype: "txt",
success: function(result){
alert(result);
window.location.reload();
},
});
}
});
})
【运行效果】
【项目源码下载】
链接:https://pan.baidu.com/s/1540uXQjLZ2z0UmOK3AYkVA
提取码:o7xg