1.案例需求
用JavaWeb相关知识完成一整套的的员工管理系统,包括增删改查,分页查询,登录等功能,具体的运行效果如下图。
2.编程思路
-
注册功能:
- 服务类实例化:服务类 EmpService 被实例化为 EmpServiceImpl,这是实现具体业务逻辑的地方。通过这种方式,AddEmpServlet 依赖于 EmpService 接口和它的实现类来执行与员工相关的数据库操作。
- 处理GET和POST请求:doGet 方法通过调用 doPost 方法来处理请求,因为注册通常通过POST请求完成。
- 请求参数处理:通过 request.getParameter 方法获取从表单提交的所有必要参数,包括员工ID、姓名、职位、经理ID、入职时间、薪水、佣金、部门编号和密码。注意,对于非字符串类型的参数(如 empid、empmgr、empdeptno、empsal、empcomm),它们被转换为相应的类型(如 Integer、Double)。入职时间(emptime)通过 SimpleDateFormat 解析字符串格式的日期为 Date 对象。
- 错误处理:在解析日期时,如果输入的日期格式不正确,会捕获 ParseException 并抛出一个运行时异常。
- 调用服务层方法:使用获取到的参数调用 empService.addEmp 方法来执行员工信息的添加操作。该方法应该返回一个整数来指示操作的成功与否(通常,非零值表示成功,零或负值表示失败)。
- 结果处理:如果添加成功(result > 0),则请求被转发到 login.jsp 页面,可能是假设用户需要立即登录或验证他们的账户。如果添加失败,则当前实现使用response.sendRedirect(“register.jsp”) 将用户重定向回注册页面。
-
登录功能:
- 初始化服务类:在LoginServlet类中,通过直接实例化EmpServiceImpl和EmpAndDeptServiceImpl来创建EmpService和EmpAndDeptService的实例。
- 处理GET和POST请求:doGet方法通过调用doPost方法来处理GET请求,这是一种常见的做法,因为在这个例子中,登录表单通常通过POST方法提交。doPost方法负责处理登录逻辑。
- 接收请求参数:通过request.getParameter(“loginusername”)和request.getParameter(“loginpass”)方法从HTTP请求中获取用户名和密码。
- 设置请求和响应的编码:设置请求编码为utf-8,以确保能够正确处理非ASCII字符(如中文)。设置响应的内容类型为text/html;charset=utf-8,确保返回给客户端的HTML内容也是以UTF-8编码。
- 验证用户名和密码:调用empService.queryEmp(username, pass)方法来验证用户名和密码。这里假设queryEmp方法会返回一个整数,其中0表示验证成功。
- 根据验证结果执行不同操作:如果验证成功(即result == 0),则通过request.getRequestDispatcher(“paginationServlet”).forward(request,response)将请求转发到paginationServlet。如果验证失败,则将错误信息存储在ServletContext中并通过response.sendRedirect(“login.jsp”)将用户重定向回登录页面。
-
修改功能:
- 服务层依赖:UpdateServlet依赖于EmpService和EmpAndDeptService通过实例化EmpServiceImpl和EmpAndDeptServiceImpl来具体实现这些服务。
-请求处理:通过重写doGet和doPost方法,UpdateServlet能够处理来自客户端的GET和POST请求。 - 请求参数获取:在doPost方法中,首先通过request.getParameter方法获取所有必要的请求参数,这些参数对应于要更新的员工信息,如员工ID、姓名、职位等。
- 日期解析:入职时间(emptime)是一个字符串,需要被解析为Date对象。这里使用了SimpleDateFormat类来执行这个转换。
- 业务逻辑处理:使用从请求中获取的参数调用empService.updateEmp方法来更新员工信息。这个方法应该返回一个整数,指示操作的成功与否(通常,非零值表示成功,零或负值表示失败)。
- 结果处理:根据updateEmp方法的返回值,决定后续的操作。如果更新成功(result > 0),则使用请求分发器(RequestDispatcher)将请求转发到另一个Servlet,如果更新失败,则通过重定向将用户发送到登录页面。
- 服务层依赖:UpdateServlet依赖于EmpService和EmpAndDeptService通过实例化EmpServiceImpl和EmpAndDeptServiceImpl来具体实现这些服务。
-
删除功能:
- 服务类实例化:类似于LoginServlet,DeleteServlet中也是直接实例化了EmpServiceImpl和EmpAndDeptServiceImpl作为EmpService和EmpAndDeptService的实现。
- 处理GET和POST请求:doGet方法简单地调用了doPost方法,因为在这个例子中,删除操作通常通过POST请求触发,以避免通过URL传递敏感操作(如删除)。
- 接收请求参数:通过request.getParameter(“empno”)方法从HTTP请求中获取要删除的员工编号(empno)。
- 执行删除操作:调用empService.deleteEmpById(empno)方法来根据员工编号删除员工。这里假设deleteEmpById方法返回一个整数,其中大于0的值表示删除成功(具体返回值含义应根据实际情况定义)。
- 处理删除结果:通过打印result值到控制台来调试或记录删除操作的结果。如果删除成功(即result > 0),则当前实现选择将请求转发到paginationServlet。如果删除失败(当前实现中没有直接处理失败的逻辑),可能需要向用户显示错误消息或重定向回原页面。
-
分页功能:
- 服务层依赖:PaginationServlet依赖于EmpAndDeptService来执行与分页相关的业务逻辑。通过实例化EmpAndDeptServiceImpl来具体实现这个服务。
- 请求处理:重写了doGet和doPost方法,但在这里,doGet方法被简单地重定向到doPost方法,使得所有分页相关的请求都在doPost方法中处理。
- 参数获取:通过request.getParameter方法获取请求中的搜索参数(如部门名称dname、职位job、薪资范围sal)和分页参数(如当前页码currPage)。对于薪资范围sal,如果提供了该参数且不为空,则将其转换为double类型。
- 构建查询条件:使用获取到的搜索参数创建一个EmpVo对象,该对象封装了分页查询时需要用到的搜索条件。
- 分页逻辑:首先,根据搜索条件查询出所有满足条件的记录总数,然后基于页面大小和记录总数计算出总页数(maxpagesize)。接着,根据请求中的当前页码参数currPage计算出实际的页码索引pageindex。如果currPage为空或超出范围,则进行相应的调整。最后,调用empAndDeptService.queryByPage方法,根据页码索引和页面大小查询出当前页的数据。
- 结果处理:将查询到的当前页数据(empAndDepts)以及总页数(maxpagesize)和当前页码(pageindex)作为属性设置到请求中。使用请求分发器(RequestDispatcher)将请求转发到showAllEmps.jsp页面,以便在页面上展示分页数据和导航链接。
-
多条件查询功能:
- queryAllEmps(EmpVo empVo) 方法
- 初始化SQL语句:首先,构建一个基本的SQL查询语句,该语句通过内连接(INNER JOIN)将员工表(emp)和部门表(dept)关联起来,并设置了一个恒真的条件where 1=1,这是为了后续方便地添加其他条件。
- 条件拼接:然后,根据EmpVo对象中的非空属性(部门名称dname、职位job、薪资sal),动态地向SQL语句中添加相应的查询条件,并将对应的值添加到contain列表中,用于后续执行查询时传递参数。对于部门名称和职位,使用LIKE操作符配合通配符%来支持模糊查询。
对于薪资,直接比较大于某个值。 - 执行查询:最后,调用JDBCUtil.executeQueryList方法执行查询,将SQL语句、目标类(EmpAndDept.class)以及参数数组(contain.toArray())作为参数传递。
- queryAllEmps(EmpVo empVo) 方法
3.案例核心源码
注册功能核心代码:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Integer empid = Integer.valueOf(request.getParameter("empid"));
String empname = request.getParameter("empname");
String empjob = request.getParameter("empjob");
Integer empmgr = Integer.valueOf(request.getParameter("empmgr"));
String time = request.getParameter("emptime");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date emptime = null;
try {
emptime = dateFormat.parse(time);
} catch (ParseException e) {
throw new RuntimeException(e);
}
Double empsal = Double.valueOf(request.getParameter("empsal"));
Double empcomm = Double.valueOf(request.getParameter("empcomm"));
Integer empdeptno = Integer.valueOf(request.getParameter("empdeptno"));
String emppass = request.getParameter("emppass");
int result = empService.addEmp(empid, empname, empjob, empmgr, emptime, empsal, empcomm, empdeptno, emppass);
ServletContext application = this.getServletContext();
if (result>0){
request.getRequestDispatcher("login.jsp").forward(request,response);
}else {
response.sendRedirect("register.jsp");
}
登录功能核心代码:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("loginusername");
String pass = request.getParameter("loginpass");
ServletContext application = this.getServletContext();
int result = empService.queryEmp(username, pass);
if (result==0){ request.getRequestDispatcher("paginationServlet").forward(request,response);
}else {
application.setAttribute("INFO","登录失败,用户名或密码错误,请重新登录!");
response.sendRedirect("login.jsp");
}
}
修改功能核心代码:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Integer empid = Integer.valueOf(request.getParameter("empid"));
String empname = request.getParameter("empname");
String empjob = request.getParameter("empjob");
Integer empmgr = Integer.valueOf(request.getParameter("empmgr"));
String time = request.getParameter("emptime");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date emptime = null;
try {
emptime = dateFormat.parse(time);
} catch (ParseException e) {
throw new RuntimeException(e);
}
Double empsal = Double.valueOf(request.getParameter("empsal"));
Double empcomm = Double.valueOf(request.getParameter("empcomm"));
Integer empdeptno = Integer.valueOf(request.getParameter("empdeptno"));
int result = empService.updateEmp(empid, empname, empjob, empmgr, emptime, empsal, empcomm, empdeptno);
if (result>0){
request.getRequestDispatcher("paginationServlet").forward(request,response);
}else {
response.sendRedirect("login.jsp");
}
}
删除功能核心代码:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String empno = request.getParameter("empno");
int result = empService.deleteEmpById(empno);
System.out.println(result);
if (result>0){ request.getRequestDispatcher("paginationServlet").forward(request,response);
}
分页功能核心代码:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String dname = request.getParameter("searchdname");
String job = request.getParameter("searchjob");
String sal = request.getParameter("searchsal");
double empsal=0;
if (sal != null && !sal.trim().isEmpty()) {
empsal = Double.parseDouble(sal.trim());
}
EmpVo empVo = new EmpVo(dname,job,empsal);
String currPage = request.getParameter("currPage");
int pagesize = 5;
Integer pageindex = 0;
int maxpagesize = (int) Math.ceil((double) empAndDeptService.queryAllEmps(empVo).size() / pagesize);
System.out.println(maxpagesize);
request.setAttribute("maxpagesize", maxpagesize);
if (currPage == null) {
pageindex = 1;
} else {
if (Integer.valueOf(currPage) < 1) {
pageindex = 1;
} else if (Integer.valueOf(currPage) > maxpagesize) {
pageindex = maxpagesize;
} else {
pageindex = Integer.valueOf(currPage);
}
}
request.setAttribute("pageindex", pageindex);
List<EmpAndDept> empAndDepts = empAndDeptService.queryByPage(pageindex, pagesize,empVo);
request.setAttribute("EMP_LIST", empAndDepts);
request.getRequestDispatcher("showAllEmps.jsp").forward(request, response);
}
多条件查询功能核心代码:
@Override
public List<EmpAndDept> queryAllEmps(EmpVo empVo) {
String sql = "select emp.*,dept.dname from emp INNER JOIN dept on emp.deptno=dept.deptno where 1=1";
List contain = new ArrayList<>();
if (empVo.getDanme()!=null){
sql+=" and dname like ?";
contain.add("%"+empVo.getDanme()+"%");
}
if (empVo.getJob()!=null){
sql+=" and job like ?";
contain.add("%"+empVo.getJob()+"%");
}
if (empVo.getSal()!=0){
sql+=" and sal > ?";
contain.add(empVo.getSal());
}
return JDBCUtil.executeQueryList(sql, EmpAndDept.class,contain.toArray());
}
@Override
public List<EmpAndDept> queryEmpsByDname(String dname) {
String sql = "select emp.*,dept.dname from emp INNER JOIN dept on emp.deptno=dept.deptno where dname like CONCAT('%', ?, '%')";
return JDBCUtil.executeQueryList(sql, EmpAndDept.class, dname);
}
@Override
public List<EmpAndDept> queryByPage(int page, int pagesize, EmpVo empVo) {
String sql = "select emp.*,dept.dname from emp INNER JOIN dept on emp.deptno=dept.deptno where 1=1";
List contain = new ArrayList<>();
if (empVo.getDanme()!=null){
sql+=" and dname like ?";
contain.add("%"+empVo.getDanme()+"%");
}
if (empVo.getJob()!=null){
sql+=" and job like ?";
contain.add("%"+empVo.getJob()+"%");
}
if (empVo.getSal()!=0){
sql+=" and sal > ?";
contain.add(empVo.getSal());
}
sql += " limit ?,?";
contain.add((page - 1) * pagesize);
contain.add( pagesize);
return JDBCUtil.executeQueryList(sql, EmpAndDept.class, contain.toArray());
}
4.小结
该员工管理系统主要涉及到以下的知识点:
- 数据库设计与SQL语言
- 数据库设计:首先,系统需要设计数据库来存储员工和部门的信息。这包括创建表(如员工表emp、部门表dept等),并定义表之间的关系(如通过外键deptno实现员工表和部门表的内连接)。
- SQL语言:系统广泛使用SQL语言进行数据的增删改查(CRUD)操作。这包括SELECT语句用于查询数据,INSERT语句用于添加数据,UPDATE语句用于修改数据,以及DELETE语句用于删除数据。此外,还涉及到了条件查询(如使用WHERE子句)、模糊查询(如使用LIKE操作符)、内连接查询(如INNER JOIN)以及分页查询(如使用LIMIT子句)。
- Java编程语言
- Java基础:系统使用Java作为后端开发语言,因此涉及到Java的基本语法、类与对象、封装、继承、多态等面向对象编程的基本概念。
- 集合框架:在代码中,使用了Java的集合框架来存储和传递数据,如List接口的实现类ArrayList用于存储查询条件或查询结果。
- 异常处理:在数据库操作中,可能会遇到各种异常情况(如SQL异常、连接异常等),因此需要使用Java的异常处理机制来捕获和处理这些异常。
- JDBC技术
- JDBC概述:JDBC(Java Database Connectivity)是Java提供的一套用于执行SQL语句的API,它允许Java程序与数据库进行交互。
- 连接数据库:系统通过JDBC连接数据库,这包括加载数据库驱动、建立连接、创建Statement或PreparedStatement对象来执行SQL语句,并处理查询结果。
- 预处理语句:为了提高性能和安全性,系统使用PreparedStatement来执行带有参数的SQL语句,这样可以避免SQL注入攻击,并且数据库可以对预编译的SQL语句进行优化。
- 分页查询
- 分页逻辑:在展示大量数据时,系统需要实现分页功能,以提高用户体验。这通常通过在SQL查询中使用LIMIT子句,并结合页码和页面大小来计算起始行号来实现。
- 页面导航:除了实现基本的分页查询外,系统还可能提供页面导航功能,如显示总页数、当前页码、上一页、下一页等,以便用户方便地浏览数据。
- 面向对象设计
封装与抽象:系统通过定义类(如Emp、Dept、EmpVo等)和接口(如可能的数据访问层接口)来实现封装和抽象,以提高代码的可读性和可维护性。
综上所述,该员工管理系统涉及了数据库设计与SQL语言、Java编程语言、JDBC技术、分页查询、面向对象设计等多个知识点。这些知识点共同构成了系统开发的基础,使得系统能够高效地管理员工和部门的信息。