源码分享在文末!
文章目录
前言
学习完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(业务去实现)
*/publicclassBookimplementsSerializable{privatelong id;//外键号privatelong typeId;privateString name;privatedouble price;privateString desc;privateString pic;privateString publish;privateString author;privatelong stock;privateString address;//外键对应的实体对象privateType type;publicTypegetType(){return type;}publicvoidsetType(Type type){this.type = type;}publiclonggetId(){return id;}publicvoidsetId(long id){this.id = id;}publiclonggetTypeId(){return typeId;}publicvoidsetTypeId(long typeId){this.typeId = typeId;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicStringgetDesc(){return desc;}publicvoidsetDesc(String desc){this.desc = desc;}publicStringgetPic(){return pic;}publicvoidsetPic(String pic){this.pic = pic;}publicStringgetPublish(){return publish;}publicvoidsetPublish(String publish){this.publish = publish;}publicStringgetAuthor(){return author;}publicvoidsetAuthor(String author){this.author = author;}publiclonggetStock(){return stock;}publicvoidsetStock(long stock){this.stock = stock;}publicStringgetAddress(){return address;}publicvoidsetAddress(String address){this.address = address;}@OverridepublicStringtoString(){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")publicclassBookServletextendsHttpServlet{BookBiz bookBiz =newBookBiz();@OverrideprotectedvoiddoGet(HttpServletRequest req,HttpServletResponse resp)throwsServletException,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
*/@OverrideprotectedvoiddoPost(HttpServletRequest req,HttpServletResponse resp)throwsServletException,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
*/privatevoidmodify(HttpServletRequest req,HttpServletResponse resp,PrintWriter out)throwsException{//1.创建磁盘工厂-临时存储文件磁盘-DiskFileItemFactory factory =newDiskFileItemFactory();//1.1设置大小
factory.setSizeThreshold(1024*9);//1.2临时仓库File file =newFile("c:\\temp");if(!file.exists()){
file.mkdir();//创建文件夹}
factory.setRepository(file);//2.文件上传+表单数据ServletFileUpload fileUpload =newServletFileUpload(factory);//3.将请求解析为一个个FileItem(文件+表单元素)List<FileItem> fileItems = fileUpload.parseRequest(req);//4.遍历FileItemBook book =newBook();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(newFile(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
*/privatevoiddetails(HttpServletRequest req,HttpServletResponse resp,PrintWriter out)throwsServletException,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
*/privatevoidquery(HttpServletRequest req,HttpServletResponse resp)throwsServletException,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
*/privatevoidadd(HttpServletRequest req,HttpServletResponse resp,PrintWriter out)throwsException{//1.创建磁盘工厂-临时存储文件磁盘-DiskFileItemFactory factory =newDiskFileItemFactory();//1.1设置大小
factory.setSizeThreshold(1024*9);//1.2临时仓库File file =newFile("c:\\temp");if(!file.exists()){
file.mkdir();//创建文件夹}
factory.setRepository(file);//2.文件上传+表单数据ServletFileUpload fileUpload =newServletFileUpload(factory);//3.将请求解析为一个个FileItem(文件+表单元素)List<FileItem> fileItems = fileUpload.parseRequest(req);//4.遍历FileItemBook book =newBook();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(newFile(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层
publicclassBookBiz{//BookDao对象BookDao bookDao =newBookDao();/**
* 根据类型编号获得书籍
* @param typeId
* @return
*/publicList<Book>getBooksByTypeId(long typeId){try{return bookDao.getBooksByTypeId(typeId);}catch(SQLException throwables){
throwables.printStackTrace();returnnull;}}/**
* 根据书籍信息来添加书本
* @param typeId
* @param name
* @param price
* @param desc
* @param pic
* @param publish
* @param author
* @param stock
* @param address
* @return
*/publicintadd(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
*/publicintadd(Book book){returnadd(book.getTypeId(), book.getName(), book.getPrice(), book.getDesc(), book.getPic(), book.getPublish(), book.getAuthor(), book.getStock(), book.getAddress());}publicintmodify(Book book){returnmodify(book.getId(),book.getTypeId(), book.getName(), book.getPrice(), book.getDesc(), book.getPic(), book.getPublish(), book.getAuthor(), book.getStock(), book.getAddress());}publicintmodify(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;}publicintremove(long id)throwsException{//1.判断id是否存在外键,存在无法删除RecordDao recordDao =newRecordDao();//2.删除int count =0;try{List<Record> records = recordDao.getRecordByBookId(id);if(records.size()>0){thrownewException("删除的书籍有子信息,删除失败");}
count = bookDao.remove(id);}catch(SQLException throwables){
throwables.printStackTrace();}return count;}/**
* 12:03
* @param pageIndex
* @param pageSize
* @return
*/publicList<Book>getByPage(int pageIndex,int pageSize){TypeDao typeDao =newTypeDao();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;}publicBookgetByName(String bookName){Book book =null;try{
book = bookDao.getByName(bookName);}catch(SQLException throwables){
throwables.printStackTrace();}return book;}publicBookgetById(long id){Book book =null;TypeDao typeDao =newTypeDao();try{
book = bookDao.getById(id);longTypeId= book.getTypeId();Type type = typeDao.getById(TypeId);
book.setType(type);}catch(SQLException throwables){
throwables.printStackTrace();}return book;}/**
* 由行数算页数
* @return
*/publicintgetPageCount(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层
publicclassBookDao{QueryRunner runner =newQueryRunner();/**
* 根据类型查询对应的书籍信息
*
* @param typeId
* @return
* @throws SQLException
*/publicList<Book>getBooksByTypeId(long typeId)throwsSQLException{Connection conn =DBHelper.getConnection();String sql ="select * from book where typeId = ?";List<Book> books = runner.query(conn, sql,newBeanListHandler<Book>(Book.class), typeId);DBHelper.close(conn);return books;}/**
* 添加
*
* @return
*/publicintadd(long typeId,String name,Double price,String desc,String pic,String publish,String author,long stock,String address)throwsSQLException{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;}publicintmodify(long id,long typeId,String name,Double price,String desc,String pic,String publish,String author,long stock,String address)throwsSQLException{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;}publicintremove(long id)throwsSQLException{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
*/publicList<Book>getByPage(int pageIndex,int pageSize)throwsSQLException{Connection conn =DBHelper.getConnection();String sql ="select * from book limit ?,?";int offset =(pageIndex -1)* pageSize;List<Book> books= runner.query(conn, sql,newBeanListHandler<Book>(Book.class), offset, pageSize);DBHelper.close(conn);return books;}publicBookgetById(long id)throwsSQLException{Connection conn =DBHelper.getConnection();String sql ="select * from book where id = ?";Book book = runner.query(conn, sql,newBeanHandler<Book>(Book.class), id);DBHelper.close(conn);return book;}/**
* 根据书籍名字查Book对象
* @param bookName
* @return
* @throws SQLException
*/publicBookgetByName(String bookName)throwsSQLException{Connection conn =DBHelper.getConnection();String sql ="select * from book where name = ?";Book book = runner.query(conn, sql,newBeanHandler<Book>(Book.class), bookName);DBHelper.close(conn);return book;}/**
* 获取书籍数量
* @return
* @throws SQLException
*/publicintgetCount()throwsSQLException{Connection conn =DBHelper.getConnection();String sql ="select count(id) from book";Object data = runner.query(conn, sql,newScalarHandler<>());int count =(int)(long)data;return count;}/**
* 修改书籍数量
* @param id
* @param amount 大于0,加一本---小于0,减一本
* @return
* @throws SQLException
*/publicintmodify(long id,int amount)throwsSQLException{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;}publicstaticvoidmain(String[] args){try{Book book =newBookDao().getById(2);System.out.println(book);}catch(SQLException throwables){
throwables.printStackTrace();}}}/**
* dao层只负责与数据库相关的基本工作
* biz层负责业务的事情
*/
总结
由于源码太多了,无法全部发出来,我已经把它上传了大家可以下载用来学习。
下载地址:图书管理系统
或者大家也可以关注下列公众号回复“图书管理系统”即可获得。
大家对源码有什么疑问也可以私聊我,我帮你解决!
版权归原作者 _ 大聪明 所有, 如有侵权,请联系我们删除。