源碼分享在文末!
前言
學(xué)習(xí)完Javaweb的知識后做了個項目練練手,我選擇了經(jīng)典而且比較簡單的圖書管理系統(tǒng)。
最近有時間,整理了一下,分享給大家,希望能夠幫到你!
一、項目技術(shù)
- 基于B/S結(jié)構(gòu)
- 前端: HTML+CSS+JS +JQuery
- 后端: Servlet+JSP+MySql
二、開發(fā)環(huán)境和工具
- 操作系統(tǒng): win8/win10
- JDK: 8.0
- 開發(fā)工具: Intellij IDEA2020.1 旗艦版
- 服務(wù)器: Tomcat8.0
- 數(shù)據(jù)庫工具:mysql5.5 +Navicat Premium 12
開發(fā)工具我也為大家打包好了,關(guān)注文末的公眾號,回復(fù)“Java全家桶”即可獲得
三、項目成品演示
四、項目講解
技術(shù)介紹
-
JSP:
JavaServer Pages
是由Sun Microsystems
公司倡導(dǎo)、許多公司參與一起建立的一種動態(tài)網(wǎng)頁技術(shù)標(biāo)準(zhǔn)。 -
Apache:
Apache
是世界使用排名第一的Web服務(wù)器軟件。 -
Ajax:
Asynchronous Javascript And XML
(異步JavaScript和XML),是指一種創(chuàng)建交互式網(wǎng)頁應(yīng)用的網(wǎng)頁開發(fā)技術(shù)。通過在后臺與服務(wù)器進行少量數(shù)據(jù)交換,AJAX 可以使網(wǎng)頁實現(xiàn)異步更新。 - C3P0:數(shù)據(jù)庫連接池
-
OSI:
Open System Interconnect
開放系統(tǒng)互連參考模型。 -
MVC:
Model View Controller
,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼。 -
DBUtils:
Commons DbUtils
是Apache組織提供的一個對JDBC進行簡單封裝的開源工具類庫,使用它能夠簡化JDBC應(yīng)用程序的開發(fā),同時也不會影響程序的性能。
工作原理:
瀏覽器和服務(wù)器通過http協(xié)議來建立連接的。瀏覽器經(jīng)過http的請求協(xié)議將用戶想要的信息傳到web服務(wù)器。
然后,web服務(wù)器會干一件事,判斷頁面
是靜態(tài)還是動態(tài)。
如果是靜態(tài)
,web服務(wù)器就直接將用戶想要的信息通過響應(yīng)封裝好了之后再返回給瀏覽器;
如果是動態(tài)
,web服務(wù)器會將接收到的內(nèi)容傳遞給web容器,web容器再將內(nèi)容傳給Servlet,(那么web容器是怎么將內(nèi)容傳給servlet的呢?分析:web容器在將信息傳遞給servlet的時候必須到web.xml的配置文件中去找到Servlet的url-pattern路徑),在找到servlet后,web容器再啟動一個servlet線程,然后再返回給web容器,web容器在將信息封裝好傳給web服務(wù)器,web服務(wù)器再將得到的信息解析后,通過響應(yīng)封裝好了,在傳遞到瀏覽器。
如下圖所示
數(shù)據(jù)庫表及其關(guān)系
項目結(jié)構(gòu)展示
- 后端
- 前端
五、源碼展示
書籍實體類
/**
* 書的實體類:注意外鍵
* 1.DBUtil無法生成表以外的數(shù)據(jù)
* 2.外鍵的實體對象沒有數(shù)據(jù),需要后期手動添加biz(業(yè)務(wù)去實現(xiàn))
*/
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;
//外鍵對應(yīng)的實體對象
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 修改前準(zhǔn)備
* /book.let?type=modify 修改
* /book.let?type=remove&id=xx 刪除
* /book.let?type=query&pageIndex=1 分頁查詢-請求轉(zhuǎn)發(fā)
* /book.let?type=details&id=xx 展示書籍詳細(xì)信息
* /book.let?type=doajax&name=xx 根據(jù)圖書名對應(yīng)的圖書信息
* @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 修改前準(zhǔn)備
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.調(diào)用biz層刪除
try {
int count = bookBiz.remove(id);
//3.提示+跳轉(zhuǎn)到查詢的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.創(chuàng)建磁盤工廠-臨時存儲文件磁盤-
DiskFileItemFactory factory = new DiskFileItemFactory();
//1.1設(shè)置大小
factory.setSizeThreshold(1024*9);
//1.2臨時倉庫
File file = new File("c:\\temp");
if(!file.exists()) {
file.mkdir();//創(chuàng)建文件夾
}
factory.setRepository(file);
//2.文件上傳+表單數(shù)據(jù)
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表單:獲取表單元素(元素名稱與用戶填寫對應(yīng)值)
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的數(shù)據(jù)為""
String fileName = item.getName();
if(fileName.trim().length() > 0) {
//避免文件替換(名稱重復(fù))來使用:當(dāng)前系統(tǒng)時間.png
//4.2.1獲取文件后綴名(文件類型)
String filterName = fileName.substring(fileName.lastIndexOf("."));
//4.2.1修改文件名 20220312545412245.png
fileName = DateHelper.getImageName() + filterName;
//文件上傳之后保存到哪里
// 文件讀寫需要實際路徑:虛擬路徑對應(yīng)的實際路徑
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.將信息保存到數(shù)據(jù)庫
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 展示書籍詳細(xì)信息
* @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.根據(jù)編號獲取圖書對象
Book book = bookBiz.getById(id);
//3.將對象保存到request
req.setAttribute("book", book);
//4.請求轉(zhuǎn)發(fā)到j(luò)sp頁面
req.getRequestDispatcher("book_details.jsp").forward(req, resp);
}
/**
* 查詢
* /book.let?type=query&pageIndex=1 分頁查詢-請求轉(zhuǎn)發(fā)
* 頁數(shù):
* 當(dāng)前頁碼:pageIndex=1
* 信息存儲:request 使用請求轉(zhuǎn)發(fā)從servlet-->jsp
* @param req
* @param resp
*/
private void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.獲取信息:頁數(shù),頁碼,信息
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.請求轉(zhuǎn)發(fā)到j(luò)sp
req.getRequestDispatcher("book_list.jsp?pageIndex="+pageIndex).forward(req,resp);
}
/**
* 添加書籍
* 1.multipart/form-data:與之前不同:
* 之前:獲取表單元素 req.getParameter()
* 2.文件上傳:圖片文件從瀏覽器端保存到服務(wù)器端(第三方FileUpload+io)
* 3.路徑問題:
* 3.1圖片本地路徑:實際路徑
* 3.2項目發(fā)布之后圖片路徑url:虛擬路徑(存在服務(wù)器中)
* @param req
* @param resp
* @param out
*/
private void add(HttpServletRequest req, HttpServletResponse resp, PrintWriter out) throws Exception {
//1.創(chuàng)建磁盤工廠-臨時存儲文件磁盤-
DiskFileItemFactory factory = new DiskFileItemFactory();
//1.1設(shè)置大小
factory.setSizeThreshold(1024*9);
//1.2臨時倉庫
File file = new File("c:\\temp");
if(!file.exists()) {
file.mkdir();//創(chuàng)建文件夾
}
factory.setRepository(file);
//2.文件上傳+表單數(shù)據(jù)
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表單:獲取表單元素(元素名稱與用戶填寫對應(yīng)值)
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();
//避免文件替換(名稱重復(fù))來使用:當(dāng)前系統(tǒng)時間.png
//4.2.1獲取文件后綴名(文件類型)
String filterName = fileName.substring(fileName.lastIndexOf("."));
//4.2.1修改文件名 20220312545412245.png
fileName = DateHelper.getImageName() + filterName;
//文件上傳之后保存到哪里
// 文件讀寫需要實際路徑:虛擬路徑對應(yīng)的實際路徑
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.將信息保存到數(shù)據(jù)庫
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();
/**
* 根據(jù)類型編號獲得書籍
* @param typeId
* @return
*/
public List<Book> getBooksByTypeId(long typeId) {
try {
return bookDao.getBooksByTypeId(typeId);
} catch (SQLException throwables) {
throwables.printStackTrace();
return null;
}
}
/**
* 根據(jù)書籍信息來添加書本
* @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對象的數(shù)據(jù)問題
for(Book book : books) {
long typeId = book.getTypeId();
//根據(jù)typeId來尋找對應(yīng)的type
Type type = typeDao.getById(typeId);
//設(shè)置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;
}
/**
* 由行數(shù)算頁數(shù)
* @return
*/
public int getPageCount(int pageSize) {
int pagecount = 0;
try {
//1.獲取行數(shù)
int rowcount = bookDao.getCount();
//2.根據(jù)行數(shù)得到頁數(shù)-,每頁多少條
pagecount = (rowcount - 1) / pageSize + 1;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return pagecount;
}
}
書籍的dao層
public class BookDao {
QueryRunner runner = new QueryRunner();
/**
* 根據(jù)類型查詢對應(yīng)的書籍信息
*
* @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 當(dāng)前頁信息
* @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;
}
/**
* 根據(jù)書籍名字查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;
}
/**
* 獲取書籍?dāng)?shù)量
* @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;
}
/**
* 修改書籍?dāng)?shù)量
* @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層只負(fù)責(zé)與數(shù)據(jù)庫相關(guān)的基本工作
* biz層負(fù)責(zé)業(yè)務(wù)的事情
*/
總結(jié)
由于源碼太多了,無法全部發(fā)出來,我已經(jīng)把它上傳了大家可以下載用來學(xué)習(xí)。
下載地址:圖書管理系統(tǒng)
之前少了數(shù)據(jù)庫腳本,現(xiàn)在補出來。
鏈接:https://pan.baidu.com/s/1Q93tvUUAu9r46qeDKKvIjA?pwd=ckgx
提取碼:ckgx文章來源:http://www.zghlxwxcb.cn/news/detail-459709.html
遠(yuǎn)程幫你部署運行是有償?shù)模颂嗔宋也豢赡軒湍阋粋€一個來運行!
文章來源地址http://www.zghlxwxcb.cn/news/detail-459709.html
到了這里,關(guān)于【圖書管理系統(tǒng)】Servlet+JSP+MySql 實現(xiàn)的一個前后端 javaweb項目(內(nèi)附源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!