Java课程设计:Servlet+JSP+MySql 实现的图书管理系统(内附源码)
源码分享在文末!
文章目录
- 一、项目技术
- 二、开发环境和工具
- 三、项目成品演示
- 四、项目讲解
- 五、源码展示
- 六、源码获取
一、项目技术
- 基于B/S结构
- 前端: HTML+CSS+JS +JQuery
- 后端: Servlet+JSP+MySql
二、开发环境和工具
- 操作系统: win8/win10
- JDK: 8.0
- 开发工具: Intellij IDEA2020.1 旗舰版
- 服务器: Tomcat8.0
- 数据库工具:mysql5.5 +Navicat Premium 12
三、项目成品演示
四、项目讲解
技术介绍
- 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;}@Overridepublic 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();@Overrideprotected 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*/@Overrideprotected 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.获取删除书籍idlong 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.遍历FileItemBook 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.pngfileName = 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.将对象保存到requestreq.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.请求转发到jspreq.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.遍历FileItemBook 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.pngfileName = 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来寻找对应的typeType 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层负责业务的事情*/
六、源码获取
因为页面与源码太多了,所以页面与源码只展示了一部分,完整源码已经打包了,点击下面蓝色链接获取!
点我获取源码