考勤登记管理系统

8 篇文章 0 订阅
3 篇文章 0 订阅

jsp+servlet+javabean综合练习题《考勤登记管理系统》

一、语言和环境要求

实现语言

Java

环境要求

JDK1.8、IntelliJ IDEA 2020、Tomcat9、MySql8、jQuery-3.6.0.js


二、功能要求

使用 JSP+Servlet 实现考勤登记管理系统,MySql 作为后台数据库,其中查询考勤记录和考勤登记功能实现具体要求如下:

1、打开首页页面,访问查询考勤记录信息的 Servlet,将查询结果在考勤记录信息页面进行展示,并按考勤日期降序排列,查询列表使用样式实现隔行变色效果,使用样式对标题文字效果进行控制。程序运行界面如图1所示:

图1:

在这里插入图片描述

2、点击“考勤登记”进入考勤登记页面,如图2所示,需要手工输入员工姓名、所属部门、考勤日期(符合格式要求),考勤状态为下拉列表选择,下拉列表的值为“请选择考勤类型、正常、迟到、早退、休假、外出”,所有项都为必填项。使用样式对标题文字效果及背景色进行控制。

图2:

在这里插入图片描述

3、登记考勤信息时,要求使用 jQuery 对输入项进行数据验证,如果输入信息有一项为空则不允许提交,并给出相应提示信息。同时对考勤日期格式进行验证。如图-3、图-4 所示。

图3:

在这里插入图片描述

图4:

在这里插入图片描述

4、提交考勤记录至登记考勤记录的 Servlet,如登记成功则给出成功提示,如图-5 所示,点击确定后跳转至显示考勤记录信息页面,并显示最新的考勤记录信息,如图-6 所示;如信息添加失败则给出失败提示,点击确定后返回考勤登记页面,重新登记。

图5:

在这里插入图片描述

图6:

在这里插入图片描述

三、 数据库设计

数据库表名称及要求:

在这里插入图片描述

四、具体要求及推荐实现步骤

1、 建立数据表 ATTENCE ,添加测试数据(至少 3 条)

2、 使用 IntelliJ IDEA 创建 web 项目 Attence,导入数据库驱动包,在源文件夹中创建 4 个包:entity 包用于存放实体类,dao 包用于存放数据访问类,service包用于存放业务访问类 servlet 包用于存放Servlet 类

3、 创建实体类 Attence.java,编写各属性的 getter/setter 方法

4、 创建 DAO 基类:BaseDao.java,包含基本数据库资源的获取、释放操作。注意释放资源时的先后顺序

5、 创建 DAO 类:AttenceDao.java

	1)、编写查询方法,获取全部考勤记录信息并按考勤时间降序排列
	2)、编写添加方法,添加考勤记录的信息

6、创建考勤记录信息查询页面

​	1)、按照图-1 所示进行页面设计,并使用 CSS 进行美化(标题、背景色、隔行变色等)
​	2)、点击“考勤登记”链接后打开考勤记录登记页面如图-2 所示

7、 创建查询考勤记录信息的 Servlet

	1)、调用 DAO 类的方法,正确查询出结果集后返回考勤记录信息查询页面,正确显示结果集,如图-1 所示。

8、创建考勤记录登记页面

​	1)、按照图-2 进行页面设计,并使用 CSS 进行美化(标题、背景色等)
​	2)、编写 jQuery 编写脚本对输入项进行非空验证,以及考勤日期格式验证

C、页面使用 post 方式将考勤记录登记表单数据提交到 Servlet 进行处理

9、创建登记考勤记录的 Servlet

​	1)、获取表单数据,对数据进行相应的中文乱码处理
​	2)、调用 DAO 方法添加申请信息,并根据添加结果显示相应的提示和跳转的页面

10、调试运行成功后导出 SQL 语句,其中包括创建表结构、主键和标识列、初始化数据,生成 SQL 文件与代码文件一同提交。若无数据库脚本提交,数据库项不得分


五、注意事项

1、 请注意界面美观,控件摆放整齐;

2、 请注意代码的书写、命名符合规范,在代码中添加必要的注释;

3、 请注意操作数据库时进行必要的异常处理。



六、功能实现

