前后端分离(前后端交互步骤)

1.设计数据库

复制代码
/*
 Navicat Premium Data Transfer
​
 Source Server         : localhost_3306
 Source Server Type    : MySQL
 Source Server Version : 80037 (8.0.37)
 Source Host           : localhost:3306
 Source Schema         : studymysql
​
 Target Server Type    : MySQL
 Target Server Version : 80037 (8.0.37)
 File Encoding         : 65001
​
 Date: 24/12/2024 11:32:08
*/
​
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
​
-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp`  (
  `empno` int NOT NULL AUTO_INCREMENT COMMENT '雇员编号',
  `ename` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '表示工作职位',
  `mgr` int NULL DEFAULT NULL COMMENT '表示一个雇员的领导编号',
  `hiredate` datetime NULL DEFAULT NULL COMMENT '表示雇佣日期',
  `sal` double NULL DEFAULT NULL COMMENT '表示月薪,工资',
  `comm` double NULL DEFAULT NULL COMMENT '表示奖金或佣金',
  `deptno` int NULL DEFAULT NULL,
  PRIMARY KEY (`empno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
​
-- ----------------------------
-- Records of emp
-- ----------------------------
​
SET FOREIGN_KEY_CHECKS = 1;
​

2.编写实体类和数据库形成映射

复制代码
package com.pyb.pojo;
​
/**
 * @version 1.0
 * @Author 彭彦彬
 * @Date 2024/12/24 15:07
 * @注释
 */
public class Emp {
    private int empNo;
    private String eName;
    private String job;
    private int mgr;
    private String hireDate;
    private double sal;
    private double comm;
    private int deptNo;
​
    public Emp(int empNo, String eName, String job, int mgr, String hireDate, double sal, double comm, int deptNo) {
        this.empNo = empNo;
        this.eName = eName;
        this.job = job;
        this.mgr = mgr;
        this.hireDate = hireDate;
        this.sal = sal;
        this.comm = comm;
        this.deptNo = deptNo;
    }
​
    public Emp(String eName, String job) {
        this.eName = eName;
        this.job = job;
    }
​
    public Emp(String eName, String job, int mgr, String hireDate, double sal, int deptNo, double comm) {
        this.eName = eName;
        this.job = job;
        this.mgr = mgr;
        this.hireDate = hireDate;
        this.sal = sal;
        this.deptNo = deptNo;
        this.comm = comm;
    }
​
    @Override
    public String toString() {
        return "Emp{" +
                "empNo=" + empNo +
                ", eName='" + eName + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hireDate='" + hireDate + '\'' +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptNo=" + deptNo +
                '}';
    }
​
    public Emp() {
    }
​
    public int getEmpNo() {
        return empNo;
    }
​
    public void setEmpNo(int empNo) {
        this.empNo = empNo;
    }
​
    public String geteName() {
        return eName;
    }
​
    public void seteName(String eName) {
        this.eName = eName;
    }
​
    public String getJob() {
        return job;
    }
​
    public void setJob(String job) {
        this.job = job;
    }
​
    public int getMgr() {
        return mgr;
    }
​
    public void setMgr(int mgr) {
        this.mgr = mgr;
    }
​
    public String getHireDate() {
        return hireDate;
    }
​
    public void setHireDate(String hireDate) {
        this.hireDate = hireDate;
    }
​
    public double getSal() {
        return sal;
    }
​
    public void setSal(double sal) {
        this.sal = sal;
    }
​
    public double getComm() {
        return comm;
    }
​
    public void setComm(double comm) {
        this.comm = comm;
    }
​
    public int getDeptNo() {
        return deptNo;
    }
​
    public void setDeptNo(int deptNo) {
        this.deptNo = deptNo;
    }
}
​

3.编写数据和Java代码交互逻辑

  • 定义业务接口
复制代码
package com.pyb.dao;
​
import com.pyb.pojo.Emp;
import java.sql.SQLException;
import java.util.List;
/**
 * @version 1.0
 * @Author 彭彦彬
 * @Date 2024/12/25 10:17
 * @注释
 */
