bookStore第二篇【图书模块、前台页面】
图书模块
分析
在设计图书管理的时候,我们应该想到:图书和分类是有关系的。一个分类可以对应多本图书。
为什么要这样设计?这样更加人性化,用户在购买书籍的时候,用户能够查看相关分类后的图书,而不是全部图书都显示给用户,让用户一个一个去找。
设计实体
    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<Book> getPageData(int start, int end) {
        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
        String sql = "SELECT * FROM book limit ?,?";
        try {
            return (List<Book>) queryRunner.query(sql, new BeanListHandler(Book.class), new Object[]{start, end});
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**得到按照分类图书的分页数据*/
    public List<Book> 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<Book>) 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<Book> bookList = bookDao.getPageData(3, 3);
        for (Book book : bookList) {
            System.out.println(book.getName());
        }
        List<Book> 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<Book> getPageData(int start, int end);
    List<Book> 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<Book> 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<Book> books = bookDao.getPageData(page.getStartIndex(), page.getLinesize(), category_id);
        page.setList(books);
        return page;
    }
后台添加图书
后台要添加图书的时候,应该说明图书的类型是什么。
要想在显示添加图书的页面上知道全部类型的id,就要经过Servlet把类型的集合传送过去
绑定链接
<a href="${pageContext.request.contextPath}/BookServlet?method=addUI" target="body">添加图书</a><br>传送类型集合的Servlet
        String method = request.getParameter("method");
        BussinessServiceImpl service = new BussinessServiceImpl();
        if (method.equals("addUI")) {
            List<Category> list = service.getAllCategory();
            request.setAttribute("list", list);
            request.getRequestDispatcher("/background/addBook.jsp").forward(request, response);
        } 显示JSP页面
<form action="${pageContext.request.contextPath}/BookServlet?method=add" method="post" enctype="multipart/form-data">
    <table border="1px" width="30%">
        <tr>
            <td> 图书名称:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td> 作者:</td>
            <td><input type="text" name="author"></td>
        </tr>
        <tr>
            <td> 图书价钱:</td>
            <td><input type="text" name="price"></td>
        </tr>
        <tr>
            <td>类型:</td>
            <td>
                <select name="category_id">
                    <c:forEach items="${list}" var="category">
                        <option value="${category.id}">${category.name}</option>
                    </c:forEach>
                </select>
            </td>
        </tr>
        <tr>
            <td> 上传图片</td>
            <td><input type="file" name="image"></td>
        </tr>
        <tr>
            <td>详细描述</td>
            <td><textarea name="description"></textarea></td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="提交">
                <input type="reset" value="重置">
            </td>
        </tr>
    </table>
</form>
处理表单数据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<FileItem> 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吧…..这些代码可以在我复用代码博文中找到
绑定超链接
<a href="${pageContext.request.contextPath}/BookServlet?method=look" target="body">查看图书</a>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对象的图片名称,弄一个超链接,超链接指向服务端的图片,这样就可以查看图片了!
<c:if test="${empty(page.list)}">
    暂时还没有任何图书哦
</c:if>
<c:if test="${!empty(page.list)}">
   <table border="1px">
       <tr>
           <td>书名</td>
           <td>作者</td>
           <td>价钱</td>
           <td>描述</td>
           <td>图片</td>
           <td>操作</td>
       </tr>
       <c:forEach var="book" items="${page.list}" >
           <tr>
               <td>${book.name}</td>
               <td>${book.author}</td>
               <td>${book.price}</td>
               <td>${book.description}</td>
               <td><a href="${pageContext.request.contextPath}/image/${book.image}">查看图片</a></td>
               <td>
                   <a href="#">删除</a>
                   <a href="#">修改</a>
               </td>
           </tr>
       </c:forEach>
   </table>
    <br>
    <jsp:include page="page.jsp"/>
</c:if>
效果:
前台页面
看回我们前台页面的成果图,我们可以把整个body页面看成是三个div
- body占整个div
- 导航条是一个div
- 显示图书的地方是一个div
设计好大概的布局
- html代码引入css
    <link rel="stylesheet" href="body.css" type="text/css">- HTML三个div
<div id="body">
    <div id="category">
        <c:forEach items="${categorys}" var="category">
        </c:forEach>
        这是导航条
    </div>
    <div id="bookandpages">
        <div id="books">
            这是书籍的地方
        </div>
        <div id="page">
            这是页码
        </div>
    </div>
</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页面,是没有后台的数据的!
    <frame src="${pageContext.request.contextPath}/IndexServlet"/>- Servlet代码:
        //得到所有的分类数据,给body页面
        BussinessServiceImpl service = new BussinessServiceImpl();
        List<Category> 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显示数据
<div id="body">
    <div id="category">
        书籍分类 :
        <br>
        <c:forEach items="${categories}" var="categories">
            <li>
                <a href="${pageContext.request.contextPath}/ListBookServlet?category_id=${categories.id}">${categories.name}</a>
            </li>
        </c:forEach>
    </div>
    <div id="bookandpages">
        <c:forEach items="${page.list}" var="book">
        <div id="books">
                <div id="image">
                    <img src="${pageContext.request.contextPath}/image/${book.image}" width="83px" height="118px">
                </div>
                <div id="bookinfo">
                    <li>
                        书名:${book.name}
                    </li>
                    <li>价格:${book.price}</li>
                    <li>作者:${book.author}</li>
                </div>
        </div>
            <%--这里要清除浮动,十分重要!--%>
            <div style="clear: both"></div>
        </c:forEach>
    </div>
    <div id="page">
        <jsp:include page="/client/page.jsp"/>
    </div>
</div>
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<Category>  categories = service.getAllCategory();
        request.setAttribute("page", page);
        request.setAttribute("categories", categories);
        request.getRequestDispatcher("/client/body.jsp").forward(request,response);效果:
bookStore第二篇【图书模块、前台页面】的更多相关文章
- 图书管理系统【JavaWeb:部署开发环境、解决分类、图书、前台页面模块】
		前言 巩固Servlet+JSP开发模式,做一个比较完整的小项目. 成果图 该项目包含了两个部分,前台和后台. 前台用于显示 后台用于管理 该项目可分为5个模块来组成:分类模块,用户模块,图书模块,购 ... 
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第二篇:第一个页面
		摘要 本文首先一步一步完成Demo的第一个页面——首页.然后根据实现过程,说明一下其中用到的与ASP.NET MVC相关的概念与原理. 让第一个页面跑起来 现在,我们来实现公告系统 ... 
- [ABP教程]第二章 图书列表页面
		Web应用程序开发教程 - 第二章: 图书列表页面 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开 ... 
- 解剖SQLSERVER 第二篇  对数据页面头进行逆向(译)
		解剖SQLSERVER 第二篇 对数据页面头进行逆向(译) http://improve.dk/reverse-engineering-sql-server-page-headers/ 在开发Orc ... 
- 使用wepy开发微信小程序商城第二篇:路由配置和页面结构
		使用wepy开发微信小程序商城 第二篇:路由配置和页面结构 前言: 最近公司在做一个微信小程序的项目,用的是类似于vue的wepy框架.我也借此机会学习和实践一下. 小程序官方文档:https://d ... 
- 【MM系列】SAP MM模块-组织结构第二篇
		公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-组织结构第二篇 ... 
- “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构、登录窗口、以及主界面)
		“MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构.登录窗口.以及主界面) 一.在上一篇文章中,主要说的就是把主框架搭建起来,并且Nhibernate能达到增 ... 
- IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm(转载)
		IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm 自从本系列发布之后,收到了很多的朋友的回复!非常感谢,同时很多朋友问到了一些问题,有些问 ... 
- PHP 性能分析第二篇: Xhgui In-Depth
		[前言]这是国外知名博主 Davey Shafik 撰写的 PHP 应用性能分析系列的第二篇,第一篇介绍 Xhprof/Xhgui,第三篇则关注于性能调优实践. 在第一篇中,我们初步介绍了 xhpro ... 
随机推荐
- django服务器正常打开,本地localhost能连上,其他计算机却连不上
			最近在学习Django,在搭建好django并且启动服务器后,遇到了麻烦. 问题现象: django服务器正常打开,本地localhost能连上,其他计算机却连不上 问题原因(可能存在原因): 这里的 ... 
- SLF4J源码解析-LoggerFactory(二)
			承接前文SLF4J源码解析-LoggerFactory(一),本文则主要针对获取ILoggerFactory对象作下简单的分析 LoggerFactory#getILoggerFactory() 源码 ... 
- JAVAWEB项目如何实现验证码 (转)
			JAVAWEB项目如何实现验证码 2012-12-21 21:19 56026人阅读 评论(36) 收藏 举报 .embody { padding: 10px 10px 10px; margin: 0 ... 
- spring boot 登录注册 demo (三) -- 前后端传递
			前端页面通过thymeleaf渲染 <dependency> <groupId>org.springframework.boot</groupId> <art ... 
- Java自定义注解及使用
			本文通过一个简单的例子展示注解的工作原理. 1.声明注解类型 @Target(value = ElementType.METHOD) //声明该注解的运行目标: 方法 @Retention(value ... 
- 【Linux】ssh免密登录
			一.ssh免密配置 ssh 无密码登录要使用公钥与私钥.linux下可以用用ssh-keygen生成公钥/私钥对,下面我以CentOS为例.有机器A(192.168.1.155),B(192.168. ... 
- python基础教程(七)
			本章介绍如何将语句组织成函数,这样,可以告诉计算机如何做事. 下面编写一小段代码计算婓波那契数列(前两个数的和是第三个数) fibs = [0,1] # 定义一个列表,初始内容是0,1 for i ... 
- pomelo 安装 windows 下
			最近一直在捣鼓这个东西,看着个的先记录下发帖时间, pomelo 现在最新版是2.0 的,和之前的版本的启动时有区别的(命令行)的,可以进pomelo官网去看下基本的信息, 在pomelo官方论坛上的 ... 
- oracle导库
			cmd窗口直接输入导库命令即可,不需要进入sqlplus C:\Documents and Settings\Administrator> imp username/pass@orcl file ... 
- Ext.grid.EditorGridPanel分页和查看全部
			在gridPanel添加查看全部数据按钮,必须使得每页显示的数量pageSize为总条数,那么总页数就只会有一页. 1.获取store数据的总条数 var totalCount = grid.getS ... 