6.1创库、创表、添加数据

-- ----------------------------
-- 1、创库
-- ----------------------------
DROP TABLE IF EXISTS `attence`;
-- ----------------------------
-- 2、创表
-- ----------------------------
CREATE TABLE `attence`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键,自增长',
  `empname` varchar(30) NOT NULL COMMENT '员工姓名',
  `dept` varchar(30)  NOT NULL COMMENT '部门',
  `chkdate` date NOT NULL COMMENT '考勤日期',
  `status` int(0) NOT NULL COMMENT '考勤类型(1-正常 2-迟到 3-早退 4-休假 5-外出)',
  PRIMARY KEY (`id`) USING BTREE
)  COMMENT = '考勤记录信息';

-- ----------------------------
-- 3、添加数据
-- ----------------------------
INSERT INTO `attence` VALUES (1, '王晓', '行政部', '2022-06-12', 1);
INSERT INTO `attence` VALUES (2, '张玉', '财务部', '2022-05-30', 1);
INSERT INTO `attence` VALUES (3, '李欢欢', '行政部', '2022-07-10', 2);
INSERT INTO `attence` VALUES (4, '王晓义', '公关部', '2022-07-05', 3);

6.2创建Maven WebApp项目

创建web项目按照要求搭建好项目的结构

在这里插入图片描述

6.3添加Maven依赖

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

6.3创建数据源配置文件

src/main目录下创建resources文件夹,并在文件加重添加database.properties文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/attence?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username=root
password=root

6.4创建工具类DBHelper

DBHelper工具类主要用于:获取数据库连接和关闭资源,该类运用了单例模式

package com.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * 工具类:获取数据库连接和关闭资源
 */
public class DBHelper {
    private static DBHelper dbHelper;

    //私有化构造
    private DBHelper() {}

    private static String DRIVER;
    private static String URL;
    private static String USERNAME;
    private static String PWD;

