目录
这是我的第一个JavaWeb的项目:学生信息管理系统
项目源码https://download.csdn.net/download/qq_63708623/85069872
看一下效果图
增添数据
删除数据
修改数据
分页
批量删除
其实还是有很多不足的,比如我本来是还想做一个条件查询的,结果老是报错,没有实现。后面我还会再做一次,会把这些功能全部实现。
题外话:
我是一个大一的学生,学的人工智能专业,上学期学完C语言,我就认识到了编程的魅力所在,并喜欢上了编程。这里介绍一下我的编程启蒙老师,这是他的主页,他真的是一个非常优秀的老师,我很崇拜他。上学期结束后的寒假,我就开始学习MySQL和一些前端的基本知识,又把Java过了一遍。然后寒假就结束了,下学期开始了,下学期的任务是学习Java。我还是比较喜欢泡论坛的,看到很多很多什么Maven,Mybatis,Spring,Vue……看不懂真的很难受,然后我就利用几乎所有的课余时间,来学习JavaWeb,用三周的时间刷完了黑马程序员的JavaWeb课程,收获还是很多的,就尝试着做了这样一个学生信息管理系统。
整体基本原理
在这个Web项目中,由前端提供页面供用户操作,前端会根据用户的操作,向Servlet发出相应的请求,Servlet接收到请求后,将发送过来的JSON字符串转换为Java对象,并给出响应,Java对象通过一系列传参,将参数传到Mybatis,再由Mybatis控制数据库进行增删改查的操作。Servlet给出响应的响应被前端接收到后,由前端做出相应的页面变化。整个系统的基本逻辑就是这样的。
源码分析
1.数据库
先来看一下数据库,数据库中id为主键,是不可重复并且自动增长的。
create table if not exists student
(
id int auto_increment,
studentId varchar(15) null,
name varchar(10) null,
gender char null,
classes varchar(10) null,
tel char(11) null,
addr varchar(30) null,
constraint student_id_uindex
unique (id)
);
2.mapper包
这个包包含了Mybatis的mapper代理,也就是StudentMapper类,里面包含了对数据库进行增删改查的几个基本方法,是操作数据库的类。
public interface StudentMapper {
@Select("select *from student")
List<Student> selcetAll();
void add(Student student);
void deleteById(int id);
void updateById(Student student);
void deleteByIds(@Param("ids") int[] ids);
@Select("select * from student limit #{begin} , #{size}")
List<Student> selectByPage(@Param("begin") int begin,@Param("size") int size);
@Select("select count(*) from student ")
int selectTotalCount();
}
其中,selectAll的SQL语句比较简单,用注解的方式来编写SQL语句,其他则是用到了StudentMapper的配置文件来编写SQL语句,也就是resource文件夹中的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.yit.mapper.StudentMapper">
<insert id="add">
insert into student (id,studentId,name,gender,classes,tel,addr)
values (null,#{studentId},#{name},#{gender},#{classes},#{tel},#{addr})
</insert>
<delete id="deleteById">
delete from student where id = #{id}
</delete>
<update id="updateById">
update student set studentId = #{studentId},name = #{name},gender = #{gender},classes = #{classes},tel = #{tel},addr = #{addr} where id = #{id}
</update>
<delete id="deleteByIds">
delete from student where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
</mapper>
2.pojo包
包里包含两个类:PageBean类和Student类。PageBean类中有两个成员变量,分别对应的是数据总数和当前页的数据,Student类与数据库中的每一列一一对应。
//分页查询的javabean
public class PageBean<T> {
//记录总数
private int totalCount;
//当前页数据
private List<T> rows;
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
public class Student {
private Integer id;
private String studentId;
private String name;
private String gender;
private String classes;
private String tel;
private String addr;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", studentId='" + studentId + '\'' +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", classes='" + classes + '\'' +
", tel='" + tel + '\'' +
", addr='" + addr + '\'' +
'}';
}
}
3.service包
Service包中包含有一个接口和一个实现类。StudentService中规定了实现类中应该实现的方法,将系统需要做的操作全都规定出来。StudentServiceImpl则是StudentService的实现类,里面包含了SqlSession的获取,mapper代理的获取,SQL语句的实现,事物的提交以及资源的释放,是用Java实现对数据库操作的重要环节。
public interface StudentService {
List<Student> selectAll();
void add(Student student);
void deleteById(int id);
void updateById(Student student);
void deleteByIds(int[] ids);
PageBean<Student> selectByPage(int currentPage,int pageSize);
}
public class StudentServiceImpl implements StudentService {
SqlSessionFactory sqlSessionFactory= SqlSessionFactoryUtils.getSqlSessionFactory();
public List<Student> selectAll() {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.selcetAll();
sqlSession.close();
return students;
}
public void add(Student student) {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.add(student);
sqlSession.commit();
sqlSession.close();
}
public void deleteById(int id) {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.deleteById(id);
sqlSession.commit();
sqlSession.close();
}
public void updateById(Student student) {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.updateById(student);
sqlSession.commit();
sqlSession.close();
}
public void deleteByIds(int[] ids) {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.deleteByIds(ids);
sqlSession.commit();
sqlSession.close();
}
public PageBean<Student> selectByPage(int currentPage, int pageSize) {
SqlSession sqlSession =sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int begin = (currentPage-1)*pageSize;
int size = pageSize;
List<Student> rows = mapper.selectByPage(begin,size);
int totalCount = mapper.selectTotalCount();
PageBean<Student> pageBean =new PageBean<>();
pageBean.setRows(rows);
pageBean.setTotalCount(totalCount);
sqlSession.close();
return pageBean;
}
}
4.utils包
utils包中只有一个类SqlSessionFactoryUtils,这个类中有一段静态代码块,只会加载一次,这个类的存在避免了SqlSessionFactory的多次加载,避免了资源的过度浪费。
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//静态代码块会随类的加载自动执行,且只执行一次
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
5.servlet包
servlet包包含了servlet层中的一些代码实现接收请求和发送响应的功能,将发送过来的JSON数据转换为Java对象,并通过输出流将响应发送给前端。这里的代码快较多,有需要的请下载源码
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
private StudentService studentService = new StudentServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BufferedReader reader = req.getReader();
String params = reader.readLine();//json字符串
//转为student对象
Student student = JSON.parseObject(params,Student.class);
//调用service添加
studentService.add(student);
resp.getWriter().write("success");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
6.resource文件夹
resource文件夹中包含了两个配置文件,一个是StudentMapper的配置文件,一个是Mybatis的配置文件。Mybatis配置文件是用来连接数据库的,有下载的可以根据MySQL的不同版本来修改Mybatis的配置文件。
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库的连接信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<mapper resource="com/yit/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
7.webapp文件夹
webapp中的文件就是前端的文件了,element-ui包含了element-ui的全部组件,用来设计样式。js文件夹中包含两个文件axios和vue。vue是前端的框架,element-ui和axios都要依靠vue才能实现。axios对原生的Ajax进行了封装,来简化书写。student.html就是前端页面的所有代码了,包含vue,Element-ui,axios。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学生信息管理系统</title>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
body {
margin: 0px;
padding: 0px;
}
#head {
background-color: #303133;
color: #f5f5f5;
height: 80px;
width: 100%;
margin: 0px;
text-align: center;
line-height: 80px;
font-size: 30px;
font-weight: bold;
letter-spacing: 10px;
}
#app {
margin-left: 10px;
margin-left: 10px;
}
</style>
</head>
<body>
<div id="head">
学生信息管理系统
</div>
<br>
<div id="app">
<!-- 按钮 -->
<el-row>
<el-button type="danger" @click="deleteByIds">批量删除</el-button>
<el-button type="primary" @click="dialogVisible = true">增添数据</el-button>
</el-row>
<!-- 对话框表单 -->
<el-dialog title="添加学生" :visible.sync="dialogVisible" width="30%">
<el-form ref="form" :model="student" label-width="80px">
<el-form-item label="学号">
<el-input v-model="student.studentId"placeholder="请输入学号"></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="student.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="性别">
<template>
<el-radio v-model="student.gender" label="男">男</el-radio>
<el-radio v-model="student.gender" label="女">女</el-radio>
</template>
</el-form-item>
<el-form-item label="班级">
<el-select v-model="student.classes" placeholder="请选择班级">
<el-option label="智2102-1" value="智2102-1"></el-option>
<el-option label="智2102-2" value="智2102-2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="student.tel" placeholder="请输入联系电话"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="student.addr" placeholder="请输入地址"></el-input>
</el-form-item>
<el-button type="primary" @click="addStudent">确认添加</el-button>
<el-button @click="dialogVisible = false">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!-- 表格 -->
<template>
<el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column type="index" width="50">
</el-table-column>
<el-table-column prop="studentId" label="学号" align="center" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center">
</el-table-column>
<el-table-column prop="gender" label="性别" width="50px" align="center">
</el-table-column>
<el-table-column prop="classes" label="班级" align="center">
</el-table-column>
<el-table-column prop="tel" label="联系电话" align="center">
</el-table-column>
<el-table-column prop="addr" label="地址" align="center">
</el-table-column>
<el-table-column prop="id" label="ID" v-if="false">
</el-table-column>
<el-table-column prop="addr" label="操作" align="center">
<template slot-scope="scope">
<el-button @click="dialogVisible1=true;getupdate(scope.row)" type="primary" round>编辑</el-button>
<el-button @click="deleteById(scope.row.id)" type="danger" round>删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<el-dialog title="编辑信息" :visible.sync="dialogVisible1" width="30%">
<el-form ref="form" :model="edtStudent" label-width="80px">
<el-form-item label="学号">
<el-input v-model="edtStudent.studentId"v-model="ruleForm.name" placeholder=edtStudent.studentId></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="edtStudent.name" placeholder=edtStudent.name></el-input>
</el-form-item>
<el-form-item label="性别">
<template>
<el-radio v-model="edtStudent.gender" label="男">男</el-radio>
<el-radio v-model="edtStudent.gender" label="女">女</el-radio>
</template>
</el-form-item>
<el-form-item label="班级">
<el-select v-model="edtStudent.classes" placeholder=edtStudent.classes>
<el-option label="智2102-1" value="智2102-1"></el-option>
<el-option label="智2102-2" value="智2102-2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="edtStudent.tel" placeholder=edtStudent.tel></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="edtStudent.addr" placeholder=edtStudent.addr></el-input>
</el-form-item>
<el-button type="primary" @click="updateById">确认提交</el-button>
<el-button @click="dialogVisible1 = false">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
:page-sizes="[5, 10, 15, 20]" :page-size="5" layout="total, sizes, prev, pager, next, jumper"
:total="totalCount">
</el-pagination>
</div>
<script src="js/vue.js"></script>
<script src="element-ui\lib\index.js"></script>
<script src="js/axios-0.18.0.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
<script>
new Vue({
el: "#app",
mounted() {
this.selectAll();
},
methods: {
deleteByIds() {
this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
console.log(this.multipleSelection);
for (let i = 0; i < this.multipleSelection.length; i++) {
let selectionElement = this.multipleSelection[i];
this.selectedIds[i] = selectionElement.id;
}
var _this = this;
//发送ajsx请求,添加数据
axios({
method: "post",
url: "http://localhost:8080/StudentsInformation/deleteByIdsServlet",
data: _this.selectedIds
}).then(function (resp) {
if (resp.data == "success") {
//添加成功
//关闭窗口
_this.dialogVisible = false;
//重新加载数据
_this.selectAll();
_this.$message({
message: '删除成功',
type: 'success'
})
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
updateById() {
var _this = this;
axios({
method: "post",
url: "http://localhost:8080/StudentsInformation/updateByIdServlet",
data: _this.edtStudent
}).then(function (resp) {
if (resp.data == "success") {
//添加成功
//关闭窗口
_this.dialogVisible1 = false;
//重新加载数据
_this.selectAll();
_this.$message({
message: '修改成功',
type: 'success'
})
}
})
},
getupdate(row) {
this.edtStudent.id = row.id;
this.edtStudent.studentId = row.studentId;
this.edtStudent.name = row.name;
this.edtStudent.gender = row.gender;
this.edtStudent.classes = row.classes;
this.edtStudent.tel = row.tel;
this.edtStudent.addr = row.addr;
},
deleteById(id) {
this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var _this = this;
_this.student.id = id;
axios({
method: "post",
url: "http://localhost:8080/StudentsInformation/deleteByIdServlet",
data: _this.student
}).then(
function (resp) {
if (resp.data == "success") {
//添加成功
//关闭窗口
_this.dialogVisible = false;
//重新加载数据
_this.selectAll();
_this.$message({
message: '删除成功',
type: 'success'
})
}
}
)
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
//查询所有数据
selectAll() {
var _this = this;
axios({
method: "get",
url: "http://localhost:8080/StudentsInformation/selectByPageServlet?currentPage=" + _this.currentPage + "&pageSize=" + _this.pageSize,
data: _this.student
}).then(function (resp) {
_this.tableData = resp.data.rows;
_this.totalCount = resp.data.totalCount;
})
},
tableRowClassName({ row, rowIndex }) {
if (rowIndex === 1) {
return 'warning-row';
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
addStudent() {
var _this = this;
//发送ajsx请求,添加数据
axios({
method: "post",
url: "http://localhost:8080/StudentsInformation/addServlet",
data: _this.student
}).then(function (resp) {
if (resp.data == "success") {
//添加成功
//关闭窗口
_this.dialogVisible = false;
//重新加载数据
_this.selectAll();
_this.$message({
message: '添加成功',
type: 'success'
})
}
})
},
handleSizeChange(val) {
this.pageSize = val;
this.selectAll();
},
handleCurrentChange(val) {
this.currentPage = val;
this.selectAll();
}
},
data() {
return {
pageSize: 5,
totalCount: 100,
currentPage: 1,
dialogVisible: false,
dialogVisible1: false,
student: {
id: null,
studentId: '',
name: '',
gender: '',
classes: '',
tel: '',
addr: ''
},
edtStudent: {
id: null,
studentId: '',
name: '',
gender: '',
classes: '',
tel: '',
addr: ''
},
selectedIds: [],
multipleSelection: [],
tableData: [{
}]
}
}
}
)
</script>
</body>
</html>
7.pom.xml
这是Maven的配置文件,里面包含了整个项目所需要的所有jar包,比如MySQL的驱动,servlet,fastjson等等
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>StudentsInformation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--
Tomcat插件
-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>