没有任何优化的代码
数据库
1创建数据库school,并且使用该数据库
2创建登陆用户的表格
3创建年级的表格
4创建学员表格
填写测试数据
1给用户表添加数据
2给年级表填写数据
3学生表添加数据
insert into student values(1,'张三','stu1001',1,'13719201111','11111111@qq.com','北京','XX区XX镇','物理','2209121102911111','党员','2020-01-01',1,'优秀学员1',1)(2,'李四','stu1002',1,'13719203830','3432312@qq.com','上海','XX区XX镇','化学','22091211029121212','党员','2020-05-03',1,'优秀学员2',1),(3,'王五','stu1003',1,'13719201111','3333333@qq.com','杭州','XX区XX镇','生物','32091211029121212','党员','2020-06-03',1,'优秀学员3',2),(4,'赵六','stu1004',1,'13719204444','4444444@qq.com','四川','XX区XX镇','英语','44444411029121212','群众','2020-04-04',1,'优秀学员4',2),(5,'李雷','stu1005',1,'13719205555','55555555@qq.com','湖南','XX区XX镇','医学','220912110295555555','群众','2020-05-05',1,'优秀学员5',3),(6,'韩梅梅','stu1006',0,'1371920666','6666666@qq.com','武汉','XX区XX镇','政治','220912110291666666','群众','2020-06-06',1,'优秀学员6',3),(7,'翠花','stu1007',0,'13719207777','7777777@qq.com','天津','XX区XX镇','计算机','22091211029177777','党员','2020-07-07',0,'优秀学员7',3);
把html页面修改为jsp页面
1在html中添加page指令
2将html的后缀修改为jsp
修改之前的
修改之后的
实体类 bean包
bean包:属性,封装方法,无参构造,全参构造;表名=类名,列名=属性名
1多表之间关系分析
①用户表和年级表、学生表之间没有关系
②年级表和学生表之间是一对多的关系,一个年级对应多个学生
2创建年级(班级)列表的实体
package com.yhp.bean;
import java.util.List;
/**
* 年级表的实体类
* 表名=类名,列名=属性名
* 尽量使用包装类int->Integer
*/
public class Grade {
private Integer gradeId;//年级编号
private String gradeName;//年级名称
//年级和学生之间是一对多的关系:一个年级包含多个学生
private List<Student> studentList;
public Integer getGradeId() {
return gradeId;
}
public void setGradeId(Integer gradeId) {
this.gradeId = gradeId;
}
public String getGradeName() {
return gradeName;
}
public void setGradeName(String gradeName) {
this.gradeName = gradeName;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
3创建学生信息实体类
package com.yhp.bean;
import java.util.Date;
/**
* 学生信息实体类
*/
public class Student {
private Integer stuId;//学生id,主键自增
private String stuName;//学生姓名
private String stuNo;//学号
private Integer sex;//性别0女1男
private String phone;//联系电话
private String email;//邮箱
private String registered;//户口
private String address;//住址
private String profession;//专业
private String idNumber;//身份证号
private String politics;//政治面貌
private Date regdate;//登记时间
private Integer state;//状态0在校1删除
private String introduction;//简介
private Integer gid;//班级编号
//年级和学生之间是一对多的关系:一个学生对应一个年级
private Grade grade;
//以上所有成员对象的get和set方法
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRegistered() {
return registered;
}
public void setRegistered(String registered) {
this.registered = registered;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
public String getPolitics() {
return politics;
}
public void setPolitics(String politics) {
this.politics = politics;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
public Integer getGid() {
return gid;
}
public void setGid(Integer gid) {
this.gid = gid;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
4 创建登陆用户的实体类
package com.yhp.bean;
//用户信息实体类
//多表关系分析:用户表和其他表没有关系
public class Users {
private Integer userId;//用户id
private String loginName;//登陆账号
private String passWord;//密码
private String realName;//真实姓名
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
}
dao包:主要是操作数据库的
①定义操作方法的接口,命名:实体类名+Dao
②Dbutils(属性文件,*.properties):连接数据库的工具类
1德鲁伊
注意:这里的DBUtils使用的是Druid技术,需要导入相关的jar包和数据文件
package com.yhp.dao;
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.*;
import java.util.List;
import java.util.ResourceBundle;
public class DBUtils {
//1.定义变量
private Connection connection;
private PreparedStatement pps;
protected ResultSet resultSet;
private int count;//存储收影响的行数
private static String userName;
private static String userPass;
private static String url;
private static String dirverName;
//德鲁伊
private static DruidDataSource dataSource=new DruidDataSource();
//2.加载驱动
static {
//德鲁伊
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
dirverName = bundle.getString("driverClassName");
url = bundle.getString("url");
userName = bundle.getString("username");
userPass = bundle.getString("password");
dataSource.setUsername(userName);
dataSource.setPassword(userPass);
dataSource.setUrl(url);
dataSource.setDriverClassName(dirverName);
// dataSource.setInitialSize(20);
}
//3.获得链接
protected Connection getConnection(){
try {
connection=dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//4.得到预状态通道
protected PreparedStatement getPps(String sql){
try {
pps= getConnection().prepareStatement(sql);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return pps;
}
//5.绑定参数 List保存的是给占位符所赋的值
protected void param(List list){
if(list!=null&&list.size()>0){
for (int i=0;i<list.size();i++) {
try {
pps.setObject(i+1,list.get(i));
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
//6.执行操作(增删改+查询)
protected int update(String sql,List list){
getPps(sql);
param(list);
try {
count= pps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return count;
}
//7.查询
protected ResultSet query(String sql,List list){
getPps(sql);
param(list);
try {
resultSet= pps.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return resultSet;
}
//8.关闭资源
protected void closeAll(){
try {
if (connection != null) {
connection.close();
}
if (pps != null) {
pps.close();
}
if (resultSet != null) {
resultSet.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2德鲁伊的配置文件
数据文件放到src目录下,注意jdbc.properties中的路径数据要修改
url=jdbc:mysql://localhost:3306/school?serverTimezone=UTC
username=root
password=XXXXXX
driverClassName=com.mysql.cj.jdbc.Driver
initialSize=5
maxActive=10
minIdle=5
maxWait=3000
3 jar包放到WEB-INF目录下的lib目录
impl包:实现接口,继承Dbutils类
命名:接口名+Impl
service.impl:主要是调取dao包的
service定义的是接口,接口中的方法和dao层接口中的方法一致
impl:这层的实现类主要负责调取dao层方法
service层的意义:service层是一个业务层,如果你的功能点的业务比较复杂,那么我们可以把业务逻辑都封装到这里进行包装,相当于进行一个准备工作
servlet:需要结合具体的功能点和需求去定义
在servlet中需要做的三件事
①接收参数
②调取service层的方法,service又在调取dao层的方法
③根据结果跳转页面
核心:jsp页面负责发送请求和展示数据
客户端:可以是浏览器、服务器、微信小程序
比如我想在淘宝上查找商品,那就是客户端发送请求,servlet调取service,service调取DAO,DAO,调取数据库,数据库将对应的消息依次返回,最后servlet获取到了数据,然后展示给客户端
代码的步骤:
1 先看jsp->2 jsp中指定Servlet地址->3 写对应的Servlet代码->4 Servelt主要做三件事:①接收参数、②调取service中对应的方法、③跳转到指定的页面(可以是前端页面,可以是有指定功能的Servlet页面,然后由该Servlet类跳转到前端页面)->5 因为Servlet中需要调用service中的方法,所以需要写对应的service接口中的抽象方法->6 写对应的Dao层的抽象方法->7Dao层的实现类实现Dao层的接口->8service层的实现类,实现service的接口(其中抽象方法的实现,是调取Dao层的实现类)
1. 登陆功能
(1)先看login.jsp页面的内容
①login.jsp的数据怎么发送过来
用户名的name是TxtUserName,密码的name是TxtPassword
②设置form的地址和method
(2)创建LoginServlet
servlet中主要做三件事1接收参数2调取service3跳转页面
1接收参数
用到了login.jsp的数据发送
2调取service
①需要在之前创建的UsersService接口中创建登陆的方法
②在UsersServiceImpl实现类中实现UsersService中的登陆方法,调取Dao层的UsersDao。
③UsersDao接口中定义登陆方法
④UsersDaoImpl中,需要进行调取数据库的操作
继承DBUtils(德鲁伊),实现UsersDao
⑤将2调取service和3跳转页面的代码内容补全
注意:代码运行时,浏览器页面出现问题,IDEA控制台中没有报错,可以按F12,点击Network,点击Response,查看
2退出功能
将session值清空掉即可
(1)书写head.jsp中的内容
(2)新建OutServlet
(3)如何验证是否退出成功
直接访问index.jsp,当前页面没有显示用户信息,就说明退出成功了
3学员列表展示
(1)首先修改left.jsp(学员信息展示的页面)当中的代码
把请求的地址修改为servlet的地址
(2)创建GetStudentServlet,它的地址就是上图中的Educational/student/getStudentList
①service
②serviceImpl
③dao
④daoImpl:进行数据库操作,调取数据库中存的数据
(3)修改之前的list.html为list.jsp,并且将其中展示的固定数据修改为真实数据展示
①引入JSPL标签库
②将需要循环展示的真实数据,用<c:forEach></c:forEach>包裹
(4)结果:
4 模糊查询实现
(1)首先看list.jsp
①需要把button(普通按钮)改为submit(提交按钮)
②需要把学生名称、学生学号和性别加上name属性,方便后续获取值
③在性别的请选择、男和女选项中加上value属性
④添加表单数据提交的请求名form的action属性
(2)修改之前的GetStudentServlet类
①类中之前是没有获取参数的,现在就需要把刚刚的参数添加上
②类之前调取service方法,是不需要穿参数的,现在则需要把获取到的参数进行传递,这就需要修改StudentService,StudentServiceImpl,StudentDao,StudentDaoImpl
③第2条修改的目的就是为了StudentDaoImpl类,进行数据库查询
④其中涉及到了,
1String类型强制转换为Integer(Integer.parseInt(sex))
2如果String为null,强制转换为Integer报错的处理(使用三目运算符,如果String为null,那String就等于-1: String == null? -1:Integer.parseInt(sex))
3String 和StringBuffer(两者区别:String是固定长度,StringBuffer可以进行动态的内存更新)
4StringBuffer转换为String类型(StringBuffer.toString)
5关于查询一次后,查询的内容自动删除的问题(这是因为每次查询后,会自动刷新一次页面,想要不丢失查询内容,需要对查询内容进行保存,并且需要在list.jsp页面中对保存的内容进行调取)
(3) 代码
①list.jsp
②GetStudentServlet
③StudentService这里比之前多了三个需要传入的参数
④StudentServiceImpl,实现StudentService,调取Dao层的StudentDao
⑤Dao层的StudentDao
⑥StudentDaoImpl,实现了StudentDao,里面跟之前不同的是查找sql的语句不同,这里使用的是:StringBuffer(String长度是固定的生成了就不能变,但是StringBuffer是可以不断添加的)
5分页功能
当用户点击首页、尾页、上一页、下一页以及中间的页码的时候,可以看到对应的信息
(1)修改相关的jsp页面(list.jsp)
给相关的按钮添加上要提交的页面连接(GetStudentServlet的地址)
(2)点击首页的功能实现
①修改GetStudentServlet中,将获取每页页码值和显示条数添加进去
②当获取了页码值和显示条数之后,就需要将他们传递给service层
③对应的GetStudentServlet和Student ServiceImpl、Dao层的接口和实现类也要进行响应的修改
④StudentDaoImpl的修改:sql语句添加分页条件
⑤GetStudentServlet的修改,需要把之前的调用StudentService进行页码值和每页条数的添加
(3)点击上一页,在jsp页面设置
①前台的页码值在后台获取
变量名为pageIndex
index是当前页面的值,用三目运算符进行值的判断
注意:这里的pageIndex只是一个变量的名字,他需要和后台接收数据的一样即可
②后台的页码值在前台获取
变量名为index
③ 前台使用el表达式对index进行获取
上一页,当前页码值-1,然后判断值是否小于等于1,如果小于1则页码值为1,如果页码值大于1,则正常的页码值-1
(4)下一页
①需要求出总页数(这里总页数命名为totalPages)
②GetStudentServlet中求出总页数
总页数=总条数/每页显示的条数(每页显示的条数是固定的5条)
③那么就需要求出总条数
需要在StudentService接口中定义一个获取总条数的方法
这个方法再复制到Dao层
然后StudentDaoImpl实现StudentDao的这个方法
然后StudentServletImpl实现StudentService接口
由GetStudentServlet调用
④GetStudentServlet中就可以存储分页数据(当前页数、每页显示条数、总条数、总页数)
⑤求出总页数(这里总页数命名为totalPages)
(5)尾页按钮
直接获取总页数即可
(6)目前的分页查询就做好了,但是还有一个模糊查询的功能,在跳转页码后,模糊查询的数据就丢失了
这是因为,上面的jsp代码中,只拼接了页码值,没有拼接模糊查询的条件,当点击上一页后,只会向后台传一个页码的数据,但是模糊查询的数据就被丢掉了
注意:拼接第一个数据加?,后面的数据用&连接
6新增
当用户点击“新增学生”按钮,会跳转到新增页面
填写完信息后,点击添加后,页面会跳回到学生管理页面
并且数据也会在学生管理页面展示
6-1新增-1:动态获取班级列表
(1)打开list.jsp页面,找到新增学生按钮
本来点击新增学生按钮之后,页面直接跳转到add.jsp,现在我们需要点击新增学生之后,跳转到GradeListServlet
①GradeListServlet目前还没有参数需要接收,需要一个查询所有年级列表的方法
(2)修改add.jsp页面的关于班级信息的静态数据换成动态数据
原本的静态数据
(3)修改为动态数据的步骤
①首先加上JSPL标签库
②在GradeService和GradeDao,这两个接口中定义查询年级列表的方法,并返回List集合
③GradeServiceImpl实现GradeService接口
④GradeDaoImpl实现GradeDao接口
⑤GradeListServlet
⑥add.jsp获取servlet层的结果
g.gradeId是年级的id,之后后台获取前台列表中数据
g.gradeName是显示年级的名字的:前台获取后台中存储的年级信息
6-2新增2:表单提交
(1)修改表单提交的地址
将其修改为处理其逻辑的servlet的地址
(2)创建Servlet
当数据成功存储到数据库后,页面会跳转到查询班级的Servlet(GradeListServlet),由Servlet查询到结果后转发到list.jsp页面
(3)StudentDaoImpl中的代码,用来将数据存储到sql中
7修改学生信息:主键查询
当用户点击修改按钮的时候,会展示学生的信息,班级信息应该动态获取,并且默认选中之前设置的
(1)找到list.jsp中的修改按钮,修改请求地址
修改后:后面拼接的sid=${stu.stuId}可以让后台的代码获取id主键