    static {
        try {
            Properties properties = new Properties();
            //读取属性文件
            InputStream in = DBHelper.class.getClassLoader().getResourceAsStream("database.properties");
            //加载属性文件
            properties.load(in);
            //赋值
            DRIVER = properties.getProperty("driver");
            URL = properties.getProperty("url");
            USERNAME = properties.getProperty("username");
            PWD = properties.getProperty("password");

            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                throw new RuntimeException("加载驱动类失败!");
            }

        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("加载配置文件失败!");
        }
    }

    /**
     * 静态内部类
     */
    public static class SingDBHelper {
        private final static DBHelper DBHELPER = new DBHelper();
    }

    /**
     * 获取DBHelper实例对象方法
     *
     * @return
     */
    public static DBHelper getInstance() {
        dbHelper = SingDBHelper.DBHELPER;
        return dbHelper;
    }

    /**
     * 获取连接对象
     *
     * @return
     */
    public Connection getConnection() {
        try {
            return DriverManager.getConnection(URL, USERNAME, PWD);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("建立数据库连接通道失败!");
        }
    }

    /**
     * 关闭资源
     *
     * @param conn 连接对象
     * @param stmt 执行对象
     * @param rs   结果集
     */
    public void closeAll(Connection conn, Statement stmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

6.5创建工具类BaseDao

BaseDao为数据库操作泛型工具类,该类中定义了操作数据库增删改查的方法,其中查询方法采用反射的机制实现。

注意: 在使用过程中如果你的实体类属性和数据库表中的字段名不一致将会导致反射异常。

package com.dao;

import com.utils.DBHelper;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库操作工具类
 * 查询单个对象或列表数据时,实体类属性和数据库表中的字段名必须一致,否则将会导致反射异常
 * @param <T>
 */
public class BaseDao<T> {
    
    private DBHelper db = DBHelper.getInstance();//单例:每次调用都返回相同的对象
    
    private Class clazz;

    public BaseDao() {
        Type type = this.getClass().getGenericSuperclass();//当前堆内存中实际运行的对象的父类的泛型类型
        ParameterizedType parameterizedType = (ParameterizedType) type;//强转
        Type[] types = parameterizedType.getActualTypeArguments();//获取父类泛型数组
        clazz = (Class) types[0];//赋值泛型中所设类型
    }

    /**
     * 修改操作
     *
     * @param sql    要执行的修改sql语句
     * @param params
     */
    public int update(String sql, Object... params) {//可变参数就是数组,数组索引从0开始,sql中索引从1开始
        int result = 0;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        try {
            stmt = conn.prepareStatement(sql);
           if (params!=null&&params.length>0){
               for (int i = 0; i < params.length; i++) {
                   stmt.setObject(i + 1, params[i]);
               }
           }
            result = stmt.executeUpdate();
        } catch (SQLException e) {
            result=-1;
            e.printStackTrace();
            throw new RuntimeException(clazz.getClass() + "执行变更的SQL语句错误" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, null);
        }
        return result;
    }

    /**
     * 查询结果为单条记录,封装成Map类型
     *
     * @param sql    查询sql语句
     * @param params
     * @return java.util.Map/null
     */
    public Map<String, Object> queryForMap(String sql, Object... params) {
        Map<String, Object> resultMap = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    stmt.setObject(i + 1, params[i]);//预处理赋值
                }
            }
            rs = stmt.executeQuery();//获取结果集对象
            if (rs.next()) {
                resultMap = new HashMap<>();//创造存储的容器
                ResultSetMetaData rsmd = rs.getMetaData();//获取元信息
                int columnCount = rsmd.getColumnCount();
                //存储数据
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = rsmd.getColumnLabel(i);
                    Object columnValue = rs.getObject(columnName);
                    resultMap.put(columnName, columnValue);
                }
            }
            return resultMap;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(clazz.getClass() + "queryForMap,执行查询的SQL语句错误" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }

    /**
     * 封装多条记录
     *
     * @param sql    查询sql语句
     * @param params 条件参数
     * @return List<Map < String, Object>>
     */
    public List<Map<String, Object>> queryForList(String sql, Object... params) {
        List<Map<String, Object>> resultList = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    stmt.setObject(i + 1, params[i]);//预处理赋值
                }
            }
            rs = stmt.executeQuery();//获取结果集对象
            if (rs.next()) {
                resultList = new ArrayList<>();//创造存储的容器
                ResultSetMetaData rsmd = rs.getMetaData();//获取元信息
                int columnCount = rsmd.getColumnCount();
                do {
                    Map<String, Object> recordMap = new HashMap<>();
                    //存储数据
                    for (int i = 1; i <= columnCount; i++) {
                        String columnName = rsmd.getColumnLabel(i);
                        Object columnValue = rs.getObject(columnName);
                        recordMap.put(columnName, columnValue);
                    }
                    //将每条记录存储list
                    resultList.add(recordMap);
                } while (rs.next());
            }

            return resultList;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(clazz.getClass() + "queryForMap,执行查询的SQL语句错误" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }

    /**
     * 返回单条记录的自定义对象
     *
     * @param sql    查询sql语句
     * @param params 条件参数
     * @return
     */
    public T queryForRecordObject(String sql, Object... params) {
        T resultDate = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                stmt.setObject(i + 1, params[i]);//预处理赋值
            }
            rs = stmt.executeQuery();//获取结果集对象
            if (rs.next()) {
                resultDate = (T) clazz.newInstance();
                ResultSetMetaData rsmd = rs.getMetaData();//获取元信息
                int columnCount = rsmd.getColumnCount();
                //存储数据
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = rsmd.getColumnLabel(i);
                    Field field = getFieldObject(columnName);
                    if (field != null) {
                        field.setAccessible(true);//破坏封装性,允许访问
                        Object colunmValue = rs.getObject(columnName);
                        field.set(resultDate, colunmValue);
                    }
                }
            }

            return resultDate;

        } catch (SQLException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(clazz.getClass() + "queryForObject,执行查询的SQL语句错误" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }

    private Field getFieldObject(String columnName) {
        try {
            return clazz.getDeclaredField(columnName);
        } catch (NoSuchFieldException e) {
            return null;
        }
    }

    /**
     * 查询 返回list<T>类型
     *
     * @param sql    查询sql语句
     * @param params 条件参数
     * @return
     */
    public List<T> queryForObjectList(String sql, Object... params) {
        List<T> resultList = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                stmt.setObject(i + 1, params[i]);//预处理赋值
            }
            rs = stmt.executeQuery();//获取ResultSet对象
            if (rs.next()) {
                resultList = new ArrayList<>();
                ResultSetMetaData rsmd = rs.getMetaData();
                int columnCount = rsmd.getColumnCount();
                do {
                    T recordData = (T) clazz.newInstance();
                    for (int i = 1; i <= columnCount; i++) {
                        String columnName = rsmd.getColumnLabel(i);
                        Field field = getFieldObject(columnName);
                        if (field != null) {
                            field.setAccessible(true);
                            //field.getType().getName() //java.util.Date
                            Object columnValue = rs.getObject(columnName);//rs.getObject(i);
                            field.set(recordData, columnValue);
                        }
                    }
                    resultList.add(recordData);
                } while (rs.next());

            }
            return resultList;
        } catch (SQLException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();//给程序员使用
            throw new RuntimeException(clazz.getName() + ".queryForObjectList,执行查询单条的SQL语句错误:" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }

    /**
     * 返回单条记录
     *
     * @param sql
     * @param params
     * @return
     */
    public Object queryForObject(String sql, Object... params) {
        Object resultObject = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                stmt.setObject(i + 1, params[i]);//预处理赋值
            }
            rs = stmt.executeQuery();//获取ResultSet对象
            if (rs.next()) {
                resultObject = rs.getObject(1);
            }
            return resultObject;
        } catch (SQLException e) {
            e.printStackTrace();//给程序员使用
            throw new RuntimeException(clazz.getName() + ".queryForObject,执行查询单条的SQL语句错误:" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }

    /**
     * 返回Integer类型的单条记录
     */
    public Integer queryForInteger(String sql, Object... params) {
        Object object = queryForObject(sql, params);
        if (object == null) {
            return null;
        }
        return Integer.parseInt(String.valueOf(object));
    }

    /**
     * 返回String类型的单条记录
     *
     * @param sql    sql语句
     * @param params 条件参数
     * @return
     */
    public String queryForString(String sql, Object... params) {
        Object object = queryForObject(sql, params);
        if (object == null) {
            return null;
        }
        return String.valueOf(object);
    }

    /**
     * 返回类型为string的单列数据
     *
     * @param sql
     * @param params
     * @return
     */
    public List<String> queryForStringList(String sql, Object... params) {
        List<String> resultList = null;
        Connection conn = db.getConnection();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                stmt.setObject(i + 1, params[i]);//预处理赋值
            }
            rs = stmt.executeQuery();//获取ResultSet对象
            if (rs.next()) {
                resultList = new ArrayList<>();
                do {
                    resultList.add(rs.getString(1));
                } while (rs.next());
            }
            return resultList;
        } catch (SQLException e) {
            e.printStackTrace();//给程序员使用
            throw new RuntimeException(clazz.getName() + ".queryForObject,执行查询单条的SQL语句错误:" + e.getMessage());
        } finally {
            db.closeAll(conn, stmt, rs);
        }
    }
}

