1. Phân tích chức năng
Xây dựng chức năng:
- Hiển thị
- Thêm
- Sửa
- Xoá
dữ liệu bảng sản phẩm (products)
2. Thực thi
Đối với mối chức năng chúng ta sẽ có 1 controller riêng để đảm nhiệm
2.1. Chức năng hiển thị
B1: Tạo controller IndexProductServlet kế thừa lớp BaseAdminServlet thực hiện chức năng quản lý trang hiển thị dữ liệu các sản phẩm
package binh.dev.admin.product; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.util.List; import binh.dev.BaseServlet; import binh.dev.data.dao.DatabaseDao; import binh.dev.data.model.Product; /** * * @author binhdev */ public class IndexProductServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Product> productList = DatabaseDao.getInstance().getProductDao().findAll(); request.setAttribute("productList", productList); request.getRequestDispatcher("admin/product/index.jsp").include(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
B2: Tạo giao diện index.jsp trong thư mục web/admin/products làm chức năng view
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>SB Admin 2 - Dashboard</title> <!-- Custom fonts for this template--> <link href="./assets/admin/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <!-- Custom styles for this template--> <link href="./assets/admin/css/sb-admin-2.min.css" rel="stylesheet"> </head> <body id="page-top"> <!-- Page Wrapper --> <div id="wrapper"> <!-- Sidebar --> <%@include file="../inc/sidebar.jsp" %> <!-- End of Sidebar --> <!-- Content Wrapper --> <div id="content-wrapper" class="d-flex flex-column"> <%@include file="../inc/header.jsp" %> <!-- Main Content --> <!-- Begin Page Content --> <div class="container-fluid"> <!-- Page Heading --> <h1 class="h3 mb-2 text-gray-800">PRODUCT</h1> <p class="mb-4">Danh sách tất cả mặt hàng có trong bảng product</p> <!-- DataTales Example --> <div class="card shadow mb-4"> <div class="card-header py-3"> <h6 class="m-0 font-weight-bold text-primary">DataTables Example</h6> </div> <div class="card-body"> <div class="table-responsive"> <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> <thead> <tr> <th>STT</th> <th>Picture</th> <th>Name</th> <th>Description</th> <th>Price</th> <th>Quantity</th> <th>Category</th> <th>#</th> <th>#</th> </tr> </thead> <tbody> <c:set var="index" value="0"/> <c:forEach items="${productList}" var="product"> <c:set var="index" value="${index + 1}"/> <tr> <td>${index}</td> <td> <img src="${product.thumbnail}" width="50" height="50" alt="alt"/> </td> <td>${product.name}</td> <td>${product.description}</td> <td> <fmt:setLocale value = "en_US"/> <fmt:formatNumber type="currency" value = "${product.price}" /> </td> <td>${product.quantity}</td> <td>${product.category.name}</td> <td> <a href="EditProductServlet?productId=${product.id}">Edit</a> </td> <td> <a href="DeleteProductServlet?productId=${product.id}">Delete</a> </td> </tr> </c:forEach> </tbody> </table> </div> </div> </div> </div> <!-- /.container-fluid --> <!-- End of Main Content --> <!-- Footer --> <%@include file="../inc/footer.jsp" %> <!-- End of Footer --> </div> <!-- End of Content Wrapper --> </div> <!-- End of Page Wrapper --> <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> <i class="fas fa-angle-up"></i> </a> <!-- Bootstrap core JavaScript--> <script src="./assets/admin/vendor/jquery/jquery.min.js"></script> <script src="./assets/admin/vendor/bootstrap/js/bootstrap.bundle.min.js"></script> <!-- Core plugin JavaScript--> <script src="./assets/admin/vendor/jquery-easing/jquery.easing.min.js"></script> <!-- Custom scripts for all pages--> <script src="./assets/admin/js/sb-admin-2.min.js"></script> <!-- Page level plugins --> <script src="./assets/admin/vendor/chart.js/Chart.min.js"></script> <!-- Page level custom scripts --> <script src="./assets/admin/js/demo/chart-area-demo.js"></script> <script src="./assets/admin/js/demo/chart-pie-demo.js"></script> </body> </html>
2.2. Chức năng thêm mới
B1: Tạo controller CreateProductServlet kế thừa lớp BaseAdminServlet thực hiện chức năng quản lý trang hiển thị dữ liệu các sản phẩm
package binh.dev.admin.product; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import binh.dev.BaseServlet; import binh.dev.data.dao.DatabaseDao; import binh.dev.data.model.Product; import java.util.List; import binh.dev.data.model.Category; import binh.dev.data.model.Gallery; import binh.dev.util.Constants; import binh.dev.util.UploadFileHelper; /** * * @author binhdev */ @MultipartConfig( fileSizeThreshold = 1024 * 1024 * 10, // 10 MB maxFileSize = 1024 * 1024 * 50, // 50 MB maxRequestSize = 1024 * 1024 * 100 // 100 MB ) public class CreateProductServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Category> categoryList = DatabaseDao.getInstance().getCategoryDao().findAll(); request.setAttribute("categoryList", categoryList); request.getRequestDispatcher("admin/product/create.jsp").include(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String name = request.getParameter("name"); String description = request.getParameter("description"); double price = Double.parseDouble(request.getParameter("price")); int quantity = 0; if(request.getParameter("quantity") == null) { session.setAttribute("errorMessage", "Vui lòng điền đầy đủ thông tin"); request.getRequestDispatcher("admin/product/create.jsp").forward(request, response); }else { quantity = Integer.parseInt(request.getParameter("quantity")); } int categoryId = Integer.parseInt(request.getParameter("categoryId")); Product product = new Product(name, description, price, quantity, categoryId); if (name.isEmpty() || description.isEmpty() ) { session.setAttribute("errorMessage", "Vui lòng điền đầy đủ thông tin"); request.getRequestDispatcher("admin/product/edit.jsp").forward(request, response); } int productId = DatabaseDao.getInstance().getProductDao().insert(product); createGallery(productId, request); response.sendRedirect("IndexProductServlet"); } private void createGallery(int productId, HttpServletRequest request) { List<String> photos = UploadFileHelper.uploadFile(Constants.UPLOAD_DIR, request); for (int i = 0; i < photos.size(); i++) { Gallery g = new Gallery(Constants.UPLOAD_DIR + "/" + photos.get(i), productId); DatabaseDao.getInstance().getGalleryDao().insert(g); } } }
B2: Tạo tập tin create.jsp trong thư mục web/admin/products làm chức năng view
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>CornSalad Admin - Dashboard</title> <!-- Custom fonts for this template--> <link href="./assets/admin/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <!-- Custom styles for this template--> <link href="./assets/admin/css/sb-admin-2.min.css" rel="stylesheet"> <link href="./assets/admin/css/style.css" rel="stylesheet"> </head> <body id="page-top"> <!-- Page Wrapper --> <div id="wrapper"> <!-- Sidebar --> <%@include file="../inc/sidebar.jsp" %> <!-- End of Sidebar --> <!-- Content Wrapper --> <div id="content-wrapper" class="d-flex flex-column"> <!-- Topbar --> <%@include file="../inc/header.jsp" %> <!-- End of Topbar --> <!-- Main Content --> <div class="container-fluid"> <form action="CreateProductServlet" method="post" enctype="multipart/form-data"> <div class="form-group"> <label for="exampleInputEmail1">Picture</label> <input type="file" name="photos" multiple="multiple" /> </div> <div class="form-group"> <label for="exampleInputEmail1">Name</label> <input type="text" name="name" class="form-control" placeholder="Enter name"> </div> <div class="form-group"> <label for="exampleInputEmail1">Description</label> <input type="text" name="description" class="form-control" placeholder="Enter Description"> </div> <div class="form-group"> <label for="exampleInputEmail1">Category</label> <select name="categoryId" class="form-control"> <c:forEach items="${categoryList}" var="category"> <option value="${category.id}">${category.name}</option> </c:forEach> </select> </div> <div class="form-group"> <label for="exampleInputEmail1">Price</label> <input type="number" name="price" class="form-control" placeholder="Enter Price"> </div> <div class="form-group"> <label for="exampleInputEmail1">Quantity</label> <input type="number" name="quantity" class="form-control" placeholder="Enter Quantity"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> <!-- End of Main Content --> <!-- Footer --> <%@include file="../inc/footer.jsp" %> <!-- End of Footer --> </div> <!-- End of Content Wrapper --> </div> <!-- End of Page Wrapper --> <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> <i class="fas fa-angle-up"></i> </a> <!-- Bootstrap core JavaScript--> <script src="./assets/admin/vendor/jquery/jquery.min.js"></script> <script src="./assets/admin/vendor/bootstrap/js/bootstrap.bundle.min.js"></script> <!-- Core plugin JavaScript--> <script src="./assets/admin/vendor/jquery-easing/jquery.easing.min.js"></script> <!-- Custom scripts for all pages--> <script src="./assets/admin/js/sb-admin-2.min.js"></script> <!-- Page level plugins --> <script src="./assets/admin/vendor/chart.js/Chart.min.js"></script> <!-- Page level custom scripts --> <script src="./assets/admin/js/demo/chart-area-demo.js"></script> <script src="./assets/admin/js/demo/chart-pie-demo.js"></script> </body> </html>
2.3. Chức năng cập nhật
B1: Tạo controller EditProductServlet kế thừa lớp BaseAdminServlet thực hiện chức năng cập nhật sản phẩm
package binh.dev.admin.product; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import java.util.List; import binh.dev.BaseServlet; import binh.dev.data.dao.Database; import binh.dev.data.dao.DatabaseDao; import binh.dev.data.dao.GalleryDao; import binh.dev.data.dao.ProductDao; import binh.dev.data.model.Category; import binh.dev.data.model.Gallery; import binh.dev.data.model.Product; import binh.dev.util.Constants; import binh.dev.util.UploadFileHelper; /** * * @author binhdev */ @MultipartConfig( fileSizeThreshold = 1024 * 1024 * 10, // 10 MB maxFileSize = 1024 * 1024 * 50, // 50 MB maxRequestSize = 1024 * 1024 * 100 // 100 MB ) public class EditProductServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); int productId = Integer.parseInt(request.getParameter("productId")); Product product = DatabaseDao.getInstance().getProductDao().find(productId); List<Category> categoryList = DatabaseDao.getInstance().getCategoryDao().findAll(); session.setAttribute("product", product); session.setAttribute("categoryList", categoryList); request.getRequestDispatcher("admin/product/edit.jsp").include(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); ProductDao productDao = Database.getInstance().getProductDao(); int productId = Integer.parseInt(request.getParameter("productId")); Product product = productDao.find(productId); String name = request.getParameter("name"); String description = request.getParameter("description"); double price = Double.parseDouble(request.getParameter("price")); int quantity = Integer.parseInt(request.getParameter("quantity")); int categoryId = Integer.parseInt(request.getParameter("categoryId")); product.setName(name); product.setDescription(description); product.setPrice(price); product.setQuantity(quantity); product.setCategoryId(categoryId); // if (name.isEmpty() || description.isEmpty() ) { // session.setAttribute("errorMessage", "Vui lòng điền đầy đủ thông tin"); // request.getRequestDispatcher("admin/product/edit.jsp").forward(request, response); // } productDao.update(product); updateGallery(product.getId(), request); response.sendRedirect("IndexProductServlet"); } private void updateGallery(int productId, HttpServletRequest request) { GalleryDao galleryDao = DatabaseDao.getInstance().getGalleryDao(); galleryDao.deleteByProduct(productId); List<String> photos = UploadFileHelper.uploadFile(Constants.UPLOAD_DIR, request); for (int i = 0; i < photos.size(); i++) { Gallery g = new Gallery(Constants.UPLOAD_DIR + "/" + photos.get(i), productId); galleryDao.insert(g); } } }
B2: Tạo tập tin update.jsp trong thư mục web/admin/products làm chức năng view
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>CornSalad Admin - Dashboard</title> <!-- Custom fonts for this template--> <link href="./assets/admin/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <!-- Custom styles for this template--> <link href="./assets/admin/css/sb-admin-2.min.css" rel="stylesheet"> <link href="./assets/admin/css/style.css" rel="stylesheet"> </head> <body id="page-top"> <!-- Page Wrapper --> <div id="wrapper"> <!-- Sidebar --> <%@include file="../inc/sidebar.jsp" %> <!-- End of Sidebar --> <!-- Content Wrapper --> <div id="content-wrapper" class="d-flex flex-column"> <!-- Topbar --> <%@include file="../inc/header.jsp" %> <!-- End of Topbar --> <!-- Main Content --> <div class="container-fluid"> <form action="EditProductServlet" method="post" enctype="multipart/form-data"> <input type="hidden" name="productId" value="${product.id}"> <div class="form-group"> <div class="row"> <c:forEach items="${product.galleries}" var="photo"> <div class="col-md-3"> <img class="p-thumbnail" src="${photo.url}" alt="alt"/> </div> </c:forEach> </div> </div> <div class="form-group"> <label for="exampleInputEmail1">Picture</label> <input type="file" name="photos" multiple="multiple" /> </div> <div class="form-group"> <label for="exampleInputEmail1">Name</label> <input type="text" name="name" class="form-control" placeholder="Enter name" value="${product.name}"> </div> <div class="form-group"> <label for="exampleInputEmail1">Description</label> <input type="text" name="description" class="form-control" placeholder="Enter Description" value="${product.description}"> </div> <div class="form-group"> <label for="exampleInputEmail1">Category</label> <select name="categoryId" class="form-control"> <c:forEach items="${categoryList}" var="cat"> <option <c:if test="${cat.id == category.id}">selected</c:if> value="${cat.id}">${cat.name}</option> </c:forEach> </select> </div> <div class="form-group"> <label for="exampleInputEmail1">Price</label> <input type="number" name="price" min="0" class="form-control" placeholder="Enter Price" value="${product.price}"> </div> <div class="form-group"> <label for="exampleInputEmail1">Quantity</label> <input type="number" name="quantity" class="form-control" placeholder="Enter Quantity" value="${product.quantity}"> </div> <div class="form-text text-muted" > ${errorMessage} <c:remove var="errorMessage" scope="session" /> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> <!-- End of Main Content --> <!-- Footer --> <%@include file="../inc/footer.jsp" %> <!-- End of Footer --> </div> <!-- End of Content Wrapper --> </div> <!-- End of Page Wrapper --> <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> <i class="fas fa-angle-up"></i> </a> <!-- Bootstrap core JavaScript--> <script src="./assets/admin/vendor/jquery/jquery.min.js"></script> <script src="./assets/admin/vendor/bootstrap/js/bootstrap.bundle.min.js"></script> <!-- Core plugin JavaScript--> <script src="./assets/admin/vendor/jquery-easing/jquery.easing.min.js"></script> <!-- Custom scripts for all pages--> <script src="./assets/admin/js/sb-admin-2.min.js"></script> <!-- Page level plugins --> <script src="./assets/admin/vendor/chart.js/Chart.min.js"></script> <!-- Page level custom scripts --> <script src="./assets/admin/js/demo/chart-area-demo.js"></script> <script src="./assets/admin/js/demo/chart-pie-demo.js"></script> </body> </html>
2.3. Chức năng xoá
B1: Tạo controller DeleteProductServlet kế thừa lớp BaseAdminServlet thực hiện chức năng xoá sản phẩm
package loi.dev.admin.product; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import binh.dev.BaseServlet; import binh.dev.data.dao.DatabaseDao; /** * * @author binhdev */ public class DeleteProductServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int productId = Integer.parseInt(request.getParameter("productId")); DatabaseDao.getInstance().getProductDao().delete(productId); response.sendRedirect("IndexProductServlet"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
B2: Với chức năng xoá thì chúng ta không cần giao diện chỉ sử lý việc xoá dữ liệu xong chuyển hướng trang lại trang index