JavaWeb项目实战

本文详细介绍了使用JavaWeb进行项目实战的过程,涵盖了从创建数据库、填充测试数据、页面转换到JSP、实体类创建、DAO及ServiceImpl实现、Servlet处理逻辑、分页模糊查询、权限管理等多个方面。涉及到的工具有Druid、DBUtils、JSP、Servlet、AJAX等,同时讨论了代码优化,如使用枚举保存学生状态、过滤器处理乱码、多请求合并到一个Servlet等。
摘要由CSDN通过智能技术生成

没有任何优化的代码 

数据库

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主键 

(2)点击修改之后,就会跳转到/Educational/student/findbyid

(3)FindByIdServlet中处理查询的方法,是由StudentServiceImpl调取StudentDao的代码获取的

(4)StudentDao中定义了根据主键查询所有信息的方法

(5)StudentDaoImpl中实现了“根据主键查询所有信息的方法”,这里主要注意columnLabel(列标签)中的值需要和数据库中的列名相同。

(6)当FindByIdServlet获取到了数据库学生和年级

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值