6.6创建实体类

src/main目录下创建java文件夹用于存放 java源代码,并在该文件目录下添加实体包entity

package com.entity;
import java.io.Serializable;
import java.util.Date;
/**
 * 考勤信息实体类
 */
public class Attence implements Serializable {
    /**
     * 主键,自增长
     */
    private Integer id;
    /**
     * 员工姓名
     */
    private String empname;
    /**
     * 部门
     */
    private String dept;
    /**
     * 考勤日期
     */
    private Date chkdate;

    /**
     * 考勤类型(1-正常 2-迟到 3-早退 4-休假 5-外出)
     */
    private Integer status;
    //此处省略 getter/setter方法...... 
}

6.7定义DAO接口

创建dao包并在保重定义AttenceDao接口

package com.dao;

import com.entity.Attence;

import java.util.List;

/**
 * 考勤dao接口
 *
 * @author Aiden
 */
public interface AttenceDao {
    /**
     * 查询所有考勤信息
     *
     * @return
     * @throws Exception
     */
    List<Attence> findAll() throws Exception;

    /**
     * 新增
     *
     * @param attence
     * @return
     * @throws Exception
     */
    int insert(Attence attence) throws Exception;

}

6.8创建DAO实现类

dao包里再创建一个impl包,并在包中创建AttenceDaoImpl实现类。该类需要继承BaseDao<Attence> 类,实现 AttenceDao接口,并需要重写 AttenceDao接口中的方法

