开学考试--仓储管理系统

开学测试
设计一个仓储管理系统原型系统,该系统支持多个仓库的设立。统一设立物资台账,物资台账需包含物资编码、物资名称、规格、材质、供应商、品牌、物资分类,用户可以自定义物资的物资分类。需限制不同的物资名称、规格、材质的物资不能设立相同的物资编码。仓库人员可进行入库作业、出库作业业务。入库单、出库单的业务单据编码系统自动生成,不能手工录入,可以采用年月日+流水号的方式。系统可查询按物资编码的库存信息、按物资分类汇总的库存信息、入库单信息、出库单信息。
一步一步来

先理解业务逻辑 按照需求建3张所需的表,分别是用户--用于区分不同身份的用户--,仓库和台账表

MySQL
create database  db666;
use  db666;
create table user(
username varchar(255),
password varchar(255),
usertype enum('yuangong','guanli')
);
insert into user value('yuangong','123456','yuangong');
insert into user value('guanli','123456','guanli');
select * from user;
CREATE TABLE warehouse (  
    id INT AUTO_INCREMENT PRIMARY KEY,  
    location VARCHAR(100) NOT NULL,  
    stored_quantity INT NOT NULL,  
    remaining_space INT NOT NULL,  
    total_space INT NOT NULL,  
    CHECK (remaining_space >= 0),  
    CHECK (stored_quantity >= 0),  
    CHECK (total_space > 0)  
);
CREATE TABLE inventory_log (  
    log_id VARCHAR(12) PRIMARY KEY,  -- 台账编号,格式为 YYYYMMDDXXXX  
    operation_type ENUM('入库', '出库') NOT NULL,  -- 操作类别  
    quantity INT NOT NULL,  -- 数量  
    unit VARCHAR(20) NOT NULL,  -- 计量单位  
    storage_location VARCHAR(100) NOT NULL,  -- 存放地点(仓库号)  
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP  -- 创建时间  
);
然后像往常一样添一个新项目,获取所需依赖. 先写用户登录部分 大致步骤:

1.获取用户输入:从HTTP请求中获取username和password参数。

2.数据库配置:加载MyBatis配置文件,创建数据库会话。

3.查询用户:使用UserMapper调用selectUser方法,根据用户名和密码查询用户信息。

4.验证用户:检查查询结果,判断用户是否存在且密码是否正确。

5.跳转页面:根据用户类型(员工或经理)跳转到相应的页面;若用户不存在或类型未知,则跳转到错误页面。

和MySQL中的user表对应写一个user实体类--我们用user_type来区分不同身份的用户,登陆时用其判断.

user
package com.stdu.pojo;

public class User {
    private String username;
    private String password;
    private String usertype; // 新增 user_type 属性

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    // Getter 和 Setter 方法
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUser_type() {
        return usertype;
    }

    public void setUser_type(String user_type) {
        this.usertype = user_type;
    }
}
然后写servlet,用于获取用户输入的username和password信息
shenfenservlet
package com.stdu.Servlet;

import com.stdu.mapper.UserMapper;
import com.stdu.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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.InputStream;

@WebServlet("/SelectUser")
public class ShenfenServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(com.stdu.mapper.UserMapper.class);

        // 创建 User 对象根据用户名和密码查询
        User user = new User(username, password);
        User foundUser = userMapper.selectUser(user); // 假设 selectUser 方法正确实现并返回匹配的用户

        sqlSession.close();

        if (foundUser != null) {
            String userType = foundUser.getUser_type(); // 假设 User 类中有 getUser_type 方法

            // 根据用户类型进行不同的跳转
            switch (userType) {
                case "yuangong":
                    resp.sendRedirect("yuangong.jsp"); // 员工
                    break;
                case "guanli":
                    resp.sendRedirect("guanli.jsp"); // 经理
                    break;
                default:
                    resp.sendRedirect("error.jsp?message=未知用户类型");
                    break;
            }
        } else {
            // 用户不存在或认证失败,重定向回登录页面
            resp.sendRedirect("login.jsp?message=用户名或密码错误");
        }
    }
}
之后写一个user接口用于获取用户输入的信息
usermapper(接口)
package com.stdu.mapper;

import com.stdu.pojo.User;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
    @Select("select *from user where username=#{username}and password=#{password}")
    User selectUser(User user);
}

写一个登录界面,login.jsp 在web.xml加上"login.jsp"可设置程序启动的起始页.

login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<html>
<head>
    <title>登录</title>
    <style>
        /* 整体页面背景设置为淡蓝色 */
        body {
            background-color: #e6f2ff;
            font-family: Arial, sans-serif;
            display: flex; /* 使用Flexbox布局 */
            justify-content: center; /* 水平居中 */
            align-items: center; /* 垂直居中 */
            height: 100vh; /* 使内容在视口的高度中居中 */
            margin: 0; /* 清除默认外边距 */
        }

        /* 容器样式 */
        .form-container {
            background-color: white; /* 表单背景色 */
            padding: 20px; /* 内边距 */
            border-radius: 10px; /* 圆角 */
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 投影效果 */
            text-align: center; /* 文本居中 */
            width: 300px; /* 设置容器宽度 */
        }

        /* 标题样式 */
        h1 {
            color: #004080;
            font-size: 28px; /* 设置字体大小 */
            margin-top: 0; /* 清除顶边距 */
            margin-bottom: 20px; /* 设置底边距 */
        }

        /* 输入框样式 */
        input[type="text"], input[type="password"] {
            margin: 10px 0; /* 上下边距 */
            padding: 10px; /* 内边距 */
            border: 1px solid #ccc; /* 边框 */
            border-radius: 5px; /* 圆角 */
            width: 100%; /* 宽度100% */
            box-sizing: border-box; /* 包括内边距和边框 */
        }

        /* 按钮样式 */
        input[type="submit"] {
            margin: 15px 0; /* 上下边距 */
            padding: 10px; /* 内边距 */
            border: none; /* 无边框 */
            border-radius: 5px; /* 圆角 */
            background-color: #0073e6; /* 按钮背景色 */
            color: white; /* 按钮文字颜色 */
            cursor: pointer; /* 鼠标指针样式 */
            width: 100%; /* 宽度100% */
        }

        /* 鼠标悬停在按钮上的样式变化 */
        input[type="submit"]:hover {
            background-color: #0059b3; /* 悬停时背景颜色 */
        }


    </style>
</head>
<body>
    <div class="form-container">
        <h1>登录</h1>
        <form method="POST" action="/Test/SelectUser">
            <p>账号 <input type="text" name="username" required></p>
            <p>密码 <input type="password" name="password" required></p>
            <input type="submit" value="登录">
        </form>
    </div>
</body>
</html>

根据不同身份跳转到不同的功能菜单
员工页

yuangong.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<html>
<head>
    <meta charset="UTF-8">
    <title>员工</title>
    <style>
        /* 整体页面背景设置为淡蓝色 */
        body {
            background-color: #e6f2ff;
            font-family: Arial, sans-serif;
            display: flex; /* 使用 Flexbox */
            flex-direction: column; /* 垂直排列 */
            align-items: center; /* 水平居中对齐 */
        }

        /* 标题样式,居中、设置颜色和字体大小 */
        h1 {
            text-align: center;
            color: #004080;
            font-size: 32px;
            margin-top: 50px;
        }

        /* 按钮通用样式,设置边距、边框、圆角、背景色、文字颜色等 */
        button {
            margin: 15px;
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            background-color: #0073e6;
            color: white;
            cursor: pointer;
            width:300px;
        }

        /* 鼠标悬停在按钮上时的样式变化 */
        button:hover {
            background-color: #0059b3;
        }
    </style>
    <script>
        function ruku() {
            console.log("按钮被点击"); 
            window.location.href = "/Test/ruku.jsp"; // 使用完整路径
        }

        function chuku() {
            window.location.href = "/Test/chuku.jsp"; // 使用完整路径
        }

        function chaxun() { // 修改函数名以避免保留字
            window.location.href = "/Test/chaxun.jsp"; // 使用完整路径
        }

        function tongji() {
            window.location.href = "/Test/tongji.jsp"; // 使用完整路径
        }
    </script>
</head>

<body>
<h1>选择所需功能</h1>
<button onclick="ruku()">新增入库</button>
<button onclick="chuku()">新增出库</button>
<button onclick="chaxun()">记录查询</button>
<button onclick="tonaji()">记录统计</button>
</body>

</html>
管理页--为了美观使用 Flexbox把功能列表设置成两列
guanli.jsp
<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<html>
<head>
    <meta charset="UTF-8">
    <title>库管</title>
    <style>
        body {
            background-color: #e6f2ff;
            font-family: Arial, sans-serif;
            display: flex; /* 使用 Flexbox */
            flex-direction: column; /* 垂直排列 */
            align-items: center; /* 水平居中对齐 */
        }

        h1 {
            text-align: center;
            color: #004080;
            font-size: 32px;
            margin-top: 50px;
        }

        .button-container {
            display: grid;
            grid-template-columns: repeat(2, 1fr); /* 创建两列 */
            gap: 10px; /* 列间距 */
            width: 500px; /* 设置容器宽度 */
        }

        button {
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            background-color: #0073e6;
            color: white;
            cursor: pointer;
        }

        button:hover {
            background-color: #0059b3;
        }
    </style>
    <script>
        function xinwuzi() {
            console.log("撰写日报按钮被点击");
            window.location.href = "/Test/xinwuzi.jsp";
        }

        function gaiwuzi() {
            window.location.href = "/Test/gaiwuzi.jsp";
        }

        function shanwuzi() {
            window.location.href = "/Test/shanwuzi.jsp";
        }

        function xincangku() {
            window.location.href = "/Test/xincangku.jsp";
        }

        function gaicangku() {
            window.location.href = "/Test/gaicangku.jsp";
        }

        function shancangku() {
            window.location.href = "/Test/shancangku.jsp";
        }
    </script>
</head>

<body>
<h1>选择所需功能</h1>
<div class="button-container">
    <button onclick="xinwuzi()">新增物资</button>
    <button onclick="xincangku()">新增仓库</button>
    <button onclick="gaiwuzi()">修改物资</button>
    <button onclick="gaicangku()">修改仓库</button>
    <button onclick="shanwuzi()">删除物资</button>
    <button onclick="shancangku()">删除仓库</button>
</div>
</body>
</html>
至此实现了管理员、仓库管理人员统一登录界面登录后,显示各自不同的菜单项。

接着写管理员的仓库的新增、删除、修改基本信息管理,可以实现对物资类别的新增、删除、修改基本信息管理
仓库的增删改
先对应MySQL中的表写一个对应的实体类

Warehouse.java
package com.stdu.pojo;

public class Warehouse {
    private String location;
    private int storedQuantity;
    private int remainingSpace;
    private int totalSpace;

    // 添加一个构造函数
    public Warehouse(String location, int storedQuantity, int remainingSpace, int totalSpace) {
        this.location = location;
        this.storedQuantity = storedQuantity;
        this.remainingSpace = remainingSpace;
        this.totalSpace = totalSpace;
    }

    // 可以添加其他的 getter 和 setter 方法

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public int getStoredQuantity() {
        return storedQuantity;
    }

    public void setStoredQuantity(int storedQuantity) {
        this.storedQuantity = storedQuantity;
    }

    public int getRemainingSpace() {
        return remainingSpace;
    }

    public void setRemainingSpace(int remainingSpace) {
        this.remainingSpace = remainingSpace;
    }

    public int getTotalSpace() {
        return totalSpace;
    }

    public void setTotalSpace(int totalSpace) {
        this.totalSpace = totalSpace;
    }
}
对应的jsp文件,用来接收用户输入的信息
xincangku.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>仓库信息输入</title>
    <style>
        /* 整体页面背景设置为淡蓝色 */
        body {
            background-color: #e6f2ff;
            font-family: Arial, sans-serif;
            display: flex; /* 使用Flexbox布局 */
            justify-content: center; /* 水平居中 */
            align-items: center; /* 垂直居中 */
            height: 100vh; /* 使内容在视口的高度中居中 */
            margin: 0; /* 清除默认外边距 */
        }

        /* 容器样式 */
        .form-container {
            background-color: white; /* 表单背景色 */
            padding: 20px; /* 内边距 */
            border-radius: 10px; /* 圆角 */
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 投影效果 */
            text-align: center; /* 文本居中 */
            width: 350px; /* 设置容器宽度 */
        }

        /* 标题样式 */
        h1 {
            color: #004080;
            font-size: 28px; /* 设置字体大小 */
            margin-top: 0; /* 清除顶边距 */
            margin-bottom: 20px; /* 设置底边距 */
        }

        /* 输入框样式 */
        .input-group {
            margin: 15px 0; /* 上下边距 */
            text-align: left; /* 左对齐 */
        }

        .input-group label {
            display: block; /* 块状显示 */
            margin-bottom: 5px; /* 下方空隙 */
            color: #333; /* 字体颜色 */
            font-weight: bold; /* 加粗 */
        }

        input[type="text"], input[type="number"] {
            margin: 10px 0; /* 上下边距 */
            padding: 10px; /* 内边距 */
            border: 1px solid #ccc; /* 边框 */
            border-radius: 5px; /* 圆角 */
            width: 100%; /* 宽度100% */
            box-sizing: border-box; /* 包括内边距和边框 */
        }

        /* 提示信息样式 */
        .tip {
            color: #666; /* 字体颜色 */
            font-size: 14px; /* 字体大小 */
            margin-top: 5px; /* 上方空隙 */
        }

        /* 按钮样式 */
        .submit-btn {
            margin: 15px 0; /* 上下边距 */
            padding: 10px; /* 内边距 */
            border: none; /* 无边框 */
            border-radius: 5px; /* 圆角 */
            background-color: #0073e6; /* 按钮背景色 */
            color: white; /* 按钮文字颜色 */
            cursor: pointer; /* 鼠标指针样式 */
            width: 100%; /* 宽度100% */
            font-size: 16px; /* 字体大小 */
            font-weight: bold; /* 加粗 */
        }

        /* 鼠标悬停在按钮上的样式变化 */
        .submit-btn:hover {
            background-color: #0059b3; /* 悬停时背景颜色 */
        }

        /* 错误提示样式 */
        .error {
            color: #ff4444; /* 字体颜色 */
            margin-top: 5px; /* 上方空隙 */
            text-align: left; /* 左对齐 */
            font-size: 14px; /* 字体大小 */
        }
    </style>
</head>
<body>
    <div class="form-container">
        <h1>创建新仓库</h1>
        <form method="POST" action="/Test/insertWarehouse">
            <div class="input-group">
                <label for="location">仓库位置:</label>
                <input type="text" id="location" name="location" placeholder="请输入仓库的位置" required>
                <div class="tip">例如:北京、上海、广州等</div>
            </div>

            <div class="input-group">
                <label for="storedQuantity">存储数量:</label>
                <input type="number" id="storedQuantity" name="storedQuantity" min="0" placeholder="请输入存储数量" required>
                <div class="tip">新仓库一般为0</div>
            </div>

            <div class="input-group">
                <label for="remainingSpace">剩余空间:</label>
                <input type="number" id="remainingSpace" name="remainingSpace" min="0" placeholder="请输入剩余空间" required>
                <div class="tip">请输入一个非负整数</div>
            </div>

            <div class="input-group">
                <label for="totalSpace">总空间:</label>
                <input type="number" id="totalSpace" name="totalSpace" min="1" placeholder="请输入总空间" required>
                <div class="tip">请输入一个大于0的整数</div>
            </div>

            <button type="submit" class="submit-btn">创建仓库</button>
        </form>
        <div id="error" class="error"></div>
    </div>

    <script>
        document.getElementById('warehouseForm').addEventListener('submit', function(e) {
            e.preventDefault();

            const location = document.getElementById('location').value.trim();
            const storedQuantity = parseInt(document.getElementById('storedQuantity').value);
            const remainingSpace = parseInt(document.getElementById('remainingSpace').value);
            const totalSpace = parseInt(document.getElementById('totalSpace').value);

            // 输入验证
            if (!location) {
                showError('仓库位置不能为空!');
                return;
            }

            if (storedQuantity < 0) {
                showError('存储数量必须是非负数!');
                return;
            }

            if (remainingSpace < 0) {
                showError('剩余空间必须是非负数!');
                return;
            }

            if (totalSpace <= 0) {
                showError('总空间必须大于0!');
                return;
            }

            // 提交表单
            this.submit();
        });

        function showError(message) {
            const errorDiv = document.getElementById('error');
            errorDiv.textContent = message;
            setTimeout(() => {
                errorDiv.textContent = '';
            }, 3000);
        }
    </script>
</body>
</html>
写出仓库的mapper文件,Mapper的功能主要是定义数据库操作接口,用于将Java方法与SQL语句映射起来。在MyBatis框架中,Mapper接口与XML配置文件结合,实现数据的增删改查操作,从而在Service层与DAO层之间提供数据访问的桥梁。通过这种方式,Java代码与SQL代码实现了分离,提高了系统的可维护性和灵活性。
warehouse.mapper
package com.stdu.mapper;

import com.stdu.pojo.Warehouse;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface WarehouseMapper {

    @Insert("insert into warehouse (  location, storedQuantity,remainingSpace,totalSpace) " +
            "values (  #{location}, #{storedQuantity}, #{remainingSpace}, #{totalSpace})")
    int insertWarehouse(Warehouse warehouse);

    @Delete("delete from warehouse where id = #{id}")
    int deleteWarehouse(String id);

    @Update("update warehouse set name = #{name}, location = #{location}, capacity = #{capacity} where id = #{id}")
    int updateWarehouse(Warehouse warehouse);

    @Select("select * from warehouse where id = #{id}")
    Warehouse selectWarehouseById(String id);

    @Select("select * from warehouse")
    List<Warehouse> selectAllWarehouses();

    @Select("select * from warehouse where name like '%${name}%'")
    List<Warehouse> selectWarehouseByName(@Param("name") String name);
}
定义所需的函数写好接口 Servlet文件有以下功能: 1.接收请求:Servlet能接收来自客户端的HTTP请求,包括GET、POST等方法。 2.处理业务逻辑:Servlet执行服务器端的业务逻辑,例如查询数据库、处理数据、调用其他服务等。 3.生成响应:处理完成后,Servlet会生成相应的HTML、JSON或其他格式的数据,返回给客户端。 4.MVC模式中的Controller:在Model-View-Controller模式中,Servlet通常作为Controller,负责协调Model(数据处理)和View(展示层,如JSP)。 写出仓库操作的servlet文件
WarehouseServlet
package com.stdu.Servlet;

import com.stdu.mapper.WarehouseMapper;
import com.stdu.pojo.Warehouse; // 假设Warehouse实体类所在的包
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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.InputStream;

@WebServlet("/insertWarehouse")
public class WarehouseServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");


        // 创建Warehouse对象
        String location = req.getParameter("location");
        int storedQuantity = Integer.parseInt(req.getParameter("storedQuantity"));
        int remainingSpace = Integer.parseInt(req.getParameter("remainingSpace"));
        int totalSpace = Integer.parseInt(req.getParameter("totalSpace"));
        Warehouse warehouse = new Warehouse( location, storedQuantity, remainingSpace, totalSpace);


        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = null;
        try {
            sqlSession = sqlSessionFactory.openSession();
            WarehouseMapper warehouseMapper = sqlSession.getMapper(WarehouseMapper.class);
            // 假设UserMapper中有insertWarehouse方法,或者更名为合适的方法  
            warehouseMapper.insertWarehouse(warehouse);
            sqlSession.commit();
            // 返回成功信息  
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().println("仓库插入成功!");
        } catch (Exception e) {
            e.printStackTrace();
            // 处理异常,可以回滚事务  
            if (sqlSession != null) {
                sqlSession.rollback();
            }
            resp.getWriter().println("仓库插入失败,错误信息:" + e.getMessage());
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}
注意

mapper文件要部署到mybatis-config.xml

servlet文件要部署到web.xml


到此为止增加仓库的操作已经完成,删除修改只需完善servlet和mapper并写相应功能的页面即可.

posted @ 2025-04-19 18:35  3jingsh0u  阅读(31)  评论(0)    收藏  举报