public interface EmpDao {
    /**
     * 获取所有用户数据
     * @return
     */
    List<Emp> list() throws SQLException;
​
    /**
     * 查询员工信息通过姓名
     * @param name
     * @return
     */
    Emp selectEmpByName(String name) throws SQLException;
    /**
     * 添加員工信息
     * @param emp
     */
    int addEmp(Emp emp);
    int deleteEmp(Emp emp);
    List<Emp> selectEmpByLike(Emp emp,int page,int limit);
    long countEmpByLike(Emp emp);
}
​
  • 实现业务接口
复制代码
package com.pyb.dao.daoImpl;
import com.pyb.dao.EmpDao;
import com.pyb.pojo.Emp;
import com.pyb.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
 * @version 1.0
 * @Author 彭彦彬
 * @Date 2024/12/25 10:19
 */
public class EmpDaoImpl implements EmpDao {
    @Override
    public List<Emp> list() throws SQLException {
        String sql = "SELECT * FROM emp";
        List<Emp> list = new ArrayList<>();
​
        // 使用 try-with-resources 确保资源自动关闭
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
​
            while (rs.next()) {
                int empno = rs.getInt("empno");
                String ename = rs.getString("ename");
                String job = rs.getString("job");
                int mgr = rs.getInt("mgr");
                String hiredate = rs.getString("hiredate"); // 如果 hiredate 是日期类型
                double sal = rs.getDouble("sal");
                double comm = rs.getDouble("comm");
                int deptno = rs.getInt("deptno");
​
                list.add(new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno));
            }
        } catch (SQLException e) {
            // 记录详细的错误信息,以便于调试
            e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
            throw e; // 或者抛出自定义异常
        }
        return list;
    }
    @Override
    public Emp selectEmpByName(String name) throws SQLException {
        String sql = "SELECT * FROM emp WHERE ename = ?";
​
        // 使用 try-with-resources 确保资源自动关闭
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
​
            ps.setString(1, name);
​
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    int empno = rs.getInt("empno");
                    String ename = rs.getString("ename");
                    String job = rs.getString("job");
                    int mgr = rs.getInt("mgr");
                    String hiredate = rs.getString("hiredate"); // 如果 hiredate 是日期类型
                    double sal = rs.getDouble("sal");
                    double comm = rs.getDouble("comm");
                    int deptno = rs.getInt("deptno");
​
                    return new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
                }
            }
​
            // 如果没有找到员工,则返回 null
            return null;
        } catch (SQLException e) {
            // 记录详细的错误信息,以便于调试
            e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
            throw e; // 或者抛出自定义异常
        }
    }
    @Override
    public int addEmp(Emp emp) {
        String sql="insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)values(?,?,?,?,?,?,?)";
        int effect=0;
        // 使用 try-with-resources 确保资源自动关闭
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
​
            ps.setString(1,emp.geteName());
            ps.setString(2,emp.getJob());
            ps.setInt(3,emp.getMgr());
            ps.setString(4,emp.getHireDate());
            ps.setDouble(5, emp.getSal());
            ps.setDouble(6,emp.getComm());
            ps.setInt(7,emp.getDeptNo());
            effect=ps.executeUpdate();
        } catch (SQLException e) {
            // 记录详细的错误信息,以便于调试
            e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
        }
        return effect;
    }
    @Override
    public int deleteEmp(Emp emp) {
        String sql = "DELETE FROM emp WHERE empno = ?";
        int affectedRows = 0;
​
        // 使用 try-with-resources 确保资源自动关闭
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
​
            ps.setInt(1, emp.getEmpNo());
​
            affectedRows = ps.executeUpdate();
​
            if (affectedRows == 0) {
                System.out.println("Warning: No rows were deleted for empno=" + emp.getEmpNo());
                // 可选择抛出自定义异常或返回特定值以表示未找到要删除的记录
            } else {
                System.out.println("Employee with empno=" + emp.getEmpNo() + " deleted successfully.");
            }
​
        } catch (SQLException e) {
            // 记录详细的错误信息,以便于调试
            e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
            // 抛出自定义异常或进行其他适当的错误处理
            throw new RuntimeException("Database error occurred while deleting employee.", e);
        }
        return affectedRows;
    }