package com.dao.impl;

import com.dao.AttenceDao;
import com.dao.BaseDao;
import com.entity.Attence;

import java.util.List;

/**
 * 考勤DAO实现类
 * @author Aiden
 */
public class AttenceDaoImpl extends BaseDao<Attence> implements AttenceDao {

    @Override
    public List<Attence> findAll() throws Exception {
        String sql = "select `id`, `empname`, `dept`, `chkdate`, `status` from attence order by chkdate desc";
        List<Attence> list = super.queryForObjectList(sql);
        return list;
    }

    @Override
    public int insert(Attence attence) throws Exception {
        String sql = "INSERT INTO `attence`(`empname`, `dept`, `chkdate`, `status`) VALUES (?,?,?,?);";
        int result = super.update(sql, attence.getEmpname(), attence.getDept(), attence.getChkdate(), attence.getStatus());
        return result;
    }
}

6.9创建service业务接口

创建service 包,并在该包中定义AttenceService接口

package com.service;

import com.entity.Attence;

import java.util.List;

/**
 * 考勤业务接口
 *
 * @author Aiden
 */
public interface AttenceService {
    //查询所有考勤信息
    List<Attence> findAll();

    //新增
    int insert(Attence attence);
}

6.10创建service业务实现类

service 包基础上创建impl包,并在该包中定义AttenceServiceImpl接口实现类。该类需要实现AttenceService接口,重写接口中业务方法,在此类中需要调用DAO实现中的方法,所以需要创建dao实例对象 private AttenceDao dao = new AttenceDaoImpl();

package com.service.impl;

import com.dao.AttenceDao;
import com.dao.impl.AttenceDaoImpl;
import com.entity.Attence;
import com.service.AttenceService;

import java.util.List;

/**
 * 考勤业务实现类
 *
 * @author Aiden
 */
public class AttenceServiceImpl implements AttenceService {

    //dao实例对象
    private AttenceDao dao = new AttenceDaoImpl();

    @Override
    public List<Attence> findAll() {
        List<Attence> list = null;
        try {
            list = dao.findAll();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return list;
    }

    @Override
    public int insert(Attence attence) {
        int insert = 0;
        try {
            insert = dao.insert(attence);
        } catch (Exception exception) {
            insert = -1;
        }
        return insert;
    }
}

6.11创建查询页面

webapp根目录下创建index.jsp页面,并按照要求写好布局。

考勤数据的展示采用JSTL标签库+EL表达式实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>考勤记录信息表</title>
    <style>
        #box {
            width: 800px;
            margin: 0 auto;
            margin-top: 20px
        }

        table {
            border-collapse: collapse;
        }
        table thead tr:first-of-type {
            background-color: #00bfff;
        }
        table td {
            border: 1px solid #ACBED1;
            line-height: 30px
        }
		/*考勤记录信息表标题样式*/
        .title {
            text-align: center;
            line-height: 50px;
            font-size: 25px;
            color: blue;
            font-weight: bold;
        }
		/*考勤登记链接样式*/
        .add {
            display: block;
            text-align: right;
            color: #bd5eea;
            font-size: 18px;
            margin-top: 10px;
        }
    </style>
