如何完成一个有前端有后端还有数据库的项目

592 阅读8分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

需要知识:Java基础,Java对象封装,Map,list接口,jdbc,sql,jquery Dom,jQuery AJAX进行数据动态读取,json解析。

完成项目:雇员管理系统

项目分析

操作流程图

图片描述

首页

  1. 首页需要登录,管理雇员和入职雇员以及管理部门等功能。页面布局不限制格式,可以自行设计。
  2. 系统必须在登录状态下,才能对雇员和部门进行管理操作,如果没有登录则拦截到登录页面。

登录页

这是登录之前的页面 image.png 这是登录成功的页面

image.png

  1. 输入用户名和密码可以实现登录,登录成功直接进入首页。系统默认会有根用户 admin 用户,密码为 123456
  2. 登录成功后系统导航栏会显示用户名,导航栏的登录按钮则不显示。
  3. 帮助和关于系统,属于装饰的功能,可以不用做。

管理雇员页

image.png

  1. 管理雇员页面主要是一个雇员信息列表。
  2. 每行的最后一个单元格里面是删除雇员和修改雇员超链接,点击“删除”可直接删除当前雇员,点击“修改”可进入修改雇员页。
  3. 下方是添加雇员按钮,可进入添加雇员页。

添加雇员页

image.png

  1. 添加雇员信息,添加完成跳到“管理雇员页”,且在“管理雇员页”可看到新增的雇员信息。
  2. 这里要注意的是,“部门”这个表单项是下拉框而不是输入框(即只能从现有部门中选择)。

修改雇员页

image.png

  1. 修改雇员信息,和添加基本一致,只是多了一个回显功能(需要把雇员信息展示在各个表单项里)。
  2. 使用者只需操作要修改的地方然后提交即可完成修改。

到这里,项目分析完成,接下来我们开始进行代码部分

数据库的设计和创建

由于我们做的是雇员管理系统。我们需要有一张表用于存放雇员信息。雇员信息有雇员名、雇员编号、薪水、职位、入职时间以及所在部门等信息。雇员所在部门又属于一个实体,如果我们把所有的部门信息都存放到雇员表里面很显然是不合适的。所以我们还需要一张部门表。一个系统里面肯定要有用户,系统需要用户登录以后才能操作。用户也是一个实体,所以我们还需要一个用户表。我们创建表的的时候还需要注意的是,所有的表名和字段名要有意义而且为英文名。以下为表 ER 图

图片描述

建表代码省略,插入数据省略

项目

接下来,我们需要创建项目的目录结构,首先来了解下各目录的作用:

PROJECT
 ├─lib
 │  └─rest-server-1.0.jar     # Web 服务器 Jar
 ├─web
 │   └─index.html             # 系统首页
 └─com                        # 放Java源码
     ├─App.java               # 启动类
     └─controller             # Rest 接口package
       └─TestController.java  # Rest 接口类

启动类(APP.java)

启动类是 Web 服务框架(rest-server-1.0)必须有的一个类,是 Web 服务的总入口。这个类几乎是固定的写法。 但是要注意的是,这个类一定要放到 Java 包的根下面。这样就能够被系统扫描到,否则将不能正常使用。下面为启动类的代码实现。

package com;
import org.service.SpringApplication;
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }
}

接口类

接下来我们在启动类(App.java)的同级的 controller 目录下创建接口类(TestController.java),用于提供 RESTful 风格的 Web 服务的具体实现。 具体代码如下:

package com.controller;
public class TestController {
    //一个简单的接口方法
    public  String test(){
        return "Hello 我是 Rest接口";
    }
}

系统首页

访问服务器时会默认进入 index.html 页面。此页面内容我们可以自定义。这里省略

接口测试

至此,我们所有的代码编写完毕,可以进行接口测试了。

要想直接访问接口里面的方法,必须启动 Web 服务。

启动 Web 服务非常简单。我们只需要运行 App.java 这个类的 main 方法即可。

运行 main 方法注意观察控制台,只要看到"欢迎使用蓝桥授课系统"字样,说明 Web 服务启动成功了。

打开浏览器,此时浏览器就会直接访问我们刚刚启动的服务器了。点击超连接或直接在 URL 上添加方法名就能够直接访问到我们刚刚创建的接口方法了。如果浏览器上可以看到接口方法的返回值,说明访问成功。

细节部分

用户登录板块

登录的基本流程就是用户通过输入用户名和密码,把数据通过 Ajax 技术提交到处理业务的服务器接口(Rest 接口),服务器接收到数据以后到数据库做查询,把查询到的用户信息和提交的用户信息进行比较。

如果信息一致则登录成功,否则登录失败。

PROJECT
├─lib                                     # 放依赖的jar包
│  ├─restServer-1.0.jar                           # Web 服务器 Jar
│  └─mysql-connector-java-5.0.8-bin.jar   # Mysql Jar
├─com                                     # 放Java源码
│  ├─controller                               # Rest 接口package
│  │  └─UserController.java                   # Rest 接口类
│  └─App.java                                 # Rest 服务启动类
└─web                                     # web静态资源目录
   ├─jquery
   │  └─jquery.min.js                     # jQuery 库
   ├─js
   │  ├─index.js                          # index.html 对应的 js 文件
   │  └─login.js                          # login.html 对应的 js 文件
   ├─pages                                # 存放其他静态页面的目录
   │  └─login.html                        # 登录页面
   └─index.html                           # 系统首页

我们需要两个页面,一个登录页,一个首页。

下面,我们先完成登录页,这里面的内容很简单,就是两个表单项:用户名和密码,

当用户点击”完成登录“按钮时,将触发 js 来提交验证。

  • login.html
<!DOCTYPE html>
<html>
  <head>
    <title>登录页面</title>
    <script
      src="/jquery/jquery.min.js"
      type="text/javascript"
      charset="utf-8"
    ></script>
    <script src="/js/login.js" type="text/javascript" charset="utf-8"></script>
  </head>
  <body>
    用户名: <input type="text" id="userName" /> <br />
    用户密码:<input type="password" id="password" />
    <button onclick="login()">完成登录</button>
  </body>
</html>
  • login.js
function login() {
  var userName = document.getElementById("userName").value;
  var password = document.getElementById("password").value;
  var param = `?userName=${userName}&password=${password}`;
  $.get("/login" + param, function (response) {
    if (response.status == "200") {
      console.log(response);
      var userName = response.userName;
      sessionStorage.setItem("userName", userName);
      window.location.href = "../index.html";
    } else if (response.status == "fail") {
      alert(response.errorMessage);
    }
  });
}
  • index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>首页</title>
    <!--引入 index.js -->
    <script src="/js/index.js" type="text/javascript" charset="utf-8"></script>
  </head>
  <body onload="showUserName()">
    <!--显示用户信息 Div -->
    <div id="userNameDiv">
      <a href="/pages/login.html">登录</a>
    </div>
  </body>
</html>
  • index.js
function showUserName() {
  var userName = sessionStorage.getItem("userName");
  if (userName) {
    document.getElementById("userNameDiv").innerHTML = `
        你好 ${userName}
        <a href="javascript:logout()">退出</a>
        `;
  }
}

function logout() {
  sessionStorage.removeItem("userName");
  window.location.href = "/index.html";
}
  • UserController.java
package com.controller;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
public class UserController {
    /**
     * 登录接口方法
     * @param userName 用户名
     * @param password 密码
     * @return  Map 对象
     */
    public Map login(String userName, String password){
        //用与向客户端返回数据的 Map 对象
        Map returnMap = new HashMap();
        //数据库的连接信息
        String driver = "com.mysql.jdbc.Driver";

        //数据库连接信息,根据自身情况填写
        String url = "jdbc:mysql:///test?characterEncoding=utf-8";

        String user = "root";
        String pass = null;

        try {
            //加载 Mysql 驱动类
            Class.forName(driver);
            //创建数据库连接对象
            Connection connection = DriverManager.getConnection(url,user,pass);
            //创建 preparedStatement 对象
            String sql = "select userName,password from user where userName=?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,userName);

            //执行 user 表查询
            ResultSet resultSet = preparedStatement.executeQuery();
            // 登录的逻辑代码
            if(resultSet.next()){
                String selectName = resultSet.getString("userName");
                String selectPass = resultSet.getString("password");
                if(selectPass.equals(password)){
                    returnMap.put("status","200");
                    returnMap.put("userName",userName);
                }else {
                    returnMap.put("status","fail");
                    returnMap.put("errorMessage","密码不对");
                }
            }else {
                returnMap.put("status","fail");
                returnMap.put("errorMessage","查不到此用户");
            }

            //关闭资源
            resultSet.close();
            preparedStatement.close();
            connection.close();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return returnMap;
    }
}

启动服务

运行 App.java 启动服务器

进入首页

本地开发环境,在浏览器地址栏输入 ip 加端口号即可直接进入首页。例如:localhost:8080。

看到登录页面我们就可以登录一下试一试啦。这里要注意的是登录的用户名和密码一定是数据库里面存在的。

雇员模块_查询雇员

后端 Java 代码实现查询和封装数据,以 JSON 的形式响应给客户端。客户端用 Ajax 请求后端服务器,接收到 JSON 数据后,把 JSON 数据遍历出来,并拼接成表格字符串。然后把字符串用操作 DOM 的方式注入到存放表格的 DIV 元素中。

我们先完成首页,这里面的内容很简单,就是一个超链接:连接到查询页,

当用户点击”查询雇员“超链接时,将跳转到查询页。

其次我们需要一个查询页(showEmps.html)。body 标签中添加 onload 属性,页面加载完毕立即调用 loadEmps 函数,用于加载查询的数据。

  • showEmps.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>登录页面</title>
    <script
      src="/jquery/jquery.min.js"
      type="text/javascript"
      charset="utf-8"
    ></script>
    <script
      src="/js/showEmps.js"
      type="text/javascript"
      charset="utf-8"
    ></script>
  </head>
  <body onload="loadEmps()">
    <table border="1">
      <thead>
        <tr>
          <th>雇员姓名</th>
          <th>雇员职位</th>
          <th>雇员薪水</th>
          <th>入职日期</th>
          <th>所在部门</th>
        </tr>
      </thead>
      <tbody id="emps_tbody">
        <!--拼接的表格数据将要注入到这里-->
      </tbody>
    </table>
  </body>
</html>

loadEmps 函数代码,在 showEmps.html 对应的 showEmps.js 里。这个 loadEmps 函数主要功能,就是先发送一个 Ajax 请求,调用 Web 服务接口 showEmps。Ajax 会把调用 Web 接口返回的雇员信息,以 JSON 对象的形式传入到回调函数当中。回调函数把接受的 JSON 数据遍历,并拼接成表格字符串。最后把拼接好的表格字符,以操作 DOM 的方式注入到页面当中。

  • showEmps.js
function loadEmps() {
  $.get("/showEmps", function (response) {
    if (response.status == "200") {
      var tbody = "";
      //取出数据拼接表格
      var emps = response.emps;
      for (var i = 0; i < emps.length; i++) {
        var emp = emps[i];
        var empno = emp.empno;
        var ename = emp.ename;
        var job = emp.job;
        var sal = emp.sal;
        var hiredate = emp.hiredate;
        var dname = emp.dname;
        tbody += `
                        <tr>
                            <td>${ename}</td>
                            <td>${job}</td>
                            <td>${sal}</td>
                            <td>${hiredate}</td>
                            <td>${dname}</td>
                        </tr>
                    `;
      }
      //把拼接的数据注入到表格元素中
      $("#emps_tbody").html(tbody);
    }
  });
}

到此为止前端代码已经编写完毕,我们还需要创建 Web 服务启动类(App.java)和处理查询业务的服务接口(EmpController.java)类。在服务接口类里面提供一个 showEmps 方法。此方法会连接数据库,把 emp 表数据查询出来封装到 List 集合里并返回。

  • EmpController.java
package com.controller;
import java.sql.*;
import java.util.*;
public class EmpController {
    public Map showEmps(){
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql:///test?characterEncoding=utf-8";
        String user = "root";
        String pass = null;
        List<Map<String,Object>> emps = new ArrayList<>();
        try {
            //加载 Mysql 驱动类
            Class.forName(driver);
            //创建数据库连接对象
            Connection connection = DriverManager.getConnection(url,user,pass);
            //创建 preparedStatement 对象
            Statement statement = connection.createStatement();
            String sql="select empno,ename,job,sal,hiredate,dname from emp join dept on emp.deptno=dept.deptno";
            ResultSet resultSet = statement.executeQuery(sql);
            while(resultSet.next()){
               int empno = resultSet.getInt("empno");
               String ename = resultSet.getString("ename");
               String job = resultSet.getString("job");
               int sal = resultSet .getInt("sal");
               String hiredate = resultSet.getString("hiredate");
               String dname = resultSet.getString("dname");
               Map<String,Object> emp = new HashMap<>();
               emp.put("empno",empno);
               emp.put("ename",ename);
               emp.put("job",job);
               emp.put("sal",sal);
               emp.put("hiredate",hiredate);
               emp.put("dname",dname);
               emps.add(emp);
            }
            resultSet.close();
            statement.close();
            connection.close();

        }catch (ClassNotFoundException e){
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        Map returnMap = new HashMap();
        returnMap.put("status","200");
        returnMap.put("emps",emps);
        return returnMap;
    }
}

添加修改等和查询类似,后端代码就是jdbc里面使用Statement或者PreparedStatement关键字实现增删改查