​
    @Override
    public List<Emp> selectEmpByLike(Emp emp, int page, int limit) {
        // Adjust the SQL query to support pagination using LIMIT and OFFSET
        String sql = "SELECT * FROM emp WHERE ename LIKE ? OR job LIKE ? LIMIT ? OFFSET ?";
        List<Emp> list = new ArrayList<>();
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
            // Set parameters with wildcards for the LIKE clause
            ps.setString(1, "%" + emp.geteName() + "%");
            ps.setString(2, "%" + emp.getJob() + "%");
​
            // Calculate offset based on page number and limit
            int offset = (page - 1) * limit;
            ps.setInt(3, limit);
            ps.setInt(4, offset);
​
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    int empno = rs.getInt("empno");
                    String ename = rs.getString("ename");
                    String job = rs.getString("job");
                    int mgr = rs.getInt("mgr");
                    String hiredate = rs.getString("hiredate"); // Assuming hiredate is a DATE type in database
                    double sal = rs.getDouble("sal");
                    Double comm = rs.getDouble("comm"); // Use Double to handle NULL values
                    int deptno = rs.getInt("deptno");
​
                    // Handle possible null values for comm
                    if (rs.wasNull()) {
                        comm = null;
                    }
                    list.add(new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno));
                }
            }
        } catch (SQLException e) {
            // Log the exception using a logging framework in production code
            e.printStackTrace();
            // You may want to throw or handle the exception here
        }
        return list; // Return the populated list
    }
​
    @Override
    public long countEmpByLike(Emp emp) {
        String sql = "SELECT COUNT(*) FROM emp WHERE ename LIKE ? OR job LIKE ?";
        try (Connection con = JdbcUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
​
            // Set parameters with wildcards for the LIKE clause
            ps.setString(1, "%" + emp.geteName() + "%");
            ps.setString(2, "%" + emp.getJob() + "%");
​
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    return rs.getLong(1);
                }
            }
        } catch (SQLException e) {
            // Log the exception using a logging framework in production code
            e.printStackTrace();
        }
        return 0L;
    }
}
​
​
​
​
​
​
​
  • 编写服务层接口
复制代码
package com.pyb.service;
​
/**
 * @version 1.0
 * @Author 彭彦彬
 * @Date 2024/12/25 14:22
 * @注释
 */
import com.pyb.pojo.Emp;
import java.sql.SQLException;
import java.util.List;
public interface EmpService {
    List<Emp> selectEmpByLike(Emp emp, int page, int limit) throws SQLException;
    long countEmpByLike(Emp emp) throws SQLException;
}
​
  • 编写服务层实现类
复制代码
package com.pyb.service.serviceImpl;
​
import com.pyb.dao.EmpDao;
import com.pyb.dao.daoImpl.EmpDaoImpl;
import com.pyb.pojo.Emp;
import com.pyb.service.EmpService;
import java.sql.SQLException;
import java.util.List;
public class EmpServiceImpl implements EmpService {
    private final EmpDao empDao = new EmpDaoImpl();
    @Override
    public List<Emp> selectEmpByLike(Emp emp, int page, int limit) throws SQLException {
        return empDao.selectEmpByLike(emp, page, limit);
    }
    @Override
    public long countEmpByLike(Emp emp) throws SQLException {
        return empDao.countEmpByLike(emp);
    }
}
  • 编写控制层实现页面控制
