Professional Documents
Culture Documents
HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG
TIN
BÁO CÁO ĐỒ ÁN
CÔNG NGHỆ JAVA
ĐỀ TÀI
SỬ DỤNG FRAMEWORK SPRING XÂY
DỰNG WEBSITE BÁN HÀNG ĐIỆN TỬ
Lời đầu tiên, nhóm chúng em xin gửi lời cảm ơn chân thành đến quý Thầy cô giảng
viên Trường Đại học Công nghệ Thông tin - Đại học Quốc gia TP.HCM và quý thầy cô
khoa Khoa học và Kỹ thuật thông tin đã giúp cho nhóm chúng em có những kiến thức cơ
bản làm nền tảng để thực hiện đề tài này.
Trong thời gian một học kỳ thực hiện đề tài, nhóm chúng em đã vận dụng những
kiến thức nền tảng đã tích lũy đồng thời kết hợp với việc học hỏi và nghiên cứu những
kiến thức mới từ thầy cô, bạn bè cũng như nhiều nguồn tài liệu tham khảo.
Từ những gì đã học được nhóm chúng em lựa chọn đề tài xây dựng một trang web
bán hàng hóa điên tử dựa trên việc sử dụng công nghệ Spring.
Tuy nhiên, vì kiến thức chuyên môn còn hạn chế và bản thân còn thiếu nhiều kinh
nghiệm thực tiễn nên nội dung của báo cáo không tránh khỏi những thiếu xót, em rất
mong nhận được sự góp ý, chỉ bảo thêm của quý thầy cô nhằm hoàn thiện những kiến
thức của mình để nhóm chúng em có thể dùng làm hành trang thực hiện các đề tài khác
trong tương lai cũng như là trong việc học tập và làm việc sau này.
MỤC LỤC
1 Framework Spring...............................................................................................6
2 ReactJS................................................................................................................7
1 Khảo sát các trang web bán hàng điện tử liên quan...........................................10
1.2 Các thành phần giao diện và chức năng của trang web thegioididong.com.
.................................................................................................................................. 10
2.1 Lưu trữ thông tin đăng nhập tài khoản người dùng....................................31
2.2 Lưu trữ thông tin liên quan User................................................................33
2.3 Lưu trữ thông tin liên lạc của người dùng..................................................34
2.13 Lưu trữ thông tin các sản phẩm trong đơn hàng.......................................47
2.14 Lưu trữ hình ảnh quảng cáo đầu trang web...............................................48
4 Thanh toán.......................................................................................................102
1 Kết luận...........................................................................................................118
Hình 2-4 Phần trên trang chi tiết sản phẩm thegioididong........................................15
Hình 2-5 Phần dưới trang chi tiết sản phẩm thegioididong......................................15
Hình 2-6 Bình luận sản phẩm trong trang chi tiết sản phẩm thegioididong..............16
Hình 2-8 Giao diện đơn hàng của khách hàng thegioididong...................................18
Hình 2-9 Giao diện đơn hàng bị khách hàng hủy thegioididong..............................19
Hình 4-6 Thông báo lỗi đăng ký với Email trùng lặp...............................................66
Hình 4-10 Email với đường dẫn xác nhận được gửi.................................................69
Hình 4-11 Xử lý xác nhận Email dựa trên Token nhận được...................................69
Hình 4-12 Thông báo khi xác nhận Email thành công.............................................70
2
Hình 4-13 Thông báo khi Token Verify Email hết hạn............................................70
Hình 4-14 Hiển thị thông báo Email đã được xác nhận............................................70
Hình 4-17 Đăng nhập với thông tin tài khoản sai.....................................................72
Hình 4-22 Tính năng lấy lại mật khẩu ở Form đăng nhập........................................78
Hình 4-25 Email xác nhận reset password không tồn tại..........................................79
Hình 4-29 Thông báo đổi mật khẩu với mật khẩu xác nhận không chính xác..........81
Hình 4-39 Thông tin các file được upload thông qua Endpoint................................86
Hình 4-43 Xử lý lỗi thiếu thông tin khi thêm sản phẩm phía Server........................88
Hình 4-45 Hiển thị danh sách sản phẩm ở trang chủ................................................89
Hình 4-46 Danh sách sản phẩm ở trang sản phẩm theo phân loại............................90
Hình 4-47 Các tiêu chí tìm kiếm danh sách sản phẩm gửi đến Server thông qua url
query parameters............................................................................................................... 91
Hình 4-50 Giao diện phía trên trang chi tiết sản phẩm.............................................93
Hình 4-51 Giao diện phía dưới trang chi tiết sản phẩm............................................93
Hình 4-52 Thông tin của mỗi sản phẩm trong danh sách sản phẩm.........................94
Hình 4-54 Quá trình đánh giá sản phẩm được thêm.................................................95
Hình 4-55 Hiển thị thông báo và đánh giá sau khi đánh giá được thêm thành công.95
Hình 4-56 Nút "chỉnh sửa" sử dụng cho việc cập nhật thông tin sản phẩm..............96
Hình 4-57 Các thông tin hiện tại của sản phẩm trong Form cập nhật sản phẩm.......96
Hình 4-59 Thông báo cập nhật thông tin sản phẩm thành công................................97
4
Hình 4-60 Popup xác nhận xóa sản phẩm................................................................98
Hình 4-63 Thêm sản phẩm vào giỏ hàng thành công...............................................99
Hình 4-64 Thông báo sản phẩm đã thêm vào giỏ hàng..........................................100
Hình 4-69 Quy trình xóa sản phẩm trong giỏ hàng................................................103
Hình 4-70 Thông báo xóa sản phẩm trong giỏ hàng thành công............................103
Hình 4-72 Quá trình xử lý thêm đơn hàng thanh toán COD...................................105
Hình 4-80 Lưu đơn hàng khi nhận được Event Webhook
checkout.session.completed............................................................................................110
Hình 4-81 Danh sách đơn hàng đã đặt ở trang Profile User...................................111
Hình 4-82 Lấy dữ liệu các đơn hàng thuộc về một User........................................111
5
Hình 4-83 Dữ liệu JSON danh sách đơn hàng của một User..................................112
Hình 4-93 Dữ liệu JSON của danh sách các quảng cáo..........................................118
6
CHƯƠNG 1 TỔNG QUAN CÔNG NGHỆ SỬ DỤNG XÂY
DỰNG WEBSITE
1 Framework Spring.
1.1 Giới thiệu
Spring là một Framework phát triển các ứng dụng Java được sử dụng bởi hàng triệu
lập trình viên. Nó giúp tạo các ứng dụng có hiệu năng cao, dễ kiểm thử, sử dụng lại
code…
Spring là một mã nguồn mở, được phát triển, chia sẻ và có cộng đồng người dùng
rất lớn.
Spring Framework được xây dựng dựa trên 2 nguyên tắc design chính là:
Dependency Injection và Aspect Oriented Programming.
Những tính năng core (cốt lõi) của Spring có thể được sử dụng để phát triển Java
Desktop, ứng dụng mobile, Java Web. Mục tiêu chính của Spring là giúp phát triển các
ứng dụng J2EE một cách dễ dàng hơn dựa trên mô hình sử dụng POJO (Plain Old Java
Object)
Spring cho phép lập trình viên sử dụng POJOs. Việc sử dụng POJOs giúp ta
không phải làm việc với EJB (Enterprise Java Beans), ứng dụng, các luồng chạy,
cấu hình… giúp công việc đơn giản hơn rất nhiều.
Spring được tổ chức theo kiểu mô đun. Số lượng các gói và các lớp tính năng cụ
thể. Khi phát triển ứng dụng, nhà phát triển chỉ cần quan tâm đến những gì cần
thiết cho dự án và không cần quan tâm đến phần còn lại.
Spring hỗ trợ sử dụng khá nhiều công nghệ như ORM Framework, các logging
framework, JEE, các thư viện tạo lịch trình (Quartz và JDK timer)…
7
Module Web của Spring được thiết kế theo mô hình MVC nên nó cung cấp đầy
đủ các tính năng giúp thay thế các web framework khác như Struts.
Là công nghệ chính sử dụng trong đề tài của đồ án. Được sử dụng để xây dụng các
RESTful API chứa các dữ liệu cần thiết dùng để xây dựng, hiển thị giao diện trang web.
2 ReactJS
2.1 Giới thiệu
React là một thư viện UI phát triển tại Facebook để hỗ trợ việc xây dựng những
thành phần (components) UI có tính tương tác cao, có trạng thái và có thể sử dụng lại
được. React được sử dụng tại Facebook trong production, và instagram được viết hoàn
toàn trên React.
Một trong những điểm hấp dẫn của React là thư viện này không chỉ hoạt động trên
phía client, mà còn được render trên server và có thể kết nối với nhau. React so sánh sự
thay đổi giữa các giá trị của lần render này với lần render trước và cập nhật ít thay đổi
nhất trên DOM.
Lợi ích đầu tiên mà ReactJS đó chính là việc tạo ra cho chính bản thân nó một dom
ảo, đây là nơi mà các component được tồn tại trên đó. Việc tạo ra dom như vậy giúp cải
thiện hiệu suất làm việc rất nhiều, khi có tính toán cần thay đổi hoặc cần cập nhật những
gì lên Dom thì ReactJS đều tính toán trước và việc còn lại chỉ là thực hiện chúng lên
Dom, làm như vậy sẽ giúp cho ReactJS tránh được những thao tác cần có trên một Dom
mà không cần tốn thêm bất cứ chi phí nào.
Lợi ích thứ hai mà ReactJS đem lại đó chính là việc viết các đoạn code JS sẽ trở nên
dễ dàng hơn vì nó sử dụng một cú pháp đặc biệt đó chính là cú pháp JSX nghĩa là cú pháp
này cho phép ta trộn được giữa code HTML và Javascript. Ngoài ra ta còn có thể đem
đoạn code thêm vào trong hàm render mà không cần phải thực hiện việc nối chuỗi và đây
được đánh giá là một trong những đặc tính thú vị của ReactJS và việc chuyển đổi các
8
đoạn HTML thành các hàm khởi động đều được thực hiện từ bộ biến đổi chính đó chính
là JSX.
Có nhiều công cụ phát triển là lợi ích tiếp theo của ReactJS. Các ứng dụng hỗ trợ
phong phú giúp việc viết mã và sửa lỗi diễn ra một cách dễ dàng hơn.
Xây dựng các Component giao diện tương tác với hệ thống Backend của trang web
thông qua việc gửi các request đến các RESTful API.
Máy chủ cơ sở dữ liệu MySQL đáp ứng nhiều tính năng linh hoạt, nó có sức chứa để
xử lý các ứng dụng được nhúng sâu với 1MB dung lượng để chạy kho dữ liệu khổng lồ
lên đến hàng terabytes thông tin. Đặc tính đáng chú ý của MySQL là sự linh hoạt về
flatform với tất cả các phiên bản của Windows, Unix và Linux đang được hỗ trợ. Và
đương nhiên, tính chất mã nguồn mở của MySQL cho phép tùy biến theo ý muốn để thêm
các yêu cầu phù hợp cho database server.
Với kiến trúc storage-engine cho phép các chuyên gia cơ sở dữ liệu cấu hình máy
chủ cơ sở dữ liệu MySQL đặc trưng cho các ứng dụng chuyên biệt. Dù ứng dụng là
website dung lượng lớn phục vụ hàng triệu người/ngày hay hệ thống xử lý giao dịch tốc
độ cao thì MySQL đều đáp ứng được khả năng xử lý khắt khe của mọi hệ thống. Với
những tiện ích tải tốc độ cao, cơ chế xử lý nâng cao khác và đặc biệt bộ nhớ caches,
9
MySQL đưa ra tất cả nhưng tính năng cần có cho hệ thống doanh nghiệp khó tính hiện
nay.
MySQL đảm bảo sự tin cậy và có thể sử dụng ngay. MySQL đưa ra nhiều tùy chọn
có thể thiết lập ngay từ cấu hình tái tạo chủ/tớ tốc độ cao, để các nhà phân phối thứ 3 có
thể đưa ra những điều hướng có thể dùng ngay duy nhất cho server cơ sở dữ liệu MySQL.
Lưu trữ dữ liệu trang web thông qua hỗ trợ của các POJO được tạo trong dự án
spring framework.
10
CHƯƠNG 2 PHÂN TÍCH THIẾT KẾ HỆ THỐNG WEBSITE
1 Khảo sát các trang web bán hàng điện tử liên quan.
Việc khảo sát các trang web đã có trước khi xây dựng một trang web mới có cùng
hình thức kinh doanh giúp cho việc xây dựng trang web mới dễ dàng hơn, tránh đi sai
hướng phát triển cũng như giúp cho tốc độ xây dựng và quá trình phát triển diễn ra nhanh
hơn thay vì phải tự phân tích thiết kế một trang web hoàn toàn mới.
Trong đồ án này, nhóm tập trung khảo sát các thành phần giao diện và một số tính
năng cần có của một website bán hàng điện tử dựa trên website khảo sát là Thế Giới Di
Động của công ty TNHH Thế Giới Di Động (www.thegioididong.com).
Công ty TNHH Thế Giới Di Động (Mobile World Co. Ltd) thành lập vào tháng
03/2004 bởi 5 thành viên đồng sáng lập là Trần Lê Quân, Nguyễn Đức Tài, Đinh Anh
Huân, Điêu Chính Hải Triều và Trần Huy Thanh Tùng, lĩnh vực hoạt động chính của
công ty bao gồm: mua bán sửa chữa các thiết bị liên quan đến điện thoại di động, thiết bị
kỹ thuật số và các lĩnh vực liên quan đến thương mại điện tử. Bằng trải nghiệm về thị
trường điện thoại di động từ đầu những năm 1990, cùng với việc nghiên cứu kỹ tập quán
mua hàng của khách hàng Việt Nam, thegioididong.com đã xây dựng một phương thức
kinh doanh chưa từng có ở Việt Nam trước đây. Công ty đã xây dựng được một phong
cách tư vấn bán hàng đặc biệt nhờ vào một đội ngũ nhân viên chuyên nghiệp và trang
web www.thegioididong.com hỗ trợ như là một cẩm nang về điện thoại di động và một
kênh thương mại điện tử hàng đầu tại Việt Nam.
1.2 Các thành phần giao diện và chức năng của trang web thegioididong.com.
1.2.1 Giao diện đầu trang chủ
Trên cùng giao diện trang chủ là thanh điều hướng giúp cho người dùng có thể
nhanh chóng nhận ra các loại sản phẩm mà công ty đang kinh doanh.
11
Dưới thanh điều hướng là phần nội dung giới thiệu các chương trình kinh doanh và
sự kiện mà công ty đang thực hiện dựa vào một slider quảng cáo bên trái. Kèm theo slider
bên trái giao diện là khung banner nằm bên phải, với mục đích giới thiệu các sản phẩm
mà công ty muốn tạo sự nổi bật trong mắt người dùng hơn.
Dưới phần thanh điều hướng và các slider, banner quảng cáo là phần giới thiệu một
vài sản phẩm nổi bật cũng như sản phẩm mới mà công ty đang kinh doanh.
Phần danh sách sản phẩm này không hiển thị hết các sản phẩm mà chỉ hiện thị một
số lượng nhất định các sản phẩm. Các sản phẩm được hiển thị một các tách biệt nhau dựa
trên các khung giao diện.
Các danh sách sản phẩm được phân chia theo các loại khác nhau để dễ dàng phân
biệt như: “điện thoại nổi bật”, “điện thoại mới”, “laptop nổi bật”…
12
Hình 2-2 Hiển thị sản phẩm ở trang chủ
1.2.3 Thông tin sản phẩm được hiện thị ở trang chủ
Thông tin một sản phẩm được hiển thị ở trang chủ bao gồm các thành phần sau:
13
Hình 2- 3 Giao diện sản phẩm ở trang chủ thegioididong
Giao diện sản phẩm chứa các thông tin chi tiết hơn của sản phẩm. Bao gồm các
thành phần sau:
Phần phía trên gồm: Slider hình ảnh sản phẩm, tên sản phẩm, giá tiền, đánh giá,
giảm giá.
14
Hình 2-4 Phần trên trang chi tiết sản phẩm thegioididong
Phần nội dung phía dưới gồm: Thông tin đánh giá mô ta sản phẩm nằm bên trái
và bảng cấu hình sản phẩm nằm bên phải.
Hình 2-5 Phần dưới trang chi tiết sản phẩm thegioididong
Khung bình luận, đánh giá của khách hàng về sản phẩm nằm ở cuối trang với
bình luận gồm đánh giá sao sản phẩm và nội dung bình luận bằng văn bảng.
15
Hình 2- 6 Bình luận sản phẩm trong trang chi tiết sản phẩm thegioididong
Giỏ hàng là nơi lưu trữ tạm thời các sản phẩm mà người dùng đã thêm trước đó để
chờ sau khi người dùng lựa chọn sản phẩm thành công thì mới tiến hành việc thanh toán.
Danh sách sản phẩm với mỗi sản phẩm hiển thị các thông tin như: tên sản phẩm.
giá tiền, giá tiền với giảm giá, số lượng.
Thông tin liên hệ gồm tên khách hàng, số điện thoại, địa chỉ…
16
Hình 2- 7 Giao diện giỏ hàng thegioididong
17
1.2.6 Giao diện trang đặt hàng
Chứa thông tin các đơn hàng của chính khách hàng đã đặt trước đó. Gồm các thông
tin như:
Mã đơn hàng
Danh sách sản phẩm
Giá tiền cho mỗi sản phẩm
Số lượng cho mỗi sản phẩm
Tổng tiền cho tất cả sản phẩm
Ngày đặt mua
Địa chỉ nhận hàng
Trạng thái đơn hàng
Hình 2-8 Giao diện đơn hàng của khách hàng thegioididong
Ngoài ra khách hàng có thể tự hủy đơn hàng của chính bản thân
18
Hình 2-9 Giao diện đơn hàng bị khách hàng hủy thegioididong
Sau khi tiến hàng bước khảo sát các trang web có sẵn, nhóm thực hiện đồ án tiến
hành đặc tả các yêu cầu cần có cho trang web đồ án.
19
Tài khoản có quyền admin có tất cả các quyền của một tài khoản user bình
thường nào khác
Tài khoản người dùng sẽ bị giới hạn quyền thao tác với trang web nếu tài khoản
không có quyền admin.
Người dùng có thể xem tất cả các thông tin sản phẩm của cửa hàng, hình ảnh, văn
bản, giá cả, thông số kỹ thuật, nhãn hiệu…
Có thể lọc sản phẩm theo nhu cầu mua hàng.
Người dùng có thể thêm sản phẩm vào giỏ hàng, thay đổi số lượng sản phẩm cần
mua có trong giỏ hàng, xem tổng giá trị giỏ hàng trước khi tiến hành thanh toán.
Xem trạng thái đơn hàng đã đặt trong phần danh sách đơn hàng, có thể hủy đơn
hàng trước khi nhận hàng.
Giao diện hệ thống phải dễ sử dụng, trực quan, thân thiện với người dùng.
Tốc độ xử lý nhanh chóng, chính xác
Tính bảo mật và độ an toàn cao.
Trang web tương thích với các trình duyệt khác nhau.
20
3 Các chức năng của trang web
3.1 Chức năng quản lý hệ thống
21
4.2 Use – case đăng nhập
Mô tả: Use – case cho người dùng đăng nhập vào hệ thống.
Điều kiện trước: Người dùng chưa đăng nhập trước đó.
22
4.3 Use – case quản lý sản phẩm
Mô tả: Use – case cho admin quản lý danh sách, thông tin sản phẩm.
Điều kiện trước: Người dùng đã đăng nhập với tài khoản Admin.
23
4.4 Use – case quản lý giỏ hàng
Mô tả: Use – case cho phép người dùng quản lý danh sách sản phẩm trong giỏ hàng.
Điều kiện trước: Người dùng đã đăng nhập vào trang web.
Mô tả: Use – case thanh toán các sản phẩm chọn mua có trong giỏ hàng.
Điều kiện trước: Người dùng đã đăng nhập vào trang web và giỏ hàng có sản phẩm
đã chọn mua.
24
Dòng sự kiện chính:
Nhấn vào nút thanh toán trong giao diện giỏ hàng
Lựa chọn phương thức thanh toán
Tiến hành thanh toán
Mô tả: Use – case cho admin quản lý danh sách, trạng thái của các đơn hàng.
Điều kiện trước: Người dùng đã đăng nhập với tài khoản Admin.
Admin vào trang quản lý đơn hàng được hiển thị trên giao diện
Cập nhật trạng thái các đơn hàng
Gửi mail trạng thái đơn hàng
Mô tả: Use – case cho admin quản lý danh sách hình ảnh quảng cáo trên slider,
banner đầu trang chủ.
Điều kiện trước: Người dùng đã đăng nhập với tài khoản Admin.
25
Admin vào trang quản lý Header
Thêm, sửa, xóa, cập nhật các hình ảnh vào thông tin
26
CHƯƠNG 3 THAO TÁC VÀ LƯU TRỮ DỮ LIỆU
JPA (Java Persistence API) là 1 giao diện lập trình ứng dụng Java, nó mô tả cách
quản lý các mối quan hệ dữ liệu trong ứng dụng sử dụng Java Platform.
JPA có thể xem như cầu nối giữa Java object và cơ sở dữ liệu quan hệ. Là một tập
hợp các đặc tả (các interface), JPA không chứa bất kỳ phương thức thực thi nào, nó cần
một JPA implementation triển khai tất cả các đặc tả mà nó định nghĩa. Những ORM tools
như Hibernate, TopLink đều cung cấp trình triển khai cho JPA.
Entity
Entity là các đối tượng thể hiện tương ứng 1 table trong cơ sở dữ liệu. Entity thường
là các class POJO đơn giản, chỉ gồm các phương thức getter, setter.
EntityManager
EntityManager là một interface cung cấp các API cho việc tương tác với các Entity.
Persist: phương thức này dùng để lưu một thực thể mới tạo vào cơ sở dữ liệu.
Merge: dùng để cập nhật trạng thái của entity vào cơ sở dữ liệu.
Remove: xóa một instance của entity.
EntityManagerFactory
Persistence
Một Persistence định nghĩa một tập hợp các Entity class được quản lý bởi 1 instacne
của EntityManager trong ứng dụng.
EntityTransaction
Một Transaction là một tập hợp các thao tác trong đó tất cả các thao tác phải được
thực hiện thành công hoặc tất cả thất bại.
Một database transaction bao gồm một tập hợp các câu lệnh SQL được committed
hoặc rolled back trong một unit.
EntityTransaction có quan hệ 1-1 với EntityManager. Bất kỳ thao tác nào được bắt
đầu thông qua đối tượng EntityManager đều được đặt trong một Transaction. Đối tượng
EntityManager giúp tạo EntityTransaction.
28
Query
Đây là một interface, được mỗi nhà cung cấp JPA implement để có được các đối
tượng quan hệ đáp ứng các tiêu chí (criteria) truy vấn.
ORM viết tắt của object-relational-mapping, công nghệ cho phép chuyển đổi từ các
object trong ngôn ngữ hướng đối tượng sang database quan hệ và ngược lại.
Hibernate là một trong những ORM tools phổ biến được sử dụng nhiều trong các
ứng dụng Java. Từ phiên bản 3.2 trở về sau, Hibernate đã cung cấp một JPA Implement
và được sử dụng khá rộng trong cộng đồng.
DAO Pattern là một mẫu thiết kế được sử dụng phổ biến trong truy xuất cơ sở dữ
liệu, tư tưởng của nó là tạo ra nơi cung cấp các method để truy xuất dữ liệu ở mức low-
level, khi đó các service hay business layer (high-level) sẽ sử dụng nó đó để truy cập cơ
sở dữ liệu lấy dữ liệu, do vậy tầng service sẽ được che dấu về cách thực hiện của các
method cấp thấp (low-level) đó. Hay còn được gọi là nguyên tắc Tách logic (Separation
of Logic).
Tư tưởng sử dụng:
Các service hay business layer sẽ không giao tiếp trực tiếp với DB để lấy dữ liệu.
29
Các service sẽ giao tiếp với lớp trung gian DAO, sau đó lớp DAO sẽ giao tiếp với
DB để truy vấn dữ liệu.
DAO Pattern dựa trên các nguyên tắc thiết kế abstraction và encapsulation. Nó
bảo vệ phần còn lại của ứng dụng khỏi mọi thay đổi trong lớp lưu trữ, ví dụ: thay
đổi database từ Oracle sang MySQL, thay đổi công nghệ lưu trữ từ file sang
database.
30
1.4 Spring Data JPA
Spring Data JPA là tầng được xây dự phía trên tầng JPA. Nó sẽ sử dụng tất cả các
chức năng của JPA như entity mapping, entity life-lifecycle, JPA query v.v để xây dựng
một số tính năng như no-code repository, khởi tạo query thông qua tên hàm…
No-code Repository
Spring Data JPA cung một tập hợp các repository interface, chỉ cần extend để có
được sự cung cấp mặc định của các hàm CRUD (thêm, tạo, sửa, xóa…).
Một tính năng tiện lợi khác của Spring Data JPA là tạo các truy vấn database dựa
trên tên hàm. Nếu một câu truy vấn không quá phức tập thì chúng ta chỉ cần định nghĩa
tên hàm trong repository bắt đầu bằng chữ findBy và kế tiếp là tên các thuộc tính tương
ứng kết hợp các phép AND, OR thì Spring Data sẽ giúp sinh ra câu truy vấn cách tự động.
Vd: khi khởi tạo một hàm trong Repository Interface là findByTitle(String title),
Spring Data JPA sẽ sinh ra câu truy vấn tìm kiếm các entity theo title một cách tự động,
đẩy giá trị title từ tham số đầu vào câu truy vấn.
31
1.5 Kiến trúc tổng quát
Controller: là tầng giao tiếp với bên ngoài và handler các request từ bên ngoài tới
hệ thống.
Repository Layer: Chịu trách nhiệm giao tiếp với các DB, thiết bị lưu trữ, xử lý
query và trả về các kiểu dữ liệu mà tầng Service yêu cầu. Nhận hỗ trợ từ Spring Data
JPA.
Các thông tin được lưu trữ bao gồm của tài khoản người dùng như Email và
Password…
32
2.1.1 UserCredential Entity
UserCredential
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi User
email String Email của user, không trùng nhau
password String Mật khẩu dùng để đăng nhập
provider AuthProvider (enum) Gồm local, facebook, google
provider_id Long Id có được khi đăng nhập bằng
Facebook và Google
user_id User Quan hệ @OneToOne với User
Quan hệ @ManyToMany với bảng
roles Set<role>
Role, tạo bảng phụ user_roles
user_credentials
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id Bigint Khóa chính
email Varchar
password Varchar
provider Varchar
provider_id Varchar
user_id Bigint Trường “id” bảng “User”
Lưu trữ bao gồm các thông tin liên quan đến tài khoản người dùng như tên, ngày
khởi tạo… Định dạng sẵn một vài kiểu dữ liệu được mappedBy bởi các bảng khác.
33
2.2.1 User Entity
User
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi User.
userCredentail UserCredential Quan hệ @OneToOne.
createdDate Date Ngày tạo tài khoản.
name String Tên người dùng.
userInfo UserInfo Các thông tin liên hệ người dùng
như: số điện thoại, địa chỉ…
products Set<Product> Quan hệ @OneToMany mappedBy
với “brand” trong Product Entity.
users
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id Bigint Khóa chính
34
avatarUrl Varchar
created_date Date
name Varchar
user_info_id Bigint
2.3 Lưu trữ thông tin liên lạc của người dùng
Lưu trữ các thông tin liên lạc như: địa chỉ, quốc gia, tỉnh thành, số điện thoại…
UserContact
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi User
phone String Số điện thoại
country String Quốc gia
province String Tỉnh (thành phố)
district String Quận, Huyện
detail String Địa chỉ nhà, địa chỉ liên hệ chi tiết
Quan hệ @OneToOne với User Entity
user User
Xác định thông tin liên lạc của User nào
Role
Tên thuộc tính Kiểu dữ liệu Mô tả
id Integer Id duy nhất cho mỗi User
name ERole (enum) Danh sách quyền người dùng gồm:
admin, user
35
Bảng 3-5 Role Entity
roles
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id Int Khóa chính
name Varchar
Bảng phụ được Hibernate tạo khi sử dụng mối quan hệ ràng buộc @ManyToMany
giữa User Entity và Role Entity.
user_roles
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
user_id bigint Khóa chính
role_id int Khóa chính
Lưu trữ danh sách thương hiệu hàng hóa đang kinh doanh.
Brand
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi User
name String Tên thương hiệu
36
products Set<Product> Quan hệ @OneToMany, mappedBy
với thuộc tính “brand” trong bảng
Product.
brands
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id Bigint Khóa chính
name Varchar
Lưu trữ danh sách các loại sản phẩm đang kinh doanh: điện thoại, laptop.
Category
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi User
name String Tên thương hiệu
products Set<Product> Quan hệ @OneToMany, mappedBy
với thuộc tính “category” trong bảng
Product.
37
là phân loại hiện tại.
Bảng 3-9 Category Entity
categories
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id Bigint Khóa chính
name Varchar
Các thông tin được lưu trữ bao gồm: người tạo, phân loại, brand, mô tả…
Product
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi sản phẩm.
user User Quan hệ @ManyToOne với User.
38
quantity int Số lượng sản phẩm hiện có
discount int Giảm giá (%)
details ProductDetails Thông số sản phẩm
images Set<ProductImage> Quan hệ @OneToMany, mappedBy với
thuộc tính “product” trong bảng
ProductImage.
products
Tên thuộc tính Kiểu dữ Khóa, liên kết
liệu
id Bigint Khóa chính
created_date datetime
description String
discount int
name Varchar
price Int
quantity Int
Brand_id Bigint references Brand(id)
Category_id Bigint references Category(id)
39
Product_details_i Bigint references ProductDetail(id)
d
User_id Bigint references User(id)
Lưu trữ các thông tin thống số, cấu hình của thiết bị điện tử mà cửa hàng kinh doanh
như: thông số Pin, màn hình, cổng kết nối…
ProductDetails
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi mục thông số.
product Product Quan hệ @OneToOne mappedBy với “details”
trong Product Entity
40
batteryCapacity String
product_details
Tên thuộc tính Kiểu dữ liệu Khóa, liên kết
id Bigint Khóa chính
cpu Varchar
ram Varchar
hardDrive Varchar
display Varchar
size Varchar
graphicCard Varchar
operatingSystem Varchar
design Varchar
fontCamera Varchar
rearCamera Varchar
chipName Varchar
internalMemory Varchar
sim Varchar
batteryCapacity Varchar
Lưu trữ các thông tin hình ảnh của sản phẩm như: id, loại ảnh…
ProductImage
41
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi ảnh
type EProductImageTypeDisplay Loại ảnh phải được là 1 trong các
(enum) loại: Slider, Official
name String Tên (tiêu đề) của ảnh Danh sách các
sản phẩm có phân loại là phân loại
hiện tại.
product Product Quan hệ @ManyToOne với sản
phẩm
product_images
Tên thuộc Kiểu dữ Khóa, liên kết
tính liệu
id Bigint Khóa chính
name Varchar
type Varchar
product_id Bigint references Product(id)
Lưu trữ các đánh giá của người dùng dành cho sản phẩm. Nội dung đánh giá bao
gồm văn bản bình luận và số sao đánh giá sản phẩm.
42
2.10.1 Review Entity
Reivew
Tên thuộc tính Kiểu dữ liệu Mô tả
id int Id duy nhất cho mỗi ảnh
product Product Quan hệ @ManyToOne với Product
reviews
Tên thuộc Kiểu dữ Khóa, liên kết
tính liệu
id int Khóa chính
comment varchar
rating float
time datetime
product_id bigint references Product(id)
user_id bigint references User(id)
43
2.11 Lưu trữ thông tin giỏ hàng
Lưu trữ thông tin của các sản phẩm có trong giỏ hàng cho từng User. Mỗi sản phẩm
trong giỏ hàng sẽ được lưu thành một hàng trong bảng carts của csdl. Các đơn hàng được
phân biệt dựa trên cột user trong bảng.
Cart
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất
user User Xác
enable Boolean Xác định sản phẩm trong giỏ hàng có
được thêm vào danh sách sẽ thanh
toán hay không.
product Product Quan hệ @OneToOne với Product
carts
Tên thuộc Kiểu dữ Khóa, liên kết
tính liệu
id Bigint Khóa chính
enable bit
quantity int
product_id Bigint references Product(id)
user_id Bigint references User(id)
44
Bảng 3-20 Bảng carts
Lưu trữ các thông tin cơ bản của đơn hàng như: ngày tạo, ngày cập nhật, trạng thái
đơn hàng…
Order
Tên thuộc tính Kiểu dữ liệu Mô tả
id String Id duy nhất, sử dụng uuid
user User Quan hệ @ManyToOne với User.
orders
Tên thuộc tính Kiểu dữ liệu Khóa, liên kết
id varchar Khóa chính
45
created_date datetime
payment_method varchar
settled bit
status varchar
stripe_charge_id varchar
updated_date datetime
user_id bigint references User(id)
2.13 Lưu trữ thông tin các sản phẩm trong đơn hàng
Lưu một vài thông tin sản phẩm cho mỗi mục sản phẩm trong đơn hàng.
Không liên kết trực tiếp với bảng dữ liệu products, để tránh trường hợp thông tin
đơn hàng bị thay đổi khi có thay đổi dữ liệu trên bảng Product.
Đơn hàng sẽ luôn giữ nguyên thông tin sản phẩm ban đầu.
OrderItem
Tên thuộc tính Kiểu dữ liệu Mô tả
id Long Id duy nhất cho mỗi order item
order Order Quan hệ @ManyToOne với Order.
46
2.13.2 Bảng order_items được tạo từ Hibernate OrderItem Entity
orders
Tên thuộc Kiểu dữ liệu Khóa, liên kết
tính
id bigint Khóa chính
product_id bigint
product_name varchar
price int
quantity int
discount int
order_id varchar references Order(id)
2.14 Lưu trữ hình ảnh quảng cáo đầu trang web
Hình ảnh quảng cáo sản phẩm đầu trang web gồm Slider và Banner.
HeaderImage
Tên thuộc tính Kiểu dữ liệu Mô tả
id int Id duy nhất cho mỗi hình ảnh
title String Tiêu đề hình ảnh
fileUploadName String Tên hình ảnh được lưu trong thư mục
Upload
linkTo String Đường dẫn hình ảnh sẽ link đến
type EHeaderIamgeType Loại ảnh. Gồm: Banner, Slider
(enum)
enable Boolean Có hiển thị hình ảnh hay không
createDate Date Thời điểm khởi tạo
modifyDate Date Thời điểm thay đổi, cập nhật
47
Bảng 3-25 HeaderImage Entity
header_iamges
Tên thuộc tính Kiểu dữ Khóa, liên kết
liệu
id int Khóa chính
file_upload_name varchar
link_to varchar
title varchar
type varchar
create_date datetime
modify_date datetimg
48
2.15 ER Diagram quan hệ giữa các bảng trong csdl.
Tạo các Interface kế thừa từ JpaRepository trong Spring Data Jpa để có được một
Repository và có thể sử dụng các tính năng mà Spring Data Jpa cung cấp.
Các interface được đính kèm Anotation @Repository để nói cho ứng dụng Spring
biết đây là một Repository.
Định dạng thêm các hàm hỗ trợ khác ngoài các hàm được Spring Data JPA cung cấp
mặc định.
49
3.1 User Repository
50
3.3 User Contact Repository
51
3.6 ProductCriteria Repository
Đây là repository được thêm vào với mục đích là trả về một Page (là một đối tượng
mà Spring Data Jpa định sẵn, với mục đích chính là đối tượng chứa các thông tin hỗ trợ
phân trang) sản phẩm dựa trên các điều kiện tìm kiếm khác nhau như: dựa theo giá sản
phẩm, cách sắp xếp, tên sản phẩm…
52
3.8 Product Image Repository
53
3.10 Brand Repository
54
3.12 Cart Repository
55
3.14 OrderItem Repository
Spring boot hỗ trợ cấu hình kết nối cơ sở dữ liệu một cách rất đơn giản.
Để Spring có thể kết nối vào Database ta chỉnh cần cấu hình các thông số cần thiết
trong tập tin application.properties.
56
Một số loại cấu hình quan trọng:
spring.datasource.driver-class-name
spring.datasource.url
spring.datasource.username
spring.datasource.password
57
CHƯƠNG 4 Xây dựng RESTful Web Service
Spring Security là một dự án nổi bật trong hệ sinh thái Spring. Spring Security cung
cấp các dịch vụ bảo mật toàn diện cho các ứng dụng doanh nghiệp có nền tảng Java EE.
Authentication (xác thực): là tiến trình thiết lập một principal. Principal có thể
hiểu là một người, hoặc một thiết bị, hoặc một hệ thống nào đó có thể thực hiện
một hành động trong ứng dụng của bạn.
Authorization (phân quyền) hay Access-control: là tiến trình quyết định xem
một principal có được phép thực hiện một hành động trong ứng dụng của bạn hay
không. Trước khi diễn tiến tới Authorization, principal cần phải được thiết lập bởi
Authentication.
Đây là 2 cơ chế khá phổ biến trong các dịch vụ bảo mật, không chỉ riêng Spring
Security.
SecurityContext là interface cốt lõi của Spring Security, lưu trữ tất cả các chi tiết
liên quan đến bảo mật trong ứng dụng. Khi kích hoạt Spring Security trong ứng dụng thì
SecurityContext cũng sẽ được kích hoạt theo.
Không thể truy cập trực tiếp vào SecurityContext, thay vào đó sẽ sử dụng
lớp SecurityContextHolder. Lớp này lưu trữ security context hiện tại của ứng dụng, bao
gồm chi tiết của principal đang tương tác với ứng dụng. Spring Security sẽ dùng một đối
tượng Authentication để biểu diễn thông tin này.
58
- UserDetails, UserDetailsService
UserDetails là một interface cốt lõi của Spring Security. Nó đại diện cho một
principal nhưng theo một cách mở rộng và cụ thể hơn. UserDetails bao gồm các method
sau:
- GrantedAuthority
Một GrantedAuthority là một quyền được ban cho principal. Các quyền đều có tiền
tố là ROLE_, ví dụ như ROLE_ADMIN, ROLE_MEMBER ...
1.1.1.3 WebSecurityConfig
59
1.1.2 JWT
1.1.1.1 Giới thiệu
JWT là một phương tiện đại diện cho các yêu cầu chuyển giao giữa hai bên Client –
Server , các thông tin trong chuỗi JWT được định dạng bằng JSON. Trong đó chuỗi
Token phải có 3 phần là header , phần payload và phần signature được ngăn bằng dấu “.”
Phần header sẽ chứa kiểu dữ liệu , và thuật toán sử dụng để mã hóa ra chuỗi JWT
Phần payload sẽ chứa các thông tin mình muốn đặt trong chuỗi Token như
username, userId…
Phần signature sẽ được tạo ra bằng cách mã hóa phần header , payload kèm theo
một chuỗi secret (khóa bí mật).
TokenProvider: class được khởi tạo với mục đích tạo, xác nhận các JWT token
phục vụ cho việc bảo mật và quản lý quyền hạn User.
appPropetites: liên hệ với file application.properties để lấy các biến môi trường
cho việc tạo Jwt token như:
o app.auth.tokenSecret: phần secret trong signature.
o app.auth.tokenExpirationMsec: thời hạn sử dụng của Token.
createToken: Tạo Jwt gồm các phần thông tin.
o Subject: UserCredential id có được từ Authentication (Authentication là một
Object chứa thông tin liên quan khi một User đăng nhập thành công).
60
o IssuedAt: Thời điểm được tạo
o Expiration: Thời hạn sử dụng của token
o Sign: thuật toán mã hóa, signature secret
getUserIdFromToken: lấy UserCredential id từ JWT để có thể lấy ra các dữ liệu
khác về User từ database.
validateJwtToken: kiểm tra một JWT token có hợp lệ.
Spring Framework cung cấp một API để gửi email, bao gồm một vài interface và
một vài lớp hỗ trợ.
Sử dụng các thymeleaf để xây dựng các template cho việc gửi mail. Spring Mail có
thể sử dụng các template từ thymeleaf để dựng nội dung cho một email.
application.properties: dựa trên Spring Boot cấu hình các thuộc tính khi gửi mail
thông qua Spring Mail như: protocol, host, port, username, password…
61
ThymeleafTemplateConfig: cấu hình thư mục lưu trữ các templates, định dạng
các thuộc tính của các template.
EmailSenderService: một class thuộc Service Layer, với hàm sendMail thực hiện
việc gửi mail dựa trên 2 tham số Mail Object và template name. Trong đó:
o Mail Object gồm các thược tính: from, to, subject, attachments, props…
o templateName: tên của template trong thư mục chứa danh sách các Thymeleaf
* Email sẽ được gửi từ một tài khoản mặc định được cấu hình trước trong file
application.property thông qua tham số spring.mail.username.
62
Hình 4-37 Nhập liệu SignupRequest phía Client
B1: Kiểm tra email đã tồn tại. Nếu tồn tại => Xử lý ngoại lệ.
B2: Tạo một UserCredential mới với các thông tin mặc định.
MessageResponse (message):
63
Hình 4-38 Thông báo đăng ký thành công
* Ở phía Client giao diện sẽ tự động chuyển sang trang đăng nhập.
Trường hợp trùng lặp email đăng ký: Xử lý ngoại lệ trả về một MessageResponse
với message là “Email ‘email đăng ký’ đã được sử dụng”.
Hình 4-39 Thông báo lỗi đăng ký với Email trùng lặp
Sau khi tạo thành công một tài khoản. Server sẽ gửi một Email xác nhận đến email
đã được sử dụng để tạo tài khoản. Sau khi xác nhận người dùng mới có thể sử dụng tài
khoản vừa được tạo.
64
1.3 Xác nhận Email cho tài khoản đã tạo.
Tài khoản được tạo ra (tài khoản Local) phải xác nhận email đăng ký trước khi được
sử dụng để đăng nhập vào trang web. Nếu đăng nhập bằng tài khoản Social thì không cần
xác nhận Email.
Email xác nhận được gửi lần đầu tiên khi người dùng tạo tài khoản hoặc trang web
sẽ gợi ý “gửi lại email xác nhận” khi người dùng đăng nhập với tài khoản chưa được xác
nhận Email.
65
Hình 4-41 Quá trình xử lý gửi lại email xác nhận
Thông báo cho người dùng việc gửi mail đã thành công.
66
Người dùng truy cập vào email sẽ tìm thấy được email xác nhận được gửi với các
thông tin sau.
Hình 4-43 Email với đường dẫn xác nhận được gửi
Khi người dùng nhấn vào đường dẫn sẽ được điều hướng sang một trang phía
Client. Trang phía Client này sẽ tự động gửi yêu cầu xác nhận với Jwt token đến Server
để xử lý.
Hình 4-44 Xử lý xác nhận Email dựa trên Token nhận được
Hiển thị thông báo khi xác nhận email thành công.
67
Hình 4-45 Thông báo khi xác nhận Email thành công
Khi Token hết hạn sẽ hiển thị thông báo cho người dùng biết, kèm theo một nút “gửi
lại email xác nhận” để người dùng có thể gửi lại email xác nhận khác.
Hiển thị thông báo trong trường hợp Token đã hết hạn sử dụng.
Hình 4-46 Thông báo khi Token Verify Email hết hạn
Thông báo khi người dùng tiếp tục gửi token xác nhận Email khi tài khoản đã có
Email được xác nhận
Hình 4-47 Hiển thị thông báo Email đã được xác nhận
68
1.4 Đăng nhập với tài khoản
Sau khi đăng nhập thành công giao diện trang web sẽ chuyển về lại trang chủ
69
Hình 4-49 Đăng nhập thành công
* Trường hợp kết quả xác minh là sai (email hoặc password không đúng) thì Spring
security sẽ xử lý lỗi thông qua authenticationEntryPoint là
RestAuthenticationEntryPoint với thông báo “Email hoặc mật khẩu không chính xác”.
Hình 4-50 Đăng nhập với thông tin tài khoản sai
Spring Framework có một module là Spring OAuth2, dùng để thao tác với các API
của các nền tảng như Facebook, Google để có được các thông tin cần thiết hỗ trợ việc
phát triển ứng dụng.
70
1.5.1 Cấu hình OAuth2 dựa trên Spring boot
Yêu cầu các tham số cấu hình sau trong file application.properties:
spring.security.oauth2.client.registration.{Provider}.client-id
spring.security.oauth2.client.registration.{Provider}.client-secret
spring.security.oauth2.client.registration.{Provider}.redirect-uri
spring.security.oauth2.client.registration.{Provider}.scope
Trong đó, Provider là facebook và google. Các giá trị tham số phải được lấy từ các
ứng dụng/Project của bản thân được tạo trên google, facebook.
71
Hình 4-52 Tạo ứng dụng trên Facebook
Thêm các thuộc tính cấu hình vào class WebSecurityConfig như:
authorizationEndpoint
redirectionEndpoint
userInfoEndpoint
successHandler
failureHandler
HttpCookieOAuth2AuthorizationRequestRepository
Lưu các thông tin của Oauth2 Authorization Request (clientId, redirectUrl, scope…)
tạm thời trên Cookie.
OAuth2UserServiceImpl
72
Authentication cho Spring Security và được gọi tự động sau khi quá trình Authorization
với các Social Provider thực hiện thành công.
Hàm loadUser sẽ được ghi đè lại để thực hiện các công việc sau.
B1: kiểm tra email có được từ OAuth2UserRequest có tồn tại trong Csdl.
B2: Tạo tài khoản mới và lưu thông tin vào Csdl.
B3: Trả về một UserPrincipal dựa trên các thông tin có được.
OAuth2AuthenticationSuccessHandler
73
1.5.3 Tổng quá quá trình Social Login
Sau khi đăng nhập thành công, Server sẽ gửi một Access token về phía Client.
Client sẽ đính kèm access token trong phần Header Authorization mỗi khi thực hiện các
request đến Server.
Xác minh Token trong request từ phía Client để xác định quyền truy cập được thực
hiện ở Server dựa trên các bước:
74
Hình 4-54 Server xử lý Request với token
Sau khi đăng nhập thành công người dùng được phân quyền dựa trên các quyền có
được từ UserDetails thông qua phương thức getAuthorities().
Ngoài cấu hình trong WebSecurityConfig, có thể sử dụng trực tiếp Anotation
@PreAuthorize với quyền cụ thể trên các phương thức thuộc lớp Controller để xác định
quyền yêu cầu sử dụng.
Nếu người dùng chưa đăng nhập nhưng vẫn truy cập vào các trang nội dung yêu cầu
các quyền hạn phù hợp. Trang web sẽ điều hướng người dùng về trang đăng nhập.
Nếu người dùng đã đăng nhập và truy cập vào các trang nội dung yêu cầu quyền hạn
cao hơn quyền hiện tại của tài khoản, trang web điều hướng người dùng về trang chủ.
75
1.8 Thay đổi mật khẩu khi quên mật khẩu
1.8.1 Gửi email xác nhận đổi lại mật khẩu
Khi người dùng quên mật khẩu đăng nhập. Nhấn vào dòng chữ quên mật khẩu ở
Form đăng nhập để tiến hành cập nhật lại mật khẩu.
Hình 4-55 Tính năng lấy lại mật khẩu ở Form đăng nhập
Sau đó thông tin sẽ được gửi đến Server và tiến hành xử lý.
76
Sử dụng Jwt để tăng tính bảo mật cho việc thay đổi mật khẩu
Jwt được tạo có phần payload chứa thông tin “email” người dùng yêu cầu đổi mật
khẩu
Mail được gửi thông qua EmailSenderService.
Hình 4-58 Email xác nhận reset password không tồn tại
Mail xác nhận được gửi với đường dẫn đến trang đổi mật khẩu.
77
1.8.2 Đổi lại mật khẩu
Khi nhân vào “đường dẫn” trong email sẽ dẫn người dùng đến giao diện tiến hành
đổi mật khẩu mới. Đường dẫn sẽ được chứa kèm theo Jwt token được tạo trước đó
Sau khi nhập xong thông tin dữ liệu sẽ được xử lý ở Server thông qua các bước sau
78
Lỗi khi mật khẩu xác nhận không chính xác
Hình 4-62 Thông báo đổi mật khẩu với mật khẩu xác nhận không chính xác
Ngoài ra để tranh việc sử dụng mật token để đổi mật khẩu nhiều lần, các đường dẫn
từ Jwt token sẽ có thời hạn sử dụng nhất định. Nếu sử dụng token hết hạn sẽ xuất hiện
thông báo lỗi.
79
Hình 4-64 Thời gian đổi mật khẩu hết hạn
Hiển thị các thông tin khách hàng và đơn hàng đã đặt (phần đơn hàng sẽ được trình
bày ở các mục sau). Yêu cầu phải đăng nhập (có quyền User ở phía Server) để truy cập
được vào trang này.
Các thông tin của khách hàng có được thông qua Request đến Endpoint user/me ở
phía Server.
80
Hình 4-66 Lấy thông tin người dùng hiện tại
Nhấn vào nút “đổi mật khẩu” ở trang Profile. Một email xác nhận đổi mật khẩu sẽ
gửi đến email của người dùng hiện tại. (các bước xử lý khác tương tự phần nội dung “thay
đổi mật khẩu khi quên mật khẩu” đã được trình bày).
Người dùng nhập thông tin mới và gửi yêu cầu thay đổi thông tin đến Server.
81
Hình 4-68 Form nhập thông tin liên hệ mới
Server thực hiện xác định người dùng hiện tại và tiến hành cập nhật dữ liệu.
Thông báo và hiển thị dữ liệu cập nhật sau khi quá trình cập nhật thành công.
82
Hình 4-70 Thông báo hiển thị thông tin liên lạc sau khi cập nhật
Các hình ảnh của các sản phẩm sẽ được upload và lưu trữ vào một thư mục trong
project thay vì lưu trực tiếp vào Database.
Xây dựng một class thuộc Service Layer là FileStorageServiceImpl chứa các
phương thức hỗ trợ việc upload cũng như xóa bỏ hình ảnh. FileStorageServiceImpl được
implements từ interface FilesStorageService.
83
Các Enpoint hỗ trợ tính năng Upload
Post => /files/upload: upload thủ công một file bất kỳ.
Get => /files: chứa thông tin của tất cả các file đã upload. Tên file trong thư mục
upload và đường dẫn để lấy dữ liệu trực tiếp.
Hình 4-72 Thông tin các file được upload thông qua Endpoint
Get => /files/{filename}: dữ liệu cụ thể của từng file upload. Tìm kiếm dựa trên
filename.
Yêu cầu quyền hạn Admin để thực hiện việc thêm sản phẩm mới cho trang web.
Sau khi đăng nhập với tài khoản Admin, vào mục “Thêm sản phẩm” để chuyển đến
Form thêm sản phẩm.
Nhập thông tin sản phẩm đầy đủ và nhấn nút “Thêm sản phẩm”. Client sẽ tổng hợp
các thông tin và gửi một Request thêm sản phẩm đến Server để thực hiện việc thêm sản
phẩm cho trang web của Shop.
84
Hình 4-73 Form thêm sản phẩm
Khi người dùng nhập thiếu thông tin sản phẩm, thì sẽ hiển thị thông báo lỗi cho
người dùng nhập đầy đủ các thông tin.
85
Hình 4-75 Xử lý thêm hình ảnh phía Server
Trong đó Form Data gửi đến Server được chia thành các phần riêng biệt sau:
Thông tin sản phẩm (các văn bản và số liệu). Khi không có đầy đủ thông tin
cần thiết trả về danh sách lỗi yêu cầu thông tin cho các thuộc tính còn thiếu.
Hình 4-76 Xử lý lỗi thiếu thông tin khi thêm sản phẩm phía Server
Client hiển thị thông báo sau khi thêm sản phẩm thành công.
86
Hình 4-77 Thông báo thêm sản phẩm thành công
Tùy theo giao diện hiển thị và các yêu cầu sản phẩm mà trang web sẽ hiện thị danh
sách sản phẩm cho phù hợp.
Ở trang chủ danh sách sản phẩm sẽ chỉ hiện thị một vài sản phẩm và không có các
bộ lọc hay thanh tìm kiếm sản phẩm.
Hình 4-78 Hiển thị danh sách sản phẩm ở trang chủ
87
Danh sách sản phẩm ở trang sản phẩm theo phân loại sẽ có bộ lọc theo giá, sắp xếp
sản phẩm và thanh tìm kiếm dựa theo tên sản phẩm.
Hình 4-79 Danh sách sản phẩm ở trang sản phẩm theo phân loại
Client gửi yêu cầu đến Server kèm theo các thuộc tính như: phân trang, giá cả, tên,
thương hiệu, phân loại,…
Sau đó Server dựa trên các thuộc tính của yêu cầu để trả về các dữ liệu sản phẩm
phù hợp.
Đây là một Object phục vụ việc phân trang, giới hạn số lượng dữ liệu trả về. Khi
khởi tạo thì yêu cầu các thuộc tính sau:
Object với các thuộc tính được dừ để lọc danh sách sản phẩm theo các tiêu chí khác
nhau:
88
Name: tên sản phẩm
Brand: thương hiệu
Category: phân loại sản phẩm
minPrice: giá nhỏ nhất
maxPrice: giá lớn nhất
2.3.2.3 ProductCriteriaRepository
JPA Criteria API cho phép ta tạo ra các câu truy vấn bằng Java Object thay vì việc
khai báo trực tiếp trong String (JPQL).
Với các lệnh truy vấn phức tạp như lọc sản phẩm theo các tiêu chí sử dụng. Việc sử
dụng Criteria API cho phép chúng ta xây dựng câu lệnh một cách Dynamic, rất linh động,
và không bị hardcode trong một String và có thể tái sử dụng lại được. Đặc biệt, vì là Java
Object, nên chúng ta sẽ biết một câu lệnh bị lỗi, không đúng quy tắc ngay khi biên dịch
chương trình.
Các tiêu chí tìm kiếm được đặt trong request url trước khi chuyển thành
ProductPage Object và ProductSearchCriteria Object.
Hình 4-80 Các tiêu chí tìm kiếm danh sách sản phẩm gửi đến Server thông qua url query
parameters
89
2.3.2.4 Sơ đồ các bước lấy danh sách sản phẩm.
Ở ProductCriteriaRepository ta thực hiện chuyển đổi các Product Object thành các
ProductResponse (dữ liệu truy vấn trả về lúc đầu chỉ là một Product Object) để có thêm
các thông tin liên quan khác của sản phẩm (ví dụ như các bình luận sản phẩm).
Trong đó một Page Product được trả về cho Client dưới dạng JSON bao gồm các dữ
liệu như sau:
Client sẽ sử dụng các dữ liệu trên để hiển thị danh sách sản phẩm cũng như phân
trang cho danh sách sản phẩm.
90
2.3.3 Trang thông tin chi tiết của sản phẩm
2.3.3.1 Giao diện trang chi tiết sản phẩm
Khi người dùng Click vào một sản phẩm trong danh sách sản phẩm. Người dùng sẽ
được điều hướng sang trang chi tiết của sản phẩm đó.
Phía trên giao diện là hình ảnh sản phẩm, slider hình ảnh giới thiệu, giá cả, giảm
giá…
Hình 4-83 Giao diện phía trên trang chi tiết sản phẩm
Phía dưới giao diện là hình ảnh bảng thông số sản phẩm và danh sách các bình luận.
Hình 4-84 Giao diện phía dưới trang chi tiết sản phẩm
91
2.3.3.2 Dữ liệu trang chi tiết sản phẩm
Client sử dụng dữ liệu từ danh sách sản phẩm để xây dựng trang chi tiết sản phẩm.
Hình 4-85 Thông tin của mỗi sản phẩm trong danh sách sản phẩm
Người dùng phải đăng nhập để có thể đánh giá sản phẩm
Một đánh giá sản phẩm bao gồm các thông tin:
92
Hình 4-87 Quá trình đánh giá sản phẩm được thêm
Hình 4-88 Hiển thị thông báo và đánh giá sau khi đánh giá được thêm thành công
Người dùng chỉ có thể có một đánh giá duy nhất cho mỗi sản phẩm.
Yêu cầu quyền Admin để thực hiện việc cập nhật thông tin sản phẩm.
Admin nhấn vào nút “Chỉnh sửa” trên giao diện sản phẩm để chuyển đến Form
chỉnh sửa hình ảnh
93
Hình 4-89 Nút "chỉnh sửa" sử dụng cho việc cập nhật thông tin sản phẩm
Client sẽ lấy các thông tin hiện có của sản phẩm và điền sẵn các thông tin này vào
Form cập nhật sản phẩm. Một số lưu ý khi cập nhật thông tin sản phẩm.
Loại sản phẩm là trường thông tin cố định không thể thay đổi.
Các hình ảnh của sản phẩm sẽ được giữ nguyên nếu không chọn hình ảnh mới
Hình 4-90 Các thông tin hiện tại của sản phẩm trong Form cập nhật sản phẩm
94
Sau khi sửa đổi các thông tin cần thiết nhấn “Sửa thông tin sản phẩm” ở cuối Form
để gửi yêu cầu cập nhật thông tin sản phẩm kèm với các thông tin cập nhật đến phía
Server.
Hình 4-92 Thông báo cập nhật thông tin sản phẩm thành công
Admin nhấn vào nút “Xóa” trên giao diện sản phẩm để xóa sản phẩm.
Một popup sẽ hiển thị để xác nhận lại việc lựa chọn xóa sản phẩm.
95
Hình 4-93 Popup xác nhận xóa sản phẩm
Client gửi yêu cầu xóa sản phẩm đến Server kèm theo Id của sản phẩm sẽ xóa.
Để hiển thị các phần tử giao diện liên quan đến việc quản lý giỏ hàng (nút “thêm vào
giỏ hàng”, trang giỏ hàng) yêu cầu người dùng phải đăng nhập trước đó.
Nhấn “Thêm vào giỏ hàng” ở trang chi tiết sản phẩm để thêm sản phẩm vào giỏ
hàng.
96
Client sẽ gửi yêu cầu thêm sản phẩm vào giỏ hàng kèm theo Id của sản phẩm đến
phía Server. Sản phẩm được thêm vào giỏ hàng với số lượng mặc định là “1”.
Hình 4-96 Thêm sản phẩm vào giỏ hàng thành công
Sản phẩm chỉ có thể thêm vào giỏ hàng một lần
97
Hình 4-97 Thông báo sản phẩm đã thêm vào giỏ hàng
Nhấn vào mục “Giỏ hàng” trên thanh điều hướng để mở trang quản lý giỏ hàng
98
Hình 4-99 Lấy dữ liệu giỏ hàng
Ta có thể cập nhật số lượng sản phẩm và trạng thái (chọn hoặc không chọn mua) sản
phẩm có trong giỏ hàng.
Mỗi khi một mục trong giỏ hàng thay đổi. Client sẽ gửi yêu cầu cập nhật giỏ hàng
đến Server . Yêu cầu được gửi đi kèm với các trường thông tin: mã id của Cart, số lượng
sản phẩm, sản phẩm đang ở trạng thái chọn mua hay không.
Khi cập nhật giỏ hàng chúng ta cũng cập nhật lại số sản phẩm còn lại cho phù hợp,
các yêu cầu cập nhật sẽ được chia thành các dạng sau:
99
Số lượng sản phẩm còn lại = Số lượng sản phẩm hiện tại – số lượng sản phẩm
trong giỏ hàng.
o Thay đổi “chọn mua” sang “không chọn mua”:
Số lượng sản phẩm còn lịa = Số lượng sản phẩm hiện tại + số lượng sản phẩm
trong giỏ hàng.
Chỉ thay đổi số lượng sản phẩm và đang trong trạng thái “Chọn mua”
Số lượng sản phẩm còn lại = Số lượng sản phẩm hiện tại + Số lượng cũ sản
phẩm trong giỏ hàng – Số lượng mới sản phẩm trong giỏ hàng.
Nhấn vào biểu tượng xóa sản phẩm ra khỏi giỏ hàng trên giao diện mỗi sản phẩm
trong giỏ hàng để tiến hành xóa. Client sẽ gửi yêu cầu xóa kèm với một CartId đến
Server.
100
Hình 4-102 Quy trình xóa sản phẩm trong giỏ hàng
Hình 4-103 Thông báo xóa sản phẩm trong giỏ hàng thành công
4 Thanh toán
Nhấn nút “Tiến Hành Thanh Toán” trong trang giỏ hàng để chuyển đến trang thanh
toán.
101
Hình 4-104 Trang thanh toán giỏ hàng
Người dùng phải điền đầy đủ thông tin liên lạc trước khi tiến hành thanh toán.
Người dùng có thể sửa đổi thông tin liên lạc trực tiếp ở trang thanh toán. Việc xử lý cập
nhật thông tin liên lạc tương tự như cập nhật thông tin ở trang Profile.
Có 2 phương thức thanh toán chính là: thanh toán khi nhận hàng và thanh toán qua
Stripe.
Nhấn vào nút thanh toán khi nhận hàng để tạo đơn hàng mới. Client gửi yêu cầu tạo
đơn hàng
102
Hình 4-105 Quá trình xử lý thêm đơn hàng thanh toán COD
Đơn hàng được lặp dựa trên các sản phẩm trong giỏ hàng đang “Chọn mua”.
Giá trị “settled” được lưu của đơn hàng mặc định là False (đơn hàng chưa được
thanh toán).
Sau khi thêm đơn hàng thành công người dùng sẽ được điều hướng về trang Profile
để xem đơn hàng
Stripe là nền tảng phần mềm tốt nhất cho hoạt động kinh doanh trên internet. Stripe
hiện đang thực hiện xử lý hàng tỷ đô la mỗi năm cho các doanh nghiệp trên khắp thế giới.
Stripe cung cấp SDK để có thể tích hợp trên các thiết bị chạy hệ điều
103
hành Android và IOS. Ngoài ra, nó còn cung cấp Stripe API để có thể được sử dụng bởi
rất nhiều các ngôn ngữ như: Ruby, Python, Java, GO... (Stripe API)
Publishable key
Đây là key mà Stripe cung cấp để sử dụng dành cho native khi sử dụng Stripe SDK.
Nó được sử dụng để tạo ra được EphemeralKey dùng cho việc thêm card.
Secret key
Như cái tên của nó, nó là key mà chúng ta cẩn phải giữ kín. Với key này, chúng ta
có thể thực hiện các giao dịch như thanh toán, xoá lịch sử giao dịch, refund...
Stripe Flow
104
4. Server giao tiếp với Stripe qua Stripe's API.
5. Khi giao dịch xong thì Stripe trả về kết quả cho server.
6. Server thông báo cho app kết quả của giao dịch.
4.1.2.3 Tạo một phiên thanh toán dựa trên Stripe API
4.1.2.4 Thêm đơn hàng sau khi thanh toán thành công dựa trên Stripe webhook
Về mặt cơ bản, Webhook là một tính năng cho phép website tự động thông báo và
gửi dữ liệu thời gian thực đến các hệ thống khi có một sự kiện nào đó phát sinh trên
website (ví dụ như khánh hàng đăng ký, điền form, mua hàng, hay gửi email) Webhook sẽ
giúp hệ thống của bạn chủ động hơn trong việc vận hành cũng như trao đổi thông tin.
Sử dụng Stripe webhook được hỗ trợ bởi Stripe để bắt sự kiện người dùng thực hiện
thanh toán thành công.
Sau khi thanh toán được thực hiện thành công phía Server sẽ nhận sự kiện đó từ
Stripe Webhook từ đó biết được người dùng đã thanh toán đơn hàng để thực hiện lưu đơn
hàng vào cơ sở dữ liệu.
106
Hình 4-111 Khởi chạy webhook
Trong đó:
Listen dùng để xác định Endpoint nhận thông tin từ Webhook sẽ là:
https://localhost:8443/payment/stripe/webhooks
--skip-verify: sẽ bỏ qua certificate verification của trang web.
Đoạn mã sau phần “Your webhook signing secret” sẽ được thêm vào Controller
xử lý của Endpoint để kiểm tra Endpoint nhận dữ liệu có thực sự đúng hay không.
Mỗi khi có sự kiện xảy ra Stripe webhook sẽ Post các thông tin đến Enpoint được
xác định.
107
Khi nhận được Event Session thanh toán thành công (checkout.session.completed)
Server sẽ lưu đơn hàng và CSDL
Hình 4-113 Lưu đơn hàng khi nhận được Event Webhook checkout.session.completed
Khi thanh toán qua Stripe thành công, đơn hàng sẽ có dữ liệu cột “settled” là True,
kèm theo một chagre_id của phiên thanh toán.
Người dùng có thể truy cập vào trang Profile để xem lại các đơn hàng đã đặt.
108
Hình 4-114 Danh sách đơn hàng đã đặt ở trang Profile User
Hình 4-115 Lấy dữ liệu các đơn hàng thuộc về một User
109
Hình 4-116 Dữ liệu JSON danh sách đơn hàng của một User
Dữ liệu hiển thị được lấy từ Endpoint /orders/admin với các thuộc tính để lọc đơn
hàng khác nhau. Admin có thể lọc đơn hàng dựa trên các tiêu chí sau: mã đơn hàng, tên
khách hàng, trạng thái.
Quá trinh xử lý lấy dữ liệu đơn hàng khi Admin truy cập vào trang QL đơn hàng.
110
Hình 4-118 Lấy dữ liệu trang QL đơn hàng Admin
111
Hình 4-119 Dữ liệu JSON trang QL đơn hàng Admin
User có thể hủy đơn hàng trước khi đơn nhận đơn hàng
Admin có thể cập nhật trạng thái đơn hàng sao cho phù hợp với tình trạng hiện tại
của đơn hàng. Các trạng thái đơn hàng bao gồm: Open, Confirmed, Shipping, Collected,
Returned, Canceled.
Phía Server sẽ yêu cầu Client gửi thông tin về Id đơn hàng cần cập nhật. Sau đó
Server sẽ xác định đơn hàng và cập nhật trạng thái đơn hàng cho phù hợp. Các endpoint
xử lý phía Server bao gồm:
Các trạng thái đơn hàng có thể thay đổi như sau:
112
Hình 4-120 Thay đổi trạng thái đơn hàng
Ngoài ra khi đơn hàng bị hủy thì dữ liệu đơn hàng vẫn giữ nguyên (không bị xóa
khỏi csdl) và các sản phẩm của Shop sẽ được hoàn lại số lượng sản phẩm có trong đơn
hàng.
Admin có thể vào trang quản lý quảng cáo để thêm, sửa, xóa, cập nhật các slider và
banner quảng cáo đầu trang chủ.
Admin nhập đầy đủ thông tin vào Form thêm ảnh và nhấn “thêm ảnh”. Client sẽ gửi
yêu cầu thêm ảnh quảng cáo kèm theo thông tin của ảnh quảng cáo đến Server để tiến
hành xử lý.
Số lượng Banner quảng cáo tối đa là 4 (để không làm vỡ giao diện). Nếu thêm
Banner quảng cáo khi đã đủ 4 mục, Server sẽ xử lý để trả về lỗi cho Client hiển thị như
sau:
Thông báo khi thêm hình ảnh quảng cáo thành công.
114
6.2 Sửa quảng cáo
Nhấn vào nút cập nhật trên mỗi quảng cáo trong danh sách quảng cáo để cập nhật
thông tin cho hình ảnh quảng cáo.
Dữ liệu mới sẽ được đưa đến Server và cập nhật lại cho quảng cáo cũ. Việc xác định
quảng cáo thông qua Id của các quảng cáo.
Hình ảnh cũ sẽ bị xóa khỏi folder upload khi ta cập nhật lại hình ảnh quảng cáo.
Ta lấy dữ liệu hình ảnh bằng phương thức Get đến Endpoint /header-images.
Ở trang chủ ta chỉ cần các dữ liệu hình ảnh quảng cáo đã enable.
115
Ở trang QL quảng cáo của admin dữ liệu hình ảnh quảng cáo sẽ được lấy tất cả.
Dữ liệu của các quảng cáo được Server trả về dưới dạng JSON gồm các trường dữ
liệu sau:
Hình 4-126 Dữ liệu JSON của danh sách các quảng cáo
116
CHƯƠNG 5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN
1 Kết luận
Spring framework là một framework với nhiều module hỗ trợ nhiều công việc khác
nhau, giúp tối ưu và thực hiện các công việc dễ dàng hơn.
Spring có kích thước nhẹ nên có thể hoạt động một cách trong trơn tru. Spring mặc
dù nhẹ nhưng lại có khả năng hỗ trợ cho các ứng dụng tạo ra hiệu năng cao, sử dụng lại
code dễ dàng và dễ kiểm thử,… Có thể dễ dàng thực hiện việc tối ưu hóa được hầu hết
mọi công việc cũng như tiết kiệm được tối đa thời gian làm việc.
Spring hiện nay giữ vai trò vô cùng quan trọng trong sự phát triển cho các ứng dụng
của Java.
Nhóm đã xây dựng thành công một trang web bán hàng với đầy đủ các tính năng cơ
bản của một trang web bán hàng.
Hiểu được cách xây dựng các restful web service cung cấp dữ liệu một cách trực
quan.
Xây các component được tạo từ thư viện React để tạo nên giao diện trang web phù
hợp, tương tác trực tiếp với dữ liệu trên web service.
Cách làm việc nhóm và phân chia công việc trong quá trình thực hiện đồ án.
Giao diện trang web được xây dựng chưa thực sự đẹp mắt và sinh động.
Một số tính năng còn thiếu như: gợi ý sản phẩm cho từng người dùng, thống kê
doanh thu buôn bán, chatbox với người dùng…
Phân chia quyền người dùng còn chưa thực sự chi tiết (chỉ có User và Admin). Cần
thêm các phân quyền như: người gửi hàng, người quản trị,…
117
2 Hướng phát triển
Xây dựng thêm các tính năng còn thiếu, bổ sung các tính năng mới dựa trên nhiều
nền tảng công nghệ khác như AI, Machine Learning.
Tìm kiếm và xử lý các lỗi còn tồn tại. Tối ưu hóa source code để Server có tốc độ xử
lý tốt hơn.
118
Tài liệu tham khảo
119
Bảng phân công công việc
120