</head>
<body id="box">
<table width="100%">
    <thead>
    <tr>
        <td colspan="4" class="title"> 考勤记录信息表</td>
    </tr>
    <tr align="center" style="font-weight: bold;background-color: #7bc5c9">
        <td>员工姓名</td>
        <td>所属部门</td>
        <td>考勤日期</td>
        <td>考勤状态</td>
    </tr>
    </thead>
    <tbody>

    <c:if test="${not empty requestScope.attenceList}">
        <c:forEach var="a" items="${requestScope.attenceList}" varStatus="v">
            <tr align="center" <c:if test="${v.index%2==1}">style="background:lightcyan"</c:if>>
                <td>${a.empname}</td>
                <td>${a.dept}</td>
                <td><f:formatDate value="${a.chkdate}" pattern="yyyy-MM-dd"  type="both" ></f:formatDate> </td>
                <td>
                    <c:choose>
                        <c:when test="${a.status ==1}">正常</c:when>
                        <c:when test="${a.status ==2}">迟到</c:when>
                        <c:when test="${a.status ==3}">早退</c:when>
                        <c:when test="${a.status ==4}">休假</c:when>
                        <c:when test="${a.status ==5}">外出</c:when>
                        <c:otherwise>未知</c:otherwise>
                    </c:choose>
                </td>
            </tr>
        </c:forEach>
    </c:if>
    <c:if test="${empty requestScope.attenceList}">
        <tr align="center">
            <td colspan="4"><a href="AttenceServlet">暂无数据!点击重新加载!</a></td>
        </tr>
    </c:if>
    </tbody>
</table>
<a class="add" href="add.jsp">考勤登记</a>
</body>
</html>

6.12创建查询控制器Servlet

创建servlet包,并在该包中创建AttenceServlet类,该类需要继承 HttpServlet类,在类名上添加@WebServlet("/AttenceServlet")注解,然后重写doGet和doPost方法,用于接收客户端get或post类型的http请求

package com.servlet;

import com.entity.Attence;
import com.service.AttenceService;
import com.service.impl.AttenceServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 考勤信息查询控制器
 * @author Aiden
 */
@WebServlet("/AttenceServlet")
public class AttenceServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //处理乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        //业务对象
        AttenceService service=new AttenceServiceImpl();
        //调用业务层方法获取集合对象
        List<Attence> attenceList = service.findAll();
        //保存数据到request作用域中
        request.setAttribute("attenceList",attenceList);
        //跳转页面(转发)
        request.getRequestDispatcher("index.jsp").forward(request,response);
    }
}

6.13创建新增页面

1、在webapp根目录下创建add.jsp页面,并按照要求写好样式与布局。

2、在webapp根目录下创建js目录,并将jQuery-3.6.0.js文件复制到在该目录下,然后在add.jsp页面使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>新增考勤记录信息</title>
    <style>
        #box {
            width: 500px;
            margin: 0 auto;
            margin-top: 120px
        }

        table {
            border-collapse: collapse;
        }

        table tr:first-of-type {
            background-color: deepskyblue;
        }

        table td {
            border: 1px solid #ACBED1;
            line-height: 35px
        }

        .title {
            text-align: center;
            line-height: 50px;
            font-size: 25px;
            color: blue;
            font-weight: bold;
        }

        input, select {
            width: 220px;
            margin-left: 10px;
            line-height: 18px;
            font-size:16px;
        }
        select{padding: 3px}
    </style>
</head>
<body id="box">
<form id="formAdd" action="" method="post">
    <table border="1" width="100%">
        <tr>
            <td colspan="2" class="title"> 考勤记录信息表</td>
        </tr>
        <tr>
            <td align="center">姓名</td>
            <td><input type="text" name="empname"></td>
        </tr>
        <tr>
            <td align="center">所属部门</td>
            <td><input type="text" name="dept"></td>
        </tr>
        <tr>
            <td align="center">考勤日期</td>
            <td><input type="text" name="chkdate"> 日期格式:yyyy-mm-dd</td>
        </tr>
        <tr>
            <td align="center">考勤状态</td>
            <td>
                <select name="status">
                    <option value="">请选择考勤类型</option>
                    <option value="1">正常</option>
                    <option value="2">迟到</option>
                    <option value="3">早退</option>
                    <option value="4">休假</option>
                    <option value="5">外出</option>
                </select>
            </td>
        </tr>
        <tr align="center">
            <td colspan="2">
                <button type="submit">登记</button>
                <button type="reset">重置</button>
            </td>
        </tr>
    </table>
</form>
<script src="js/jquery-3.6.0.js"></script>
<script>
    $(function () {
        //触发表单的提交事件
        $("#formAdd").submit(function () {
            //非空验证:
            let empname = $("[name=empname]").val().trim();//员工姓名
            let dept = $("[name=dept]").val().trim();//部门
            let chkdate = $("[name=chkdate]").val().trim();//考勤日期
            let status = $("[name=status]").val().trim();//考勤类型
            //非空验证
            if (empname == '' || empname == null || empname == undefined) {
                alert('员工姓名不能为空!');
                return false;
            }
            if (dept == '' || dept == null || dept == undefined) {
                alert('部门不能为空!');
                return false;
            }
            if (chkdate == '' || chkdate == null || chkdate == undefined) {
                alert('考勤日期不能为空!');
                return false;
            }
            //日期验证格式:
            let dateReg = /^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/;
            if (!dateReg.test(chkdate)) {
                alert('日期格式必须是yyy-mm-dd格式,请检查后重新输入');
                return false;
            }
            if (status == '' || status == null || status == undefined) {
                alert('请选择考勤类型!');
                return false;
            }

            //ajax提交数据
            $.ajax({
                url: 'InsertServlet',//提交的控制器名字
                data: {empname: empname, dept: dept, chkdate: chkdate, status: status},
                type: 'post',
                success: function (data) {//data:服务端Servlet反馈给客户端的值
                    if (data == 'true') {
                        alert('登记成功');
                        //请求查询Servlet实现刷新
                        location.href = 'AttenceServlet';
                    } else {
                        alert('登记失败!');
                    }
                }
            });

            return false;//保证页面不会被刷新
        })

    })
</script>
</body>
</html>

6.14创建新增控制器Servlet

servlet包中创建InsertServlet类,该类需要继承 HttpServlet类,在类名上添加@WebServlet("/InsertServlet")注解,然后重写doGet和doPost方法,用于接收客户端get或post类型的http请求

package com.servlet;

import com.entity.Attence;
import com.service.AttenceService;
import com.service.impl.AttenceServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;

/**
 * 新增考勤信息控制器
 *
 * @author Aiden
 */
@WebServlet("/InsertServlet")
public class InsertServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.处理乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        //2.获取客户端表单提交过来的数据
        String empname = request.getParameter("empname");
        String dept = request.getParameter("dept");
        String chkdate = request.getParameter("chkdate");
        String status = request.getParameter("status");

        PrintWriter out = response.getWriter();
        //3.业务对象
        AttenceService service = new AttenceServiceImpl();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Attence attence = new Attence();
            attence.setEmpname(empname);//名字
            attence.setDept(dept);//部门
            attence.setStatus(Integer.parseInt(status));
            attence.setChkdate(df.parse(chkdate));
            //调用业务层新增方法
            int result = service.insert(attence);
            if (result > 0) {//判断是否成功
                out.print("true");//成功则响应客户端一个字符串 true
            } else {
                out.print("false");//失败则响应客户端一个字符串 false
            }
        } catch (Exception exception) {
            out.print(false);
        } finally {
            out.flush();
            out.close();
        }
    }
}


6.15设置默认启动

打开webapp/WEB-INF目录下的web.xml文件,添加 <welcome-file-list>节点设置项目启动时访问查询控制器AttenceServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0" >
  
  <display-name>Archetype Created Web Application</display-name>
  
  <welcome-file-list>
    <welcome-file>AttenceServlet</welcome-file>
  </welcome-file-list>

</web-app>



6.16配置Tomcat运行项目

部署工件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UPwokr9q-1657602827747)(E:\BDQN\BCSP\课件笔记\JSP\jsp 08.assets\1657598345710.png)]

设置运行配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mDvedce4-1657602827747)(E:\BDQN\BCSP\课件笔记\JSP\jsp 08.assets\1657598423125.png)]

使用Tomcat运行项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yXcgBSE8-1657602827748)(E:\BDQN\BCSP\课件笔记\JSP\jsp 08.assets\1657598553152.png)]


6.17导出数据库脚本

使用Navicat工具鼠标右键点击数据库 然后导出脚本到指定磁盘目录就可以了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSLbyMld-1657602827748)(E:\BDQN\BCSP\课件笔记\JSP\jsp 08.assets\1657598801378.png)]


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiHwxfDH-1657602827749)(E:\BDQN\BCSP\课件笔记\JSP\jsp 08.assets\1657599034596.png)]


源码获取请加群: 617530501

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

众生云海,一念初见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值