复制代码
package com.pyb.controller;
​
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pyb.service.EmpService;
​
import com.pyb.pojo.Emp;
import com.pyb.service.serviceImpl.EmpServiceImpl;
​
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.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/api/likeEmp")
public class EmpLikeServlet extends HttpServlet {
    private final EmpService empService = new EmpServiceImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        handleRequest(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        handleRequest(req, resp);
    }
​
    private void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // 处理请求编码
            req.setCharacterEncoding("utf-8");
            resp.setContentType("application/json;charset=UTF-8");
            resp.setHeader("Access-Control-Allow-Origin", "*"); // 生产环境中应限制到具体域名
            resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            resp.setHeader("Access-Control-Max-Age", "3600");
            resp.setHeader("Access-Control-Allow-Headers", "Content-Type");
​
            // 解析分页参数
            int page = Integer.parseInt(req.getParameter("page") != null ? req.getParameter("page") : "1");
            int limit = Integer.parseInt(req.getParameter("limit") != null ? req.getParameter("limit") : "2");
​
            // 解析检索参数
            String ename = req.getParameter("ename");
            String job = req.getParameter("job");
​
            // 调用Service层
            List<Emp> list = empService.selectEmpByLike(new Emp(ename, job), page, limit);
            long totalUsers = empService.countEmpByLike(new Emp(ename, job));
​
            // 构建响应对象
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("users", list);
            responseData.put("total", totalUsers);
            responseData.put("page", page);
            responseData.put("limit", limit);
            if (ename != null) responseData.put("ename", ename);
            if (job != null) responseData.put("job", job);
​
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(resp.getWriter(), responseData);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

启动服务部署到tomcat,用postman测试接口

复制代码
http://localhost:8080/api/likeEmp?ename=a
  • 测试结果

4.编写前端页面,实现前后端数据交互

