图书模块

分析

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

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

设计实体


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第二篇【图书模块、前台页面】的更多相关文章

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

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

  2. ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第二篇:第一个页面

    摘要      本文首先一步一步完成Demo的第一个页面——首页.然后根据实现过程,说明一下其中用到的与ASP.NET MVC相关的概念与原理. 让第一个页面跑起来      现在,我们来实现公告系统 ...

  3. [ABP教程]第二章 图书列表页面

    Web应用程序开发教程 - 第二章: 图书列表页面 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开 ...

  4. 解剖SQLSERVER 第二篇 对数据页面头进行逆向(译)

    解剖SQLSERVER 第二篇  对数据页面头进行逆向(译) http://improve.dk/reverse-engineering-sql-server-page-headers/ 在开发Orc ...

  5. 使用wepy开发微信小程序商城第二篇:路由配置和页面结构

    使用wepy开发微信小程序商城 第二篇:路由配置和页面结构 前言: 最近公司在做一个微信小程序的项目,用的是类似于vue的wepy框架.我也借此机会学习和实践一下. 小程序官方文档:https://d ...

  6. 【MM系列】SAP MM模块-组织结构第二篇

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-组织结构第二篇   ...

  7. “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构、登录窗口、以及主界面)

    “MVC+Nhibernate+Jquery-EasyUI”信息发布系统 第二篇(数据库结构.登录窗口.以及主界面) 一.在上一篇文章中,主要说的就是把主框架搭建起来,并且Nhibernate能达到增 ...

  8. IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm(转载)

    IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm 自从本系列发布之后,收到了很多的朋友的回复!非常感谢,同时很多朋友问到了一些问题,有些问 ...

  9. PHP 性能分析第二篇: Xhgui In-Depth

    [前言]这是国外知名博主 Davey Shafik 撰写的 PHP 应用性能分析系列的第二篇,第一篇介绍 Xhprof/Xhgui,第三篇则关注于性能调优实践. 在第一篇中,我们初步介绍了 xhpro ...

随机推荐

  1. 获取windows所有用户名

    #include <LM.h> #pragma comment(lib, "netapi32.lib") // See more: http://msdn.micros ...

  2. Win10个性化设置

    Win10个性化设置.. ---------------------- Capture001-我的桌面 ---------------------- Win10设置任务栏的颜色 ----------- ...

  3. WeQuant交易策略—MACD

    MACD(指数平滑异同平均线)策略简介MACD指标应该是大家最常见的技术指标,在很多股票.比特币的软件中都是默认显示的.MACD是从双指数移动平均线发展而来的.意义和双移动平均线基本相同,即由快.慢均 ...

  4. Javaweb分页功能简单实现

    效果如下图 数据库中的数据                                                                页面效果 首先,创建一个通用类Page,代码及 ...

  5. java 基础三

    1 运算符 1.1  比较运算符 比较运算符的结果都是boolean类型,也即是要么是true,要么是false. 比较运算符"=="不能写成"=". > ...

  6. 关于i++和++i

    初学Java,经常看到i++和++i的一些问题,在此整理一下. 首先看下面一个小程序: public class atest{ public static void main(String args[ ...

  7. QQ无法通过ISA2006&TMG2010代理收发图片问题解决

    近期公司有业务需求通过TMG访问QQ,但配置多次均无法通过QQ收发图片,文字输入正常. 目前已解决,供参考: 这个问题是SSL端口默认使用了443,但QQ的离线文件不使用这个端口.所以ISA会把QQ的 ...

  8. Tomcat迁移到WebsphereURL获取中文参数乱码问题

    URL携带中文参数时,tomcat通常用两种方法可以解决中文乱码问题: String param = new String(request.getParameter("param " ...

  9. JVM(一) OpenJDK1.8源码在Ubuntu16.04下的编译

    笔者最近在学习周志明老师编写的<深入理解Java虚拟机>一书,书中第一章的实战部分就是"自己编译JDK",不过书中提到的是OpenJDK 7的编译.由于现在Java开发 ...

  10. jumpserver-0.3.2 堡垒机环境搭建(图文详解)

    下载安装包:https://github.com/jumpserver/jumpserver.git 解压 三.执行快速安装脚本 cd /opt/jumpserver/install pip inst ...