CÔNG NGHỆ THÔNG TIN >> BÀI VIẾT CHỌN LỌC

Hướng dẫn các thao tác cơ bản với MongoDB trong Spring MVC-Maven-Eclipse

Đăng lúc: 11:47 AM - 04/03/2024 bởi Charles Chung - 1083

Trong bài này tôi sẽ hướng dẫn các thao tác cơ bản CRUD, tìm kiếm, phân trang với MongoDB trong Spring MVC-Maven-Eclipse

1. Kiến thức cần có

  • Thiết kế web với HTML5, CSS3, JS, JQuery, Bootstrap
  • Cơ bản về MongoDB
  • Nắm vững JavaCore
  • Nắm cơ bản về JSP Servlet, Spring MVC

2. Chuẩn bị dữ liệu

  • Tải tệp script tạo cơ sở dữ liệu trong MongoDB tại đây
  • Tải thư mục images chứa các ảnh sản phẩm tại đây
  • Tải thư mục ckeditor 3.x tại đây

3. Các chức năng trong bài viết

  • Hiển thị sản phẩm kèm tên danh mục và chi tiết
  • Thêm mới, sửa sản phẩm có upload ảnh và tích hợp ckeditor cho soạn thảo nội dung
  • Xóa sản phẩm 
  • Hiển thị sản phẩm hoa theo loại
  • Tìm kiếm sản phẩm hoa theo loại và tên
  • Tìm kiếm sản phẩm hoa theo khoảng giá
  • Phân trang sản phẩm

4. Các bước thực hiện

Bước 1: Tạo dự án

Mở Eclipse tạo loại project Dynamic Web Project và đặt tên "SpringMVCMongoDB", lưu ý sinh file web.xml trong quá trình tạo

Bước 2: Convert project sang Maven Project

Kích chuột phải vào project vừa tạo -> chọn Configure->Convert to Maven Project -> Finish

Bước 3: Mở file pom.xml và cấu hình các dependency như sau

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<dependencies>
		<!-- spring dependency -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>5.0.5.RELEASE</version>
		</dependency>
		<!-- jstl dependency -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<!-- javax servlet api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>3.0-alpha-1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-mongodb -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-mongodb</artifactId>
			<version>3.4.9</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongo-java-driver</artifactId>
			<version>3.12.14</version>
		</dependency>
		<!--https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.5</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.13.0</version>
		</dependency>
	</dependencies>

Bước 4: Copy thư mục ckeditor và images đã tải về vào thư mục src/main/webapp/resources của project (chưa có resources thì tạo ra nhé)

Bước 5: Tạo tệp tin spring-servlet.xml trong thư mục src/main/webapp/WEB-INF và cấu hình như sau

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
	<!-- chỉ ra các package chứa các lớp java được đăng ký như là các bean -->
	<context:component-scan	base-package="com.hanam88" />
	<!-- chỉ tìm kiếm các bean trong cùng context application mà nó được định nghĩa -->
	<context:annotation-config />
	<!-- mặc định các basic components được ủy quyền gửi request tới các controller -->
	<mvc:annotation-driven />
	<!-- Cấu hình đường dẫn tài nguyên được phép truy cập -->
	<mvc:resources mapping="/**" location="/resources" />
	<!-- Tạo bean xác định view sẽ được sinh ra (thư mục chứa các view, đuôi tệp tin view) -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		p:prefix="/WEB-INF/views/" p:suffix=".jsp" />
	<!-- Tạo bean xác định dữ liệu multipart khi upload file -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
</beans>

Bước 6: Mở tệp tin web.xml ở thư mục src/main/webapp/WEB-INF và cấu hình vào trong thẻ web-app như sau

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!-- Cấu hình filter hỗ trợ UTF-8 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!-- Cấu hình Dispatcher Servlet nhận các cấu hình của Spring trong file spring-servlet.xml -->
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

Bước 7: Tạo các trang jsp để hiển thị dữ liệu và các lớp entities, dao, controller để xử lý logic

Tạo thư mục views trong thư mục src/main/webapp/WEB-INF để chứa các trang jsp, sau đây là cấu trúc project đầy đủ

- Tạo lớp com.hanam88.entities/Category.java (Biểu diễn dữ liệu của collection categories)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.hanam88.entities;

import java.io.Serializable;

public class Category implements Serializable {
	private int categoryId;
	private String categoryName;
	private boolean status;
	public Category() {
		// TODO Auto-generated constructor stub
	}
	
	public Category(int categoryId, String categoryName, boolean status) {
		super();
		this.categoryId = categoryId;
		this.categoryName = categoryName;
		this.status = status;
	}

	public int getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(int categoryId) {
		this.categoryId = categoryId;
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}

	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}
	
}

- Tạo lớp com.hanam88.entities/Brand.java (Biểu diễn dữ liệu collection brands)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.hanam88.entities;

import java.io.Serializable;

public class Brand implements Serializable {
	private int brandId;
	private String brandName;
	private boolean status;
	public Brand() {
		// TODO Auto-generated constructor stub
	}
	public Brand(int brandId, String brandName, boolean status) {
		super();
		this.brandId = brandId;
		this.brandName = brandName;
		this.status = status;
	}
	public int getBrandId() {
		return brandId;
	}
	public void setBrandId(int brandId) {
		this.brandId = brandId;
	}
	public String getBrandName() {
		return brandName;
	}
	public void setBrandName(String brandName) {
		this.brandName = brandName;
	}
	public boolean isStatus() {
		return status;
	}
	public void setStatus(boolean status) {
		this.status = status;
	}	
}

- Tạo lớp com.hanam88.entities/Product.java (Biểu diễn dữ liệu collection products)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.hanam88.entities;

import java.io.Serializable;

public class Product implements Serializable{
	private String productId;
	private String productName;
	private int categoryId;
	private int brandId;
	private int price;
	private String picture;
	private String description;
	private boolean status;
	public Product() {
		// TODO Auto-generated constructor stub
	}
	public Product(String productId, String productName, int categoryId, int brandId, int price, String picture,
			String description, boolean status) {
		super();
		this.productId = productId;
		this.productName = productName;
		this.categoryId = categoryId;
		this.brandId = brandId;
		this.price = price;
		this.picture = picture;
		this.description = description;
		this.status=status;
	}
	public String getProductId() {
		return productId;
	}
	public void setProductId(String productId) {
		this.productId = productId;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public int getCategoryId() {
		return categoryId;
	}
	public void setCategoryId(int categoryId) {
		this.categoryId = categoryId;
	}
	public int getBrandId() {
		return brandId;
	}
	public void setBrandId(int brandId) {
		this.brandId = brandId;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getPicture() {
		return picture;
	}
	public void setPicture(String picture) {
		this.picture = picture;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public boolean isStatus() {
		return status;
	}
	public void setStatus(boolean status) {
		this.status = status;
	}
}

- Tạo lớp com.hanam88.entities/ProductPage.java (Biểu diễn trang dữ liệu lấy ra từ collection products)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.hanam88.entities;
import java.util.List;
public class ProductPage {
	private List<Product> products;
	private long totalPages;
	private int pageSize;
	private int currentPage;
	public ProductPage() {
		// TODO Auto-generated constructor stub
	}
	
	public ProductPage(List<Product> products, long totalPages, int pageSize, int currentPage) {
		super();
		this.products = products;
		this.totalPages = totalPages;
		this.pageSize = pageSize;
		this.currentPage = currentPage;
	}

	public List<Product> getProducts() {
		return products;
	}
	public void setProducts(List<Product> products) {
		this.products = products;
	}
	public long getTotalPages() {
		return totalPages;
	}
	public void setTotalPages(long totalPages) {
		this.totalPages = totalPages;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	public int getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
}

- Tạo lớp com.hanam88.factory/ProductModel.java (Biểu diễn dữ liệu từ Product và Category)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.hanam88.entities;

import java.io.Serializable;

public class ProductModel implements Serializable {
	private String productId;
	private String productName;
	private String categoryName;
	private int price;
	private String picture;
	private boolean status;
	public ProductModel() {
		// TODO Auto-generated constructor stub
	}
	public ProductModel(String productId, String productName, String categoryName, int price, String picture,boolean status) {
		super();
		this.productId = productId;
		this.productName = productName;
		this.categoryName = categoryName;
		this.price = price;
		this.picture = picture;
		this.status=status;
	}
	public boolean isStatus() {
		return status;
	}
	public void setStatus(boolean status) {
		this.status = status;
	}
	public String getProductId() {
		return productId;
	}
	public void setProductId(String productId) {
		this.productId = productId;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public String getCategoryName() {
		return categoryName;
	}
	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getPicture() {
		return picture;
	}
	public void setPicture(String picture) {
		this.picture = picture;
	}
	
}

- Tạo lớp com.hanam88.factory/MongoFactory.java (Kết nối với cơ sở dữ liệu mongodb)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.hanam88.factory;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
public class MongoFactory {
	private static MongoClient mongo;

	private MongoFactory() {

	}

	public static MongoClient getInstance() {
		int port = 27017;
		String hostname = "localhost";
		if (mongo == null) {
			try {
				mongo = new MongoClient(hostname, port);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return mongo;
	}

	public static MongoDatabase getDatabase() {
		return getInstance().getDatabase("bkapdb");
	}
}

- Tạo lớp com.hanam88.services/ProductService.java (Chứa các nghiệp vụ CRUD... làm việc với mongodb)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package com.hanam88.services;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bson.BsonDocument;
import org.bson.BsonInt32;
import org.bson.BsonString;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.stereotype.Service;
import com.hanam88.entities.Brand;
import com.hanam88.entities.Category;
import com.hanam88.entities.Product;
import com.hanam88.entities.ProductModel;
import com.hanam88.entities.ProductPage;
import com.hanam88.factory.MongoFactory;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;

@Service("productService")
public class ProductService {
	// phương thức lấy danh sách các brands
	public List<Brand> getBrands() {
		List<Brand> brands = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("brands");
		MongoCursor<Document> cursor = collection.find().cursor();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			brands.add(new Brand(doc.getInteger("_id"), doc.getString("BrandName"),doc.getBoolean("Status")));
		}
		return brands;
	}

	// phương thức lấy danh sách categories
	public List<Category> getCategories() {
		List<Category> categories = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("categories");
		MongoCursor<Document> cursor = collection.find().cursor();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			categories
					.add(new Category(doc.getInteger("_id"), doc.getString("CategoryName"),doc.getBoolean("Status")));
		}
		return categories;
	}

	// phương thức lấy danh sách product
	public List<Product> getProducts() {
		List<Product> products = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		MongoCursor<Document> cursor = collection.find().cursor();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		return products;
	}

	// phương thức product theo id
	public Product getProduct(String id) {
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		Bson filter = new BsonDocument("_id", new BsonString(id));
		Document doc = collection.find(filter).first();
		if (doc != null)
			return new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status"));
		else
			return null;
	}

	// Tìm sản phẩm theo category
	public List<Product> getProductCategory(int categoryId) {
		List<Product> products = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		Bson filter = new BsonDocument("CategoryId", new BsonInt32(categoryId));
		MongoCursor<Document> cursor = collection.find(filter).cursor();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		return products;
	}

	// Tìm sản phẩm theo Brand
	public List<Product> getProductBrand(int brandId) {
		List<Product> products = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		Bson filter = new BsonDocument("BrandId", new BsonInt32(brandId));
		MongoCursor<Document> cursor = collection.find(filter).cursor();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		return products;
	}

	// Tìm sản phẩm theo tên và category
	public List<Product> search(int categoryId, String name) {
		List<Product> products = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		Bson c1 = Filters.eq("CategoryId", categoryId);
		Bson c2 = Filters.regex("ProductName", "^.*" + name + ".*$");
		MongoCursor<Document> cursor = null;
		if (categoryId == 0)
			cursor = collection.find(c2).cursor();
		else
			cursor = collection.find(Filters.and(c1, c2)).cursor();// sử dụng Filters.or nếu muốn
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		return products;
	}

	// Tìm sản phẩm theo tên và category
	public List<Product> search(Integer fromPrice, Integer toPrice) {
		List<Product> products = new ArrayList<>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		Bson c1 = Filters.gte("Price", fromPrice);
		Bson c2 = Filters.lte("Price", toPrice);
		MongoCursor<Document> cursor = null;
		if (fromPrice == 0 && toPrice>0)
			cursor = collection.find(c2).cursor();
		else if (fromPrice > 0 && toPrice==0)
			cursor = collection.find(c1).cursor();
		else
			cursor = collection.find(Filters.and(c1, c2)).cursor();// sử dụng Filters.or nếu muốn
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		return products;
	}

	// thêm mới
	public void insert(Product p) {
		Document bson = new Document();
		bson.append("_id", p.getProductId());
		bson.append("ProductName", p.getProductName());
		bson.append("CategoryId", p.getCategoryId());
		bson.append("BrandId", p.getBrandId());
		bson.append("Price", p.getPrice());
		bson.append("Picture", p.getPicture());
		bson.append("Description", p.getDescription());
		bson.append("Status", p.isStatus());
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		collection.insertOne(bson);
	}

	// sửa
	public void update(Product p) {
		Document bson = new Document();
		bson.append("_id", p.getProductId());
		bson.append("ProductName", p.getProductName());
		bson.append("CategoryId", p.getCategoryId());
		bson.append("BrandId", p.getBrandId());
		bson.append("Price", p.getPrice());
		bson.append("Picture", p.getPicture());
		bson.append("Description", p.getDescription());
		bson.append("Status", p.isStatus());
		Document updateData = new Document();
		updateData.append("$set", bson);
		Bson filter = Filters.eq("_id", p.getProductId());
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		collection.updateOne(filter, updateData);
	}

	// xóa
	public void delete(String productId) {
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		collection.deleteOne(new BsonDocument("_id", new BsonString(productId)));
	}
	//phân trang
	public ProductPage paging(int pageno, int pagesize) {
		ProductPage page=new ProductPage();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		long records=collection.countDocuments();
		MongoCursor<Document> cursor= collection.find().limit(pagesize).skip((pageno-1)*pagesize).cursor();
		List<Product> products=new ArrayList<Product>();
		while (cursor.hasNext()) {
			Document doc = cursor.next();
			products.add(new Product(doc.getString("_id"), doc.getString("ProductName"), doc.getInteger("CategoryId"),
					doc.getInteger("BrandId"), doc.getInteger("Price"), doc.getString("Picture"),
					doc.getString("Description"),doc.getBoolean("Status")));
		}
		page.setProducts(products);
		long total=records%pagesize==0?records/pagesize:(records/pagesize)+1;
		page.setPageSize(pagesize);
		page.setCurrentPage(pageno);
		page.setTotalPages(total);
		return page;
	}
	//lấy dữ liệu từ nhiều bảng
	public List<ProductModel> getProductFull(){
		List<ProductModel> data=new ArrayList<ProductModel>();
		MongoCollection<Document> collection = MongoFactory.getDatabase().getCollection("products");
		MongoCursor<Document> cursor= collection.aggregate(Arrays.asList(
				new Document("$lookup",new Document("from","categories").append("localField","CategoryId").append("foreignField","_id").append("as","Categories"))
				)).cursor();
		while(cursor.hasNext()) {
			Document doc = cursor.next();
			data.add(new ProductModel(doc.getString("_id"),doc.getString("ProductName"), doc.getList("Categories",Document.class).get(0).getString("CategoryName"), doc.getInteger("Price"),doc.getString("Picture"),doc.getBoolean("Status")));
		}
		return data;
	}
}

- Tạo lớp com.hanam88.controllers/ProductController.java (Controller xử lý luồng nghiệp vụ của product)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.hanam88.controllers;
import java.io.File;
import java.io.IOException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.hanam88.entities.Product;
import com.hanam88.entities.ProductPage;
import com.hanam88.services.ProductService;

@Controller
public class ProductController {
	@Resource(name="productService")
	ProductService productService;
	
	@RequestMapping(value={"/","trang-chu"})
	public String index(Model model) {
		model.addAttribute("page", "products");
		model.addAttribute("products",productService.getProductFull());
		return "index";
	}
	@RequestMapping(value="chi-tiet/{id}")
	public String detail(@PathVariable("id") String id, Model model) {
		model.addAttribute("page", "productdetail");
		model.addAttribute("product",productService.getProduct(id));
		return "index";
	}
	@RequestMapping(value="tim-theo-danh-muc")
	public String searchcategory(Integer cateid, Model model) {
		model.addAttribute("page", "productcategory");
		model.addAttribute("categories",productService.getCategories());
		cateid=cateid==null?0:cateid;
		model.addAttribute("cateid",cateid);
		model.addAttribute("products",productService.getProductCategory(cateid));
		return "index";
	}
	@RequestMapping(value="tim-theo-ten")
	public String searchcategory(Integer cateid,String searchname, Model model) {
		model.addAttribute("page", "productsearchname");
		model.addAttribute("categories",productService.getCategories());
		cateid=cateid==null?0:cateid;
		model.addAttribute("cateid",cateid);
		model.addAttribute("searchname",searchname);
		model.addAttribute("products",productService.search(cateid, searchname));
		return "index";
	}
	@RequestMapping(value="tim-theo-gia")
	public String searchcategory(Integer fromPrice,Integer toPrice, Model model) {
		fromPrice=fromPrice==null?0:fromPrice;
		toPrice=toPrice==null?0:toPrice;
		model.addAttribute("page", "productsearchprice");
		model.addAttribute("fromPrice",fromPrice);
		model.addAttribute("toPrice",toPrice);
		model.addAttribute("products",productService.search(fromPrice, toPrice));
		return "index";
	}
	@RequestMapping(value="them-moi")
	public String add(Model model) {
		model.addAttribute("product", new Product());
		model.addAttribute("page", "add");
		model.addAttribute("categories",productService.getCategories());
		model.addAttribute("brands",productService.getBrands());
		return "index";
	}
	@RequestMapping(value = "luu", method = RequestMethod.POST)
	public String save(@ModelAttribute("product") Product product, @RequestParam("file") MultipartFile file, Model model,
			HttpServletRequest req) {
		if (file != null && !file.isEmpty()) {
			String uploadRootPath = req.getServletContext().getRealPath("resources/images");
			File destination = new File(uploadRootPath + "/" + file.getOriginalFilename());
			try {
				file.transferTo(destination);
			} catch (IllegalStateException | IOException e) {
				e.printStackTrace();
			}
			product.setPicture("/images/"+file.getOriginalFilename());
		}
		productService.insert(product);
		return "redirect:/trang-chu";
	}
	@RequestMapping(value = "xoa/{id}")
	public String delete(@PathVariable("id") String id) {
		productService.delete(id);
		return "redirect:/trang-chu";
	}
	@RequestMapping(value = "sua/{id}")
	public String edit(@PathVariable("id") String id, Model model) {
		model.addAttribute("categories", productService.getCategories());
		model.addAttribute("brands", productService.getBrands());
		model.addAttribute("product", productService.getProduct(id));
		model.addAttribute("page", "edit");
		return "index";
	}
	@RequestMapping(value = "cap-nhat", method = RequestMethod.POST)
	public String update(@ModelAttribute("product") Product product,String pictureOld, @RequestParam("file") MultipartFile file, Model model,
			HttpServletRequest req) {
		if (file != null && !file.isEmpty()) {
			String uploadRootPath = req.getServletContext().getRealPath("resources/images");
			File destination = new File(uploadRootPath + "/" + file.getOriginalFilename());
			try {
				file.transferTo(destination);
			} catch (IllegalStateException | IOException e) {
				e.printStackTrace();
			}
			product.setPicture("/images/"+file.getOriginalFilename());
		}else
		{
			product.setPicture(pictureOld);
		}
		productService.update(product);
		return "redirect:/trang-chu";
	}
	@RequestMapping(value = "phan-trang")
	public String paging(Integer pageno, Model model) {
		pageno = pageno == null ? 1 : pageno;
		model.addAttribute("page", "productpaging");
		ProductPage productPage = productService.paging(pageno, 3);
		model.addAttribute("products", productPage.getProducts());
		model.addAttribute("totalpage", productPage.getTotalPages());
		model.addAttribute("currentpage", pageno);
		return "index";
	}
}

- Tạo trang src/main/webapp/WEB-INF/views/index.jsp (hiển thị cấu trúc trang chủ mặc định hiển thị tất cả các sản phẩm)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring MVC với MongoDB</title>
<link rel="stylesheet"
	href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" />
	<script src="${pageContext.servletContext.contextPath}/resources/ckeditor/ckeditor.js"></script>
<style>
#content {
	padding: 10px;
}
</style>
</head>
<body>
	<div class="container">
		<nav class="nav">
			<a class="nav-link active" href="${pageContext.servletContext.contextPath}/trang-chu">Trang chủ</a> |
			<a class="nav-link" href="${pageContext.servletContext.contextPath}/tim-theo-danh-muc">Lọc theo danh mục</a> |
			<a class="nav-link" href="${pageContext.servletContext.contextPath}/tim-theo-ten">Tìm kiếm theo tên</a> |
			<a class="nav-link" href="${pageContext.servletContext.contextPath}/tim-theo-gia">Tìm kiếm theo giá</a> |
			<a class="nav-link" href="${pageContext.servletContext.contextPath}/phan-trang">Phân trang</a> 
		</nav>
		<hr>
		<div id="content">
			<c:if test="${!(empty page)}">
				<jsp:include page="${page}.jsp"></jsp:include>
			</c:if>
		</div>
	</div>
	<!-- Optional JavaScript -->
	<!-- jQuery first, then Popper.js, then Bootstrap JS -->
	<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
	<script
		src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js"></script>
	<script
		src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js"></script>
		
</body>
</html>

- Tạo trang src/main/webapp/WEB-INF/views/products.jsp (hiển thị tất cả các sản phẩm và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

<h4>Hiển thị tất sản phẩm</h4>
<span style="color:blue">${msg}</span>
<p><a href="them-moi" class="btn btn-primary">Thêm mới</a></p>
<table class="table table-bordered">
	<tr>
		<th>Mã sản phẩm</th>
		<th>Tên sản phẩm</th>
		<th>Loại sản phẩm</th>
		<th>Giá</th>
		<th>Ảnh</th>
		<th>Tình trạng</th>
		<th></th>
	</tr>
	<c:forEach items="${products}" var="p">
		<tr>
			<td>${p.productId}</td>
			<td>${p.productName}</td>
			<td>${p.categoryName}</td>
			<td>${p.price}</td>
			<td><img src="resources${p.picture}" width="100"/></td>
			<td><c:choose>
				<c:when test="${p.status==true}">
					Còn hàng
				</c:when>
				<c:otherwise>
					Hết hàng
				</c:otherwise>
			</c:choose>
			</td>
			<td>
				<a href="sua/${p.productId}" class="btn btn-info">Sửa</a>
				<a href="xoa/${p.productId}" class="btn btn-danger" onclick="return confirm('Bạn có muốn xóa không?')">Xóa</a>
				<a href="chi-tiet/${p.productId}" class="btn btn-success">Chi tiết</a>
			</td>
			
		</tr>
	</c:forEach>
</table>

- Tạo trang src/main/webapp/WEB-INF/views/add.jsp (thêm mới sản phẩm và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<h3>Thêm mới sản phẩm</h3>
<form:form action="luu" method="post" modelAttribute="product" enctype="multipart/form-data">
	<table class="table">
		<tr>
			<td>Mã sản phẩm</td>
			<td><form:input path="productId" /></td>
		</tr>
		<tr>
			<td>Tên sản phẩm</td>
			<td><form:input path="productName" /></td>
		</tr>
		<tr>
			<td>Loại sản phẩm</td>
			<td><form:select path="categoryId" items="${categories}" itemValue="categoryId" itemLabel="categoryName"></form:select>  </td>
		</tr>
		<tr>
			<td>Thương hiệu</td>
			<td><form:select path="brandId" items="${brands}" itemValue="brandId" itemLabel="brandName"></form:select>  </td>
		</tr>
		<tr>
			<td>Giá</td>
			<td><form:input path="price" value="0" /></td>
		</tr>
		<tr>
			<td>Mô tả đầy đủ</td>
			<td><form:textarea path="description"></form:textarea></td>
		</tr>
		<tr>
			<td>Ảnh</td>
			<td><input type="file" name="file" /></td>
		</tr>
		<tr>
			<td>Tình trạng</td>
			<td><form:checkbox path="status" checked="checked" />Còn
				hàng</td>
		</tr>
		<tr>
			<td colspan="2"><button>Lưu</button></td>
		</tr>
	</table>
</form:form>
<script>
	CKEDITOR.replace('description')
</script>

- Tạo trang src/main/webapp/WEB-INF/views/edit.jsp (sửa sản phẩm và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<h3>Sửa sản phẩm</h3>
<form:form action="${pageContext.servletContext.contextPath}/cap-nhat"
	method="post" modelAttribute="product" enctype="multipart/form-data">
	<input type="hidden" name="pictureOld" value="${product.picture}" />
	<table class="table">
		<tr>
			<td>Mã sản phẩm</td>
			<td><form:input path="productId" /></td>
		</tr>
		<tr>
			<td>Tên sản phẩm</td>
			<td><form:input path="productName" /></td>
		</tr>
		<tr>
			<td>Loại sản phẩm</td>
			<td><form:select path="categoryId" items="${categories}"
					itemValue="categoryId" itemLabel="categoryName"></form:select></td>
		</tr>
		<tr>
			<td>Thương hiệu</td>
			<td><form:select path="brandId" items="${brands}"
					itemValue="brandId" itemLabel="brandName"></form:select></td>
		</tr>
		<tr>
			<td>Giá</td>
			<td><form:input path="price"/></td>
		</tr>
		<tr>
			<td>Mô tả đầy đủ</td>
			<td><form:textarea path="description"></form:textarea></td>
		</tr>
		<tr>
			<td>Ảnh</td>
			<td><input type="file" name="file" /></td>
		</tr>
		<tr>
			<td>Tình trạng</td>
			<td><form:checkbox path="status"/>Còn hàng</td>
		</tr>
		<tr>
			<td colspan="2"><button>Lưu</button></td>
		</tr>
	</table>
</form:form>
<script>
	CKEDITOR.replace('description')
</script>

- Tạo trang src/main/webapp/WEB-INF/views/productdetail.jsp (hiển thị chi tiết sản phẩm và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>
<h4>CHI TIẾT SẢN PHẨM</h4>
<div class="row" style="border: 1px gray solid;border-radius:5px;">
	<div class="col-3">
		<img src="${pageContext.servletContext.contextPath}/resources${product.picture}" width="95%" />
	</div>
	<div class="col-9">
		<p>${product.productName}</p>
		<p>
			Giá mới:<f:formatNumber value="${product.price}" />	đ
		</p>
		<p>Loại: ${product.categoryId}</p>
		<p>Thương hiệu: ${product.brandId}</p>
	</div>
	<div class="col-12">
		<h4>Mô tả</h4>
		<p>${product.description}</p>
		<p><a href="javascript:history.back()">Quay lại</a>
	</div>
</div>

- Tạo trang src/main/webapp/WEB-INF/views/productcategory.jsp (hiển thị các sản phẩm theo loại và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

<h4>Tìm kiếm theo danh mục sản phẩm</h4>
<form action="" method="post">
	<select name="cateid" onchange="forms[0].submit()" class="form-control">
		<option value="0">---------Chọn danh mục sản phẩm---------</option>
		<c:forEach var="c" items="${categories}">
			<c:choose>
				<c:when test="${c.categoryId==cateid}">
					<option value="${c.categoryId}" selected>${c.categoryName}</option>
				</c:when>
				<c:otherwise>
					<option value="${c.categoryId}">${c.categoryName}</option>
				</c:otherwise>
			</c:choose>
		</c:forEach>
	</select>
</form>
<hr>
<table class="table table-bordered">
	<tr>
		<th>Mã sản phẩm</th>
		<th>Tên sản phẩm</th>
		<th>Giá</th>
		<th>Ảnh</th>
		<th>Tình trạng</th>
		<th></th>
	</tr>
	<c:forEach items="${products}" var="p">
		<tr>
			<td>${p.productId}</td>
			<td>${p.productName}</td>
			<td>${p.price}</td>
			<td><img src="resources${p.picture}" width="100"/></td>
			<td><c:choose>
				<c:when test="${p.status==true}">
					Còn hàng
				</c:when>
				<c:otherwise>
					Hết hàng
				</c:otherwise>
			</c:choose>
			</td>
		</tr>
	</c:forEach>
</table>

- Tạo trang src/main/webapp/WEB-INF/views/productsearchname.jsp (tìm kiếm sản phẩm theo tên - loại và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

<h4>Tìm kiếm theo loại và tên</h4>
<form action="" method="post">
	Chọn loại hoa <select name="cateid">
		<option value="0">---------Chọn danh mục sản phẩm---------</option>
		<c:forEach var="c" items="${categories}">
			<c:choose>
				<c:when test="${c.categoryId==cateid}">
					<option value="${c.categoryId}" selected>${c.categoryName}</option>
				</c:when>
				<c:otherwise>
					<option value="${c.categoryId}">${c.categoryName}</option>
				</c:otherwise>
			</c:choose>
		</c:forEach>
	</select>
	 <input type="text" name="searchname" value="${searchname}" placeholder="Nhập tên cần tìm"/>
	 <button class="btn btn-primary key">Tìm</button>
</form>
<hr>
<table class="table table-bordered">
		<tr>
		<th>Mã sản phẩm</th>
		<th>Tên sản phẩm</th>
		<th>Giá</th>
		<th>Ảnh</th>
		<th>Tình trạng</th>
		<th></th>
	</tr>
	<c:forEach items="${products}" var="p">
		<tr>
			<td>${p.productId}</td>
			<td>${p.productName}</td>
			<td>${p.price}</td>
			<td><img src="resources${p.picture}" width="100"/></td>
			<td><c:choose>
				<c:when test="${p.status==true}">
					Còn hàng
				</c:when>
				<c:otherwise>
					Hết hàng
				</c:otherwise>
			</c:choose>
			</td>
		</tr>
	</c:forEach>
</table>

- Tạo trang src/main/webapp/WEB-INF/views/productsearchprice.jsp (tìm kiếm sản phẩm theo khoảng giá và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

<h4>Tìm kiếm theo khoảng giá</h4>
<form action="tim-theo-gia" method="post">
	Nhập giá từ <input type="number" name="fromPrice" value="${fromPrice}"/> đến giá 
	 <input type="number" name="toPrice" value="${toPrice}"/>
	 <button class="btn btn-primary key">Tìm</button>
</form>
<hr>
<table class="table table-bordered">
	<tr>
		<th>Mã sản phẩm</th>
		<th>Tên sản phẩm</th>
		<th>Giá</th>
		<th>Ảnh</th>
		<th>Tình trạng</th>
		<th></th>
	</tr>
	<c:forEach items="${products}" var="p">
		<tr>
			<td>${p.productId}</td>
			<td>${p.productName}</td>
			<td>${p.price}</td>
			<td><img src="resources${p.picture}" width="100"/></td>
			<td><c:choose>
				<c:when test="${p.status==true}">
					Còn hàng
				</c:when>
				<c:otherwise>
					Hết hàng
				</c:otherwise>
			</c:choose>
			</td>
		</tr>
	</c:forEach>
</table>

- Tạo trang src/main/webapp/WEB-INF/views/productpaging.jsp (phân trang sản phẩm và include vào trang index.jsp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

<h4>Phân trang sản phẩm</h4>
<hr>
<table class="table table-bordered">
	<tr>
		<th>Mã sản phẩm</th>
		<th>Tên sản phẩm</th>
		<th>Giá</th>
		<th>Ảnh</th>
		<th>Tình trạng</th>
	
	</tr>
	<c:forEach items="${products}" var="p">
		<tr>
			<td>${p.productId}</td>
			<td>${p.productName}</td>
			<td>${p.price}</td>
			<td><img src="resources${p.picture}" width="100"/></td>
			<td><c:choose>
				<c:when test="${p.status==true}">
					Còn hàng
				</c:when>
				<c:otherwise>
					Hết hàng
				</c:otherwise>
			</c:choose>
			</td>
			
		</tr>
	</c:forEach>
</table>
Trang:
<c:forEach var="i" begin="1" end="${totalpage}">
	<c:choose>
		<c:when test="${i==currentpage}">
			<span> ${i} </span>
		</c:when>
		<c:otherwise>
			<a href="phan-trang?pageno=${i}"> ${i} </a>
		</c:otherwise>
	</c:choose>
</c:forEach>

Bước 8: Run và kiểm tra kết quả

- Màn hình hiển thị tất cả các sản phẩm với các nút thêm/xóa/sửa/xem chi tiết 

- Màn hình thêm sản phẩm

- Màn hình sửa sản phẩm

- Màn hình chi tiết sản phẩm

- Màn hình lọc sản phẩm theo danh mục

- Màn hình tìm kiếm theo loại và tên

- Màn hình tìm kiếm theo khoảng giá

- Màn hình phân trang sản phẩm

Link tải source code

Video đang quay

thay lời cảm ơn!

QUẢNG CÁO - TIẾP THỊ