  • html页面
复制代码
<template>
  <div class="employee-manager">
    <!-- 现有的表格和分页组件 -->
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>员工列表</span>
          <!-- 检索框 -->
          <el-input v-model="searchEname" placeholder="请输入姓名" style="width: 200px; margin-right: 10px;"></el-input>
          <el-input v-model="searchJob" placeholder="请输入岗位" style="width: 200px; margin-right: 10px;"></el-input>
          <el-button type="primary" @click="fetchData">搜索</el-button>
          <el-button type="info" @click="resetSearch">重置</el-button>
          <el-button type="primary" @click="openAddEmployeeDialog">添加员工</el-button>
        </div>
      </template>
      <el-table :data="paginatedData" style="width: 100%; margin-top: 20px;" stripe>
        <el-table-column prop="empNo" label="ID" width="100" />
        <el-table-column prop="eName" label="姓名" width="100" />
        <el-table-column prop="job" label="岗位" width="100" />
        <el-table-column prop="mgr" label="上级编号" />
        <el-table-column prop="hireDate" label="入职日期" width="200"/>
        <el-table-column prop="sal" label="月薪" width="100"/>
        <el-table-column prop="comm" label="奖金" />
        <el-table-column prop="deptNo" label="部门编号" />
    
​
        <el-table-column fixed="right" label="操作" width="180">
          <template #default="scope">
            <el-button size="small" type="danger" @click="deleteEmployee(scope.row.empNo)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
​
      <el-pagination
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalItems"
        :page-size="pageSize"
        :current-page="currentPage"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :page-sizes="[3, 6, 9, 12]"
        style="margin-top: 20px;"
      >
      </el-pagination>
    </el-card>
​
    <!-- 添加员工对话框 -->
    <el-dialog v-model="dialogVisible" title="添加员工" width="30%">
      <el-form :model="employeeForm" label-width="100px" class="add-employee-form">
        <el-form-item label="ID">
          <el-input v-model="employeeForm.id" placeholder="请输入ID"></el-input>
        </el-form-item>
        <el-form-item label="姓名">
          <el-input v-model="employeeForm.name" placeholder="请输入姓名"></el-input>
        </el-form-item>
        <el-form-item label="职位">
          <el-input v-model="employeeForm.position" placeholder="请输入职位"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="addEmployee">确认添加</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
  • css样式页面
复制代码
<style scoped>
.employee-manager {
  padding: 20px;
}
​
.box-card {
  width: 100%;
}
​
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
​
.add-employee-form {
  max-width: 400px;
  margin: auto;
}
​
.el-table {
  border-radius: 8px;
  overflow: hidden;
}
​
.el-pagination {
  text-align: center;
}
​
.dialog-footer {
  text-align: right;
}
</style>
  • 和后台交互的script代码
复制代码
<script lang="js" setup>
import { ref, onMounted, computed } from 'vue';
import axios from 'axios';
import { ElMessage } from 'element-plus'; // 局部引入 ElMessage
​
const tableData = ref([]); // 使用 ref 创建响应式数据源
const totalItems = ref(0);
const currentPage = ref(1);
const pageSize = ref(3);
​
// 表单数据模型
const employeeForm = ref({
  id: '',
  name: '',
  position: ''
});
​
// 对话框可见性
const dialogVisible = ref(false);
​
// 检索条件
const searchEname = ref('');
const searchJob = ref('');
​
// 计算属性,用于根据当前页码和每页大小获取分页后的数据
const paginatedData = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value;
  const end = start + pageSize.value;
  return tableData.value;
});
​
const fetchData = async () => {
  try {
    const response = await axios.get('http://localhost:8080/api/likeEmp', {
      params: {
        page: currentPage.value,
        limit: pageSize.value,
        ename: searchEname.value,
        job: searchJob.value
      }
    });
    const { users, total } = response.data;
    tableData.value = users.map(user => ({ ...user, id: user.id, name: user.name, position: user.position }));
    totalItems.value = total; // 更新总条目数
  } catch (error) {
    console.error('Error fetching data:', error);
  }
};
​
onMounted(() => {
  fetchData(); // 组件挂载时自动加载数据
});
​
const handleSizeChange = (newSize) => {
  pageSize.value = newSize;
  fetchData();
};
​
const handleCurrentChange = (newPage) => {
  currentPage.value = newPage;
  fetchData();
};
​
// 打开添加员工对话框的方法
const openAddEmployeeDialog = () => {
  dialogVisible.value = true;
};
​
// 关闭对话框的方法
const closeDialog = () => {
  dialogVisible.value = false;
  Object.assign(employeeForm.value, {
    id: '',
    name: '',
    position: ''
  });
};
​
// 添加员工的方法
const addEmployee = async () => {
  try {
    const response = await axios.post('http://localhost:8080/api/emp', employeeForm.value, {
      headers: {
        'Content-Type': 'application/json'
      }
    });
    console.log('Employee added successfully:', response.data);
    // 关闭对话框并清空表单
    closeDialog();
    // 刷新表格数据
    fetchData();
  } catch (error) {
    console.error('Error adding employee:', error);
  }
};
​
// 删除员工的方法
const deleteEmployee = async (empNo) => {
  try {
    const response = await axios.delete(`http://localhost:8080/api/delEmp`, {
      params: {
        empNo: empNo
      }
    });
    console.log('Employee deleted successfully:', response.data.message);
    ElMessage({
      message: response.data.message,
      type: response.data.success ? 'success' : 'error'
    });
    // 刷新表格数据
    fetchData();
  } catch (error) {
    console.error('Error deleting employee:', error);
    ElMessage({
      message: '删除员工时出错',
      type: 'error'
    });
  }
};
​
// 重置检索条件的方法
const resetSearch = () => {
  searchEname.value = '';
  searchJob.value = '';
  fetchData();
};
</script>
  • 实现效果

相关推荐
晨航17 小时前
5个实用的设计相关的AI网站
人工智能·平面·交互
梓贤Vigo2 天前
【Axure高保真原型】计时秒表
交互·产品经理·axure·原型·中继器
m0_748256342 天前
QWebChannel实现与JS的交互
java·javascript·交互
264玫瑰资源库3 天前
从零开始C++棋牌游戏开发之第四篇:牌桌界面与交互实现
开发语言·c++·交互
温轻舟3 天前
前端开发 之 12个鼠标交互特效上【附完整源码】
开发语言·前端·javascript·css·html·交互·温轻舟
~央千澈~3 天前
优雅草央千澈-关于蓝湖如何快速的标注交互原型是如何使用的-如何使用蓝湖设计交互原型和整个软件项目的流程逻辑-实践项目详细说明
ui·交互·蓝湖
乐闻x5 天前
VSCode 插件开发实战(二):自定义插件与编辑器交互技巧
vscode·编辑器·交互
万物得其道者成7 天前
构建健壮的 Axios 请求管理器:提升 React 应用的 API 交互体验
前端·react.js·交互
小小怪下士yeah8 天前
探秘 JSON:数据交互的轻盈使者
okhttp·json·交互