源码分享在文末!
前言
学习完Javaweb的知识后做了个项目练练手,我选择了经典而且比较简单的图书管理系统。
最近有时间,整理了一下,分享给大家,希望能够帮到你!
一、项目技术
- 基于B/S结构
- 前端: HTML+CSS+JS +JQuery
- 后端: Servlet+JSP+MySql
二、开发环境和工具
- 操作系统: win8/win10
- JDK: 8.0
- 开发工具: Intellij IDEA2020.1 旗舰版
- 服务器: Tomcat8.0
- 数据库工具:mysql5.5 +Navicat Premium 12
开发工具我也为大家打包好了,关注文末的公众号,回复“Java全家桶”即可获得
三、项目成品演示
四、项目讲解
技术介绍
-
JSP:
JavaServer Pages
是由Sun Microsystems
公司倡导、许多公司参与一起建立的一种动态网页技术标准。 -
Apache:
Apache
是世界使用排名第一的Web服务器软件。 -
Ajax:
Asynchronous Javascript And XML
(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。 - C3P0:数据库连接池
-
OSI:
Open System Interconnect
开放系统互连参考模型。 -
MVC:
Model View Controller
,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码。 -
DBUtils:
Commons DbUtils
是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
工作原理:
浏览器和服务器通过http协议来建立连接的。浏览器经过http的请求协议将用户想要的信息传到web服务器。
然后,web服务器会干一件事,判断页面
是静态还是动态。
如果是静态
,web服务器就直接将用户想要的信息通过响应封装好了之后再返回给浏览器;
如果是动态
,web服务器会将接收到的内容传递给web容器,web容器再将内容传给Servlet,(那么web容器是怎么将内容传给servlet的呢?分析:web容器在将信息传递给servlet的时候必须到web.xml的配置文件中去找到Servlet的url-pattern路径),在找到servlet后,web容器再启动一个servlet线程,然后再返回给web容器,web容器在将信息封装好传给web服务器,web服务器再将得到的信息解析后,通过响应封装好了,在传递到浏览器。
如下图所示
数据库表及其关系
项目结构展示
- 后端
- 前端
五、源码展示
书籍实体类
/**
* 书的实体类:注意外键
* 1.DBUtil无法生成表以外的数据
* 2.外键的实体对象没有数据,需要后期手动添加biz(业务去实现)
*/
public class Book implements Serializable {
private long id;
//外键号
private long typeId;
private String name;
private double price;
private String desc;
private String pic;
private String publish;
private String author;
private long stock;
private String address;
//外键对应的实体对象
private Type type;
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getTypeId() {
return typeId;
}
public void setTypeId(long typeId) {
this.typeId = typeId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public String getPublish() {
return publish;
}
public void setPublish(String publish) {
this.publish = publish;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public long getStock() {
return stock;
}
public void setStock(long stock) {
this.stock = stock;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", typeId=" + typeId +
", name='" + name + '\'' +
", price=" + price +
", desc='" + desc + '\'' +
", pic='" + pic + '\'' +
", publish='" + publish + '\'' +
", author='" + author + '\'' +
", stock=" + stock +
", address='" + address + '\'' +
", type=" + type +
'}';
}
}
书籍的Servlet层
@WebServlet("/book.let")
public class BookServlet extends HttpServlet {
BookBiz bookBiz = new BookBiz();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
/**
* /book.let?type=add 添加图片
* /book.let?type=modifypre&id=xx 修改前准备
* /book.let?type=modify 修改
* /book.let?type=remove&id=xx 删除
* /book.let?type=query&pageIndex=1 分页查询-请求转发
* /book.let?type=details&id=xx 展示书籍详细信息
* /book.let?type=doajax&name=xx 根据图书名对应的图书信息
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//验证用户是否登录
HttpSession session = req.getSession();
if(session.getAttribute("user") == null) {
out.println("<script>alert('请登录');parent.window.location.href = 'login.html';</script>");
return;
}
String type = req.getParameter("type");
switch (type) {
case "add":
try {
add(req, resp, out);
} catch (Exception e) {
e.printStackTrace();
resp.sendError(500, e.getMessage());
}
break;
case "modifypre":
///book.let?type=modifypre&id=xx 修改前准备
long bookId = Long.parseLong(req.getParameter("id"));
Book book = bookBiz.getById(bookId);
req.setAttribute("book", book);
req.getRequestDispatcher("book_modify.jsp").forward(req,resp);
break;
case "modify":
try {
modify(req, resp,out);
} catch (Exception e) {
e.printStackTrace();
}
break;
case "remove":
//1.获取删除书籍id
long id = Long.parseLong(req.getParameter("id"));
//2.调用biz层删除
try {
int count = bookBiz.remove(id);
//3.提示+跳转到查询的servlet -out对象
if(count > 0) {
out.println("<script>alert('删除成功');location.href='book.let?type=query&pageIndex=1'</script>");
}else{
out.println("<script>alert('删除失败');location.href='book.let?type=query&pageIndex=1'</script>");
}
} catch (Exception e) {
//e.printStackTrace();
out.println("<script>alert('"+e.getMessage()+"');location.href='book.let?type=query&pageIndex=1'</script>");
}
case "query":
query(req, resp);
break;
case "details":
details(req, resp,out);
break;
case "doajax":
String name = req.getParameter("name");
Book book1 = bookBiz.getByName(name);
if(book1 == null) {
out.print("{}");//null的json对象
}else{
out.print(JSON.toJSONString(book1));
}
break;
default:
out.println("404");
}
}
/**
* 修改图书信息
* @param req
* @param resp
* @param out
*/
private void modify(HttpServletRequest req, HttpServletResponse resp, PrintWriter out) throws Exception {
//1.创建磁盘工厂-临时存储文件磁盘-
DiskFileItemFactory factory = new DiskFileItemFactory();
//1.1设置大小
factory.setSizeThreshold(1024*9);
//1.2临时仓库
File file = new File("c:\\temp");
if(!file.exists()) {
file.mkdir();//创建文件夹
}
factory.setRepository(file);
//2.文件上传+表单数据
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//3.将请求解析为一个个FileItem(文件+表单元素)
List<FileItem> fileItems = fileUpload.parseRequest(req);
//4.遍历FileItem
Book book = new Book();
for(FileItem item : fileItems) {
if(item.isFormField()) {
//4.1表单:获取表单元素(元素名称与用户填写对应值)
String name = item.getFieldName();
String value = item.getString("utf-8");//防止乱码
switch(name) {
case "id":
book.setId(Long.parseLong(value));
break;
case "pic":
book.setPic(value);
break;
case "typeId":
book.setTypeId(Long.parseLong(value));
break;
case "name":
book.setName(value);
break;
case "price":
book.setPrice(Double.parseDouble(value));
break;
case "desc":
book.setDesc(value);
break;
case "publish":
book.setPublish(value);
break;
case "author":
book.setAuthor(value);
break;
case "stock":
book.setStock(Long.parseLong(value));
break;
case "address":
book.setAddress(value);
break;
}
}else{
//4.2文件:图片的文件名,用户不选择图片时,fileName的数据为""
String fileName = item.getName();
if(fileName.trim().length() > 0) {
//避免文件替换(名称重复)来使用:当前系统时间.png
//4.2.1获取文件后缀名(文件类型)
String filterName = fileName.substring(fileName.lastIndexOf("."));
//4.2.1修改文件名 20220312545412245.png
fileName = DateHelper.getImageName() + filterName;
//文件上传之后保存到哪里
// 文件读写需要实际路径:虚拟路径对应的实际路径
String path = req.getServletContext().getRealPath("/Images/cover");
String filePath = path + "/" + fileName;
String dbPath = "Images/cover/" + fileName;
book.setPic(dbPath);
//4.3保存文件
item.write(new File(filePath));
}
}
}
//5.将信息保存到数据库
int count = bookBiz.modify(book);
if(count > 0) {
out.println("<script>alert('修改书籍成功');location.href='book.let?type=query&pageIndex=1';</script>");
}else {
out.println("<script>alert('修改书籍失败');location.href='book.let?type=query&pageIndex=1';</script>");
}
}
/**
* 查看图书详情
* /book.let?type=details&id=xx 展示书籍详细信息
* @param req
* @param resp
*/
private void details(HttpServletRequest req, HttpServletResponse resp, PrintWriter out) throws ServletException, IOException {
//1.获取图书编号
long id = Long.parseLong(req.getParameter("id"));
//2.根据编号获取图书对象
Book book = bookBiz.getById(id);
//3.将对象保存到request
req.setAttribute("book", book);
//4.请求转发到jsp页面
req.getRequestDispatcher("book_details.jsp").forward(req, resp);
}
/**
* 查询
* /book.let?type=query&pageIndex=1 分页查询-请求转发
* 页数:
* 当前页码:pageIndex=1
* 信息存储:request 使用请求转发从servlet-->jsp
* @param req
* @param resp
*/
private void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取信息:页数,页码,信息
int pageSize = 3;
int pageCount = bookBiz.getPageCount(pageSize);
int pageIndex = Integer.parseInt(req.getParameter("pageIndex"));
if(pageIndex < 1) {
pageIndex = 1;
}
if(pageIndex > pageCount) {
pageIndex = pageCount;
}
List<Book> books = bookBiz.getByPage(pageIndex, pageSize);
//2.存
req.setAttribute("pageCount",pageCount);
req.setAttribute("books", books);
//3.请求转发到jsp
req.getRequestDispatcher("book_list.jsp?pageIndex="+pageIndex).forward(req,resp);
}
/**
* 添加书籍
* 1.multipart/form-data:与之前不同:
* 之前:获取表单元素 req.getParameter()
* 2.文件上传:图片文件从浏览器端保存到服务器端(第三方FileUpload+io)
* 3.路径问题:
* 3.1图片本地路径:实际路径
* 3.2项目发布之后图片路径url:虚拟路径(存在服务器中)
* @param req
* @param resp
* @param out
*/
private void add(HttpServletRequest req, HttpServletResponse resp, PrintWriter out) throws Exception {
//1.创建磁盘工厂-临时存储文件磁盘-
DiskFileItemFactory factory = new DiskFileItemFactory();
//1.1设置大小
factory.setSizeThreshold(1024*9);
//1.2临时仓库
File file = new File("c:\\temp");
if(!file.exists()) {
file.mkdir();//创建文件夹
}
factory.setRepository(file);
//2.文件上传+表单数据
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//3.将请求解析为一个个FileItem(文件+表单元素)
List<FileItem> fileItems = fileUpload.parseRequest(req);
//4.遍历FileItem
Book book = new Book();
for(FileItem item : fileItems) {
if(item.isFormField()) {
//4.1表单:获取表单元素(元素名称与用户填写对应值)
String name = item.getFieldName();
String value = item.getString("utf-8");//防止乱码
switch(name) {
case "typeId":
book.setTypeId(Long.parseLong(value));
break;
case "name":
book.setName(value);
break;
case "price":
book.setPrice(Double.parseDouble(value));
break;
case "desc":
book.setDesc(value);
break;
case "publish":
book.setPublish(value);
break;
case "author":
book.setAuthor(value);
break;
case "stock":
book.setStock(Long.parseLong(value));
break;
case "address":
book.setAddress(value);
break;
}
}else{
//4.2文件:图片的文件名
String fileName = item.getName();
//避免文件替换(名称重复)来使用:当前系统时间.png
//4.2.1获取文件后缀名(文件类型)
String filterName = fileName.substring(fileName.lastIndexOf("."));
//4.2.1修改文件名 20220312545412245.png
fileName = DateHelper.getImageName() + filterName;
//文件上传之后保存到哪里
// 文件读写需要实际路径:虚拟路径对应的实际路径
String path = req.getServletContext().getRealPath("/Images/cover");
String filePath = path + "/" + fileName;
String dbPath = "Images/cover/" + fileName;
book.setPic(dbPath);
//4.3保存文件
item.write(new File(filePath));
}
}
//5.将信息保存到数据库
int count = bookBiz.add(book);
if(count > 0) {
out.println("<script>alert('添加书籍成功');location.href='book.let?type=query&pageIndex=1';</script>");
}else {
out.println("<script>alert('添加书籍失败');location.href='book_add.jsp';</script>");
}
}
}
书籍的biz层
public class BookBiz {
//BookDao对象
BookDao bookDao = new BookDao();
/**
* 根据类型编号获得书籍
* @param typeId
* @return
*/
public List<Book> getBooksByTypeId(long typeId) {
try {
return bookDao.getBooksByTypeId(typeId);
} catch (SQLException throwables) {
throwables.printStackTrace();
return null;
}
}
/**
* 根据书籍信息来添加书本
* @param typeId
* @param name
* @param price
* @param desc
* @param pic
* @param publish
* @param author
* @param stock
* @param address
* @return
*/
public int add(long typeId, String name, Double price, String desc, String pic, String publish, String author, long stock, String address) {
int count = 0;
try {
count = bookDao.add(typeId, name, price, desc, pic, publish, author, stock, address);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return count;
}
/**
* 如果用户使用对象的方式来添加书籍
* @param book
* @return
*/
public int add(Book book) {
return add(book.getTypeId(), book.getName(), book.getPrice(), book.getDesc(), book.getPic(), book.getPublish(), book.getAuthor(), book.getStock(), book.getAddress());
}
public int modify(Book book) {
return modify(book.getId(),book.getTypeId(), book.getName(), book.getPrice(), book.getDesc(), book.getPic(), book.getPublish(), book.getAuthor(), book.getStock(), book.getAddress());
}
public int modify(long id, long typeId, String name, Double price, String desc, String pic, String publish, String author, long stock, String address) {
int count = 0;
try {
count = bookDao.modify(id, typeId, name, price, desc, pic, publish, author, stock, address);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return count;
}
public int remove(long id) throws Exception {
//1.判断id是否存在外键,存在无法删除
RecordDao recordDao = new RecordDao();
//2.删除
int count = 0;
try {
List<Record> records = recordDao.getRecordByBookId(id);
if(records.size() > 0) {
throw new Exception("删除的书籍有子信息,删除失败");
}
count = bookDao.remove(id);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return count;
}
/**
* 12:03
* @param pageIndex
* @param pageSize
* @return
*/
public List<Book> getByPage(int pageIndex, int pageSize) {
TypeDao typeDao = new TypeDao();
List<Book> books = null;
try {
books = bookDao.getByPage(pageIndex, pageSize);
//处理type对象的数据问题
for(Book book : books) {
long typeId = book.getTypeId();
//根据typeId来寻找对应的type
Type type = typeDao.getById(typeId);
//设置type属性
book.setType(type);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return books;
}
public Book getByName(String bookName) {
Book book = null;
try {
book = bookDao.getByName(bookName);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return book;
}
public Book getById(long id) {
Book book = null;
TypeDao typeDao = new TypeDao();
try {
book = bookDao.getById(id);
long TypeId = book.getTypeId();
Type type = typeDao.getById(TypeId);
book.setType(type);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return book;
}
/**
* 由行数算页数
* @return
*/
public int getPageCount(int pageSize) {
int pagecount = 0;
try {
//1.获取行数
int rowcount = bookDao.getCount();
//2.根据行数得到页数-,每页多少条
pagecount = (rowcount - 1) / pageSize + 1;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return pagecount;
}
}
书籍的dao层
public class BookDao {
QueryRunner runner = new QueryRunner();
/**
* 根据类型查询对应的书籍信息
*
* @param typeId
* @return
* @throws SQLException
*/
public List<Book> getBooksByTypeId(long typeId) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "select * from book where typeId = ?";
List<Book> books = runner.query(conn, sql, new BeanListHandler<Book>(Book.class), typeId);
DBHelper.close(conn);
return books;
}
/**
* 添加
*
* @return
*/
public int add(long typeId, String name, Double price, String desc, String pic, String publish, String author, long stock, String address) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "insert into book(typeId,`name`,price,`desc`,pic,publish,author,stock,address) values(?,?,?,?,?,?,?,?,?)";
int count = runner.update(conn, sql, typeId, name, price, desc, pic, publish, author, stock, address);
DBHelper.close(conn);
return count;
}
public int modify(long id, long typeId, String name, Double price, String desc, String pic, String publish, String author, long stock, String address) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "update book set typeId=?,`name`=?,price=?,`desc`=?,pic=?,publish=?,author=?,stock=?,address=? where id=?";
int count = runner.update(conn, sql, typeId, name, price, desc, pic, publish, author, stock, address, id);
DBHelper.close(conn);
return count;
}
public int remove(long id) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "delete from book where id = ?";
int count = runner.update(conn, sql, id);
DBHelper.close(conn);
return count;
}
/**
* 分页查询
* @param pageIndex 第几页开始
* @param pageSize 每一页有多少行
* @return 当前页信息
* @throws SQLException
*/
public List<Book> getByPage(int pageIndex, int pageSize) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "select * from book limit ?,?";
int offset = (pageIndex - 1) * pageSize;
List<Book> books= runner.query(conn, sql, new BeanListHandler<Book>(Book.class), offset, pageSize);
DBHelper.close(conn);
return books;
}
public Book getById(long id) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "select * from book where id = ?";
Book book = runner.query(conn, sql, new BeanHandler<Book>(Book.class), id);
DBHelper.close(conn);
return book;
}
/**
* 根据书籍名字查Book对象
* @param bookName
* @return
* @throws SQLException
*/
public Book getByName(String bookName) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "select * from book where name = ?";
Book book = runner.query(conn, sql, new BeanHandler<Book>(Book.class), bookName);
DBHelper.close(conn);
return book;
}
/**
* 获取书籍数量
* @return
* @throws SQLException
*/
public int getCount() throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "select count(id) from book";
Object data = runner.query(conn, sql, new ScalarHandler<>());
int count = (int)(long)data;
return count;
}
/**
* 修改书籍数量
* @param id
* @param amount 大于0,加一本---小于0,减一本
* @return
* @throws SQLException
*/
public int modify(long id, int amount) throws SQLException {
Connection conn = DBHelper.getConnection();
String sql = "update book set stock=stock + ? where id=?";
int count = runner.update(conn, sql,amount, id);
DBHelper.close(conn);
return count;
}
public static void main(String[] args) {
try {
Book book = new BookDao().getById(2);
System.out.println(book);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* dao层只负责与数据库相关的基本工作
* biz层负责业务的事情
*/
总结
由于源码太多了,无法全部发出来,我已经把它上传了大家可以下载用来学习。
下载地址:图书管理系统
之前少了数据库脚本,现在补出来。
链接:https://pan.baidu.com/s/1Q93tvUUAu9r46qeDKKvIjA?pwd=ckgx
提取码:ckgx文章来源:https://www.toymoban.com/news/detail-459709.html
远程帮你部署运行是有偿的,人太多了我不可能帮你一个一个来运行!
文章来源地址https://www.toymoban.com/news/detail-459709.html
到了这里,关于【图书管理系统】Servlet+JSP+MySql 实现的一个前后端 javaweb项目(内附源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!