图书管理系统【JavaWeb:部署开发环境、解决分类、图书、前台页面模块】

简介: 前言巩固Servlet+JSP开发模式,做一个比较完整的小项目.成果图该项目包含了两个部分,前台和后台。前台用于显示后台用于管理该项目可分为5个模块来组成:分类模块,用户模块,图书模块,购买模块,订单模块。

前言

巩固Servlet+JSP开发模式,做一个比较完整的小项目.

成果图

该项目包含了两个部分,前台和后台。

前台用于显示

这里写图片描述

后台用于管理

这里写图片描述

该项目可分为5个模块来组成:分类模块,用户模块,图书模块,购买模块,订单模块


搭建环境

建立包结构

这里写图片描述

导入开发包

这里写图片描述

前台分帧页面

  • index.jsp【没有body标签的】

  
  • head.jsp

欢迎来到购物中心

  • body是空白的jsp页面

  • 效果:

这里写图片描述


后台分帧页面

  • manager.jsp【嵌套了framset标签,也是没有body标签的】


  • head.jsp

后台管理

  • left.jsp


分类管理



图书管理

订单管理

  • body.jsp是空白的

  • 效果:

这里写图片描述

分帧的文件夹目录结构

这里写图片描述

值得注意的是:

  • 文件夹的名字不能使用“manager”,不然会出现:403 Access Denied错误
  • frameset标签是可以嵌套的,分列用“cols”,分行用“rows”

导入工具类和方法的代码

  • 过滤中文乱码数据
  • HTML转义
  • DAOFactory
  • JDBC连接池
  • UUID工具类
  • c3p0.xml配置文件

这些代码都可以在我的博客分类:代码库中找到!


分类模块

首先,我们来做分类模块吧

创建实体Category

    private String id;
    private String name;
    private String description;

    //各种setter、getter

在数据库创建表


CREATE TABLE category (

  id          VARCHAR(40) PRIMARY KEY,
  name        VARCHAR(10) NOT NULL UNIQUE ,
  description VARCHAR(255)


);

编写CategoryDAO


/**
 * 分类模块
 *  1:添加分类
 *  2:查找分类
 *  3:修改分类
 *
 *
 * */
public class CategoryImpl {

    public void addCategory(Category category) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "INSERT INTO category (id, name, description) VALUES(?,?,?)";
        try {
            queryRunner.update(sql, new Object[]{category.getId(), category.getName(), category.getDescription()});

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Category findCategory(String id) {
        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
        String sql = "SELECT * FROM category WHERE id=?";

        try {
            Category category = (Category) queryRunner.query(sql, id, new BeanHandler(Category.class));

            return category;

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
 
    }

    public List getAllCategory() {
        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
        String sql = "SELECT * FROM category";

        try {
            List categories = (List) queryRunner.query(sql, new BeanListHandler(Category.class));

             return categories;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
     
    }
}

测试DAO


public class demo {

    @Test
    public void add() {

        Category category = new Category();
        category.setId("2");
        category.setName("数据库系列");
        category.setDescription("这是数据库系列");

        CategoryImpl category1 = new CategoryImpl();
        category1.addCategory(category);

    }

    @Test
    public void find() {

        String id = "1";
        CategoryImpl category1 = new CategoryImpl();
        Category category = category1.findCategory(id);

        System.out.println(category.getName());
    }
    @Test
    public void getAll() {


        CategoryImpl category1 = new CategoryImpl();
        List categories = category1.getAllCategory();

        for (Category category : categories) {
            System.out.println(category.getName());
        }
    }

}

抽取成DAO接口


public interface CategoryDao {
    void addCategory(Category category);

    Category findCategory(String id);

    List getAllCategory();
}

后台页面的添加分类

  • 在超链接上,绑定显示添加分类的页面

添加分类
  • 显示添加分类的JSP页面


分类名称:
分类描述:
  • 处理添加分类的Servlet

        if (method.equals("add")) {

            try {
                //把浏览器带过来的数据封装到bean中
                Category category = WebUtils.request2Bean(request, Category.class);
                category.setId(WebUtils.makeId());

                service.addCategory(category);
                request.setAttribute("message", "添加分类成功!");

            } catch (Exception e) {
                request.setAttribute("message","添加分类失败");
                e.printStackTrace();
            }
            request.getRequestDispatcher("/message.jsp").forward(request, response);

        }
  • 效果:

这里写图片描述


后台页面的查看分类

  • 在超链接上,绑定处理请求的Servlet

        else if (method.equals("look")) {

            List list = service.getAllCategory();
            request.setAttribute("list", list);
            request.getRequestDispatcher("/background/lookCategory.jsp").forward(request, response);

        } 
  • 显示分类页面的JSP



    暂时还没有分类数据哦,请你添加把



    
分类名字 分类描述 操作
${category.name} ${category.description} 删除 修改
  • 效果:

这里写图片描述


图书模块

分析

在设计图书管理的时候,我们应该想到:图书和分类是有关系的。一个分类可以对应多本图书。

为什么要这样设计?这样更加人性化,用户在购买书籍的时候,用户能够查看相关分类后的图书,而不是全部图书都显示给用户,让用户一个一个去找。

设计实体


    private String id;
    private String name;
    private String author;
    private String description;
    private double price;

    //记住图片的名称
    private String image;

    //记住分类的id
    private String category_id;

    //各种setter和getter

设计数据库表


CREATE TABLE book (
  id          VARCHAR(40) PRIMARY KEY,
  name        VARCHAR(10) NOT NULL UNIQUE,
  description VARCHAR(255),
  author      VARCHAR(10),
  price       FLOAT,
  image       VARCHAR(100),
  category_id VARCHAR(40),
  CONSTRAINT category_id_FK FOREIGN KEY (category_id) REFERENCES category (id)

);

编写DAO



/**
 * 图书模块
 * 1:添加图书
 * 2:查看图书
 * 3:查找图书的分页数据【图书一般来说有很多,所以要分页】
 */
public class BookDaoImpl {

    public void addBook(Book book) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "INSERT INTO book (id,name,description,author,price,image,category_id) VALUES(?,?,?,?,?,?,?)";
        try {
            queryRunner.update(sql, new Object[]{book.getId(), book.getName(), book.getDescription(), book.getAuthor(), book.getPrice(),book.getImage(), book.getCategory_id()});

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Book findBook(String id) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM book WHERE id=?";

        try {
            return (Book) queryRunner.query(sql, id, new BeanHandler(Book.class));
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**得到图书的分页数据*/
    public List getPageData(int start, int end) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM book limit ?,?";

        try {
            return (List) queryRunner.query(sql, new BeanListHandler(Book.class), new Object[]{start, end});
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**得到按照分类图书的分页数据*/
    public List getPageData(int start, int end,String category_id) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        //WHERE字句在limit字句的前边,注意Object[]的参数位置!
        String sql = "SELECT * FROM book WHERE category_id=? limit ?,?";

        try {
            return (List) queryRunner.query(sql, new BeanListHandler(Book.class), new Object[]{ category_id,start, end});
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 得到图书的总记录数
     */
    public int getTotalRecord() {
        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT COUNT(*) FROM book";

        try {
            return (int) queryRunner.query(sql, new ScalarHandler());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 得到分类后图书的总记录数
     * getCategoryTotalRecord
     */
    public long getCategoryTotalRecord(String category_id) {

        try {
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

            String sql = "SELECT COUNT(*) FROM book WHERE category_id=?";
            return (long) queryRunner.query(sql, category_id, new ScalarHandler());

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}

测试DAO


public class BookDemo {

    BookDaoImpl bookDao = new BookDaoImpl();


    @Test

    public void add() {
        Book book = new Book();
        book.setId("5");
        book.setName("SQLServer");
        book.setAuthor("我也不知道");
        book.setImage("33333332432");
        book.setPrice(33.22);
        book.setDescription("这是一本好书");
        book.setCategory_id("2");

        bookDao.addBook(book);
    }

    @Test
    public void look() {

        List bookList = bookDao.getPageData(3, 3);

        for (Book book : bookList) {
            System.out.println(book.getName());
        }

        List books = bookDao.getPageData(0,2,"2");

        for (Book book : books) {
            System.out.println(book.getName());

        }
    }

    @Test
    public void find() {
        String id = "2";
        Book book = bookDao.findBook(id);

        System.out.println(book.getName());
    }


}

抽取成DAO接口


public interface BookDao {
    void addBook(Book book);

    Book findBook(String id);

    List getPageData(int start, int end);

    List getPageData(int start, int end, String category_id);

    long getTotalRecord();

    long getCategoryTotalRecord(String category_id);
}

编写Service层


    /*添加图书*/
    public void addBook(Book book) {
        bookDao.addBook(book);

    }

    /*查找图书*/
    public Book findBook(String id) {
        return bookDao.findBook(id);
    }

    /*查找图书*/
    public Book findBook(String id) {
        return bookDao.findBook(id);
    }

    /*获取图书的分页数据*/
    public Page getPageData(String pageNum) {
        
        Page page=null;
        if (pageNum == null) {
            page = new Page(1, bookDao.getTotalRecord());
        } else {
            page = new Page(Integer.valueOf(pageNum), bookDao.getTotalRecord());
        }

        List books = bookDao.getPageData(page.getStartIndex(), page.getLinesize());
        page.setList(books);
        
        return page;

    }

    /*获取图书分类后的分页数据*/
    public Page getPageData(String currentPageCount,String category_id) {

        Page page=null;
        if (currentPageCount == null) {
            page = new Page(1, bookDao.getCategoryTotalRecord(category_id));
        } else {
            page = new Page(Integer.valueOf(currentPageCount), bookDao.getCategoryTotalRecord(category_id));
        }

        List books = bookDao.getPageData(page.getStartIndex(), page.getLinesize(), category_id);
        page.setList(books);
        return page;

    }

后台添加图书

后台要添加图书的时候,应该说明图书的类型是什么。

要想在显示添加图书的页面上知道全部类型的id,就要经过Servlet把类型的集合传送过去

绑定链接


添加图书

传送类型集合的Servlet


        String method = request.getParameter("method");
        BussinessServiceImpl service = new BussinessServiceImpl();

        if (method.equals("addUI")) {

            List list = service.getAllCategory();
            request.setAttribute("list", list);
            request.getRequestDispatcher("/background/addBook.jsp").forward(request, response);

        } 

显示JSP页面

图书名称:
作者:
图书价钱:
类型: ${category.name}
上传图片
详细描述

处理表单数据Servlet

 else if (method.equals("add")) { //上传文件和普通数据分割开,封装到Book对象上 Book book = uploadData(request); book.setId(WebUtils.makeId()); service.addBook(book); request.setAttribute("message", "添加图书成功"); request.getRequestDispatcher("/message.jsp").forward(request, response); } 
  • uploadData()方法代码
 private Book uploadData(HttpServletRequest request) { Book book = new Book(); try{ //1.得到解析器工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //2.得到解析器 ServletFileUpload upload = new ServletFileUpload(factory); //设置编码 upload.setHeaderEncoding("UTF-8"); //为上传表单,则调用解析器解析上传数据 List list = upload.parseRequest(request); //FileItem //遍历list,得到用于封装第一个上传输入项数据fileItem对象 for(FileItem item : list){ if(item.isFormField()){ //得到的是普通输入项 String name = item.getFieldName(); //得到输入项的名称 String value = item.getString("UTF-8"); //使用BeanUtils封装数据 BeanUtils.setProperty(book, name, value); }else{ //得到上传输入项 //得到上传文件名全路径 String filename = item.getName(); //截取文件名 filename = filename.substring(filename.lastIndexOf("\\")+1); InputStream in = item.getInputStream(); //得到上传数据 int len = 0; byte buffer[]= new byte[1024]; //如果没有这个目录,就创建它 String savepath = this.getServletContext().getRealPath("/image"); File file = new File(savepath); if (!file.exists()) { file.mkdir(); } FileOutputStream out = new FileOutputStream(savepath + "\\" + filename); while((len=in.read(buffer))>0){ out.write(buffer, 0, len); } //设置图片的名字 book.setImage(filename); in.close(); out.close(); //关闭临时文件 item.delete(); } } }catch (Exception e) { e.printStackTrace(); } return book; }
  • 效果:

这里写图片描述


后台显示图书模块

由于我们用的是分页技术,所以我们导入之前写过的Page类和jsp吧.....这些代码可以在我分类的代码库中找到

绑定超链接

 查看图书

Servlet处理请求

 else if (method.equals("look")) { String currentPageCount = request.getParameter("currentPageCount"); Page page = service.getPageData(currentPageCount); request.setAttribute("page",page); request.getRequestDispatcher("/background/listBook.jsp").forward(request, response); }

显示图书JSP页面

Servlet端传过来的是Page对象,而不是list集合

可以根据记载在Book对象的图片名称,弄一个超链接,超链接指向服务端的图片,这样就可以查看图片了!

 暂时还没有任何图书哦 
书名 作者 价钱 描述 图片 操作
${book.name} ${book.author} ${book.price} ${book.description} 查看图片 删除 修改

效果:

这里写图片描述


前台页面

看回我们前台页面的成果图,我们可以把整个body页面看成是三个div

  • body占整个div
  • 导航条是一个div
  • 显示图书的地方是一个div

这里写图片描述


设计好大概的布局

  • html代码引入css
 
  • HTML三个div
 
这是导航条
这是书籍的地方
这是页码
  • CSS代码:
 #body { position: relative; } #category { border: 1px solid #000; position: absolute; width: 300px; height: 400px; float: left; left: 200px; top: 70px;; } #bookandpages { border: 1px solid #000000; position: absolute; width: 600px; height: 600px;; float: left; left: 500px; margin-left: 50px; } #books { border: 1px solid #000; width: 600px; height: 550px;; } #page { border: 1px solid #000; position: absolute; height: 48px; width: 600px; } 
  • 大概的布局

这里写图片描述


IndexServlet

在显示首页的下部分的时候,应该先去寻找一个Servlet来把数据交给对应的JSP

因为我们的JSP一般都是放在WEB-INF下,是不能直接访问的。还有就是JSP往往是需要我们后台的数据的,因此我们使用Servlet来获取得到数据,再交由JSP来展示就最好不过了。

 
  • Servlet代码:
 //得到所有的分类数据,给body页面 BussinessServiceImpl service = new BussinessServiceImpl(); List categories = service.getAllCategory(); request.setAttribute("categories", categories); String currentPageCount = request.getParameter("currentPageCount"); //得到所有分类的图书,给body页面 Page page = service.getPageData(currentPageCount); request.setAttribute("page", page); request.getRequestDispatcher("/client/body.jsp").forward(request,response);

JSP显示数据

 
书籍分类 :
  • ${categories.name}
  • 书名:${book.name}
  • 价格:${book.price}
  • 作者:${book.author}
  • CSS代码:

    重要的是:如果div浮动都黏贴在一起了,那么在后边多加个div,用于清除浮动效果

     #body { position: relative; } #category { border: 1px solid #000; position: absolute; width: 300px; height: 400px; float: left; left: 200px; top: 70px;; } #bookandpages { border: 1px solid #000000; position: absolute; width: 780px; height: 538px;; float: left; left: 500px; margin-left: 50px; } #books{ margin-left: 50px; margin-top: 30px; } #image{ float: left; } #bookinfo{ float: left; } #page { height: 62px; width: 780px; position: fixed; margin-left: 549px; margin-top: 477px; text-align: center; line-height: 50px; }
    • 效果:

    这里写图片描述


    按照分类显示图书

    我们可以根据左边的导航条来显示相对应的分类图书。

    • Servlet代码:
     BussinessServiceImpl service = new BussinessServiceImpl(); String currentPageCount = request.getParameter("currentPageCount"); String category_id = request.getParameter("category_id"); Page page = service.getPageData(currentPageCount, category_id); List categories = service.getAllCategory(); request.setAttribute("page", page); request.setAttribute("categories", categories); request.getRequestDispatcher("/client/body.jsp").forward(request,response);

    效果:

    这里写图片描述


    如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y

    目录
    相关文章
    |
    4月前
    |
    机器学习/深度学习 人工智能 监控
    Java与AI模型部署:构建企业级模型服务与生命周期管理平台
    随着企业AI模型数量的快速增长,模型部署与生命周期管理成为确保AI应用稳定运行的关键。本文深入探讨如何使用Java生态构建一个企业级的模型服务平台,实现模型的版本控制、A/B测试、灰度发布、监控与回滚。通过集成Spring Boot、Kubernetes、MLflow和监控工具,我们将展示如何构建一个高可用、可扩展的模型服务架构,为大规模AI应用提供坚实的运维基础。
    372 0
    |
    5月前
    |
    JavaScript Java 大数据
    基于JavaWeb的销售管理系统设计系统
    本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
    存储 jenkins 持续交付
    698 2
    |
    7月前
    |
    机器学习/深度学习 分布式计算 Java
    Java 大视界 -- Java 大数据机器学习模型在遥感图像土地利用分类中的优化与应用(199)
    本文探讨了Java大数据与机器学习模型在遥感图像土地利用分类中的优化与应用。面对传统方法效率低、精度差的问题,结合Hadoop、Spark与深度学习框架,实现了高效、精准的分类。通过实际案例展示了Java在数据处理、模型融合与参数调优中的强大能力,推动遥感图像分类迈向新高度。
    |
    7月前
    |
    SQL 前端开发 Java
    JavaWeb 学习日记案例详解及 javaweb 完整项目案例实战指南
    本文介绍了一个基于Spring Boot的JavaWeb企业员工管理系统完整案例,涵盖部门管理、员工管理、登录、异常处理、事务管理及AOP等核心功能实现,结合CSDN相关技术文章,提供详细技术方案与应用实例,适合JavaWeb开发者学习与参考。
    433 0
    |
    7月前
    |
    Oracle Java 关系型数据库
    新手必看:Java 开发环境搭建之 JDK 与 Maven
    本文分享了 Java 学习中 JDK 安装配置与 Maven 使用的入门知识,涵盖 JDK 下载安装、环境变量设置、Maven 安装配置及本地仓库与镜像设置,帮助新手快速搭建 Java 开发环境。
    872 0
    |
    7月前
    |
    安全 JavaScript Java
    java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
    本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
    629 0
    |
    7月前
    |
    安全 Java 测试技术
    Java 大学期末实操项目在线图书管理系统开发实例及关键技术解析实操项目
    本项目基于Spring Boot 3.0与Java 17,实现在线图书管理系统,涵盖CRUD操作、RESTful API、安全认证及单元测试,助力学生掌握现代Java开发核心技能。
    415 1
    |
    7月前
    |
    Java 关系型数据库 MySQL
    Java项目实战(图书管理系统)
    本项目为简易图书管理系统,实现图书增删改查、用户借阅归还及基础用户管理功能。采用Java语言,结合MySQL数据库与MVC架构,涵盖JDBC、Servlet、JSP等技术,适合初学者学习Java Web开发流程与项目结构设计。
    374 2
    |
    7月前
    |
    Java 应用服务中间件 Docker
    java-web部署模式概述
    本文总结了现代 Web 开发中 Spring Boot HTTP 接口服务的常见部署模式,包括 Servlet 与 Reactive 模型、内置与外置容器、物理机 / 容器 / 云环境部署及单体与微服务架构,帮助开发者根据实际场景选择合适的方案。
    318 25