Sử dụng HttpSession tạo ứng dụng giỏ hàng trong Servlet
Trong ví dụ này, chúng ta tạo ứng dụng bằng cách viết tất cả dưới dạng servlet. Cấu trúc của ứng dụng chúng ta như sau:
Kết quả thực thi của ứng dụng của chúng ta có kết xuất như sau:
Bây giờ chúng ta lần lượt các bước tạo ứng dụng:
1> Trong Eclipse J2EE bạn tạo 1 project dạng Dyamic Web Project. Đặt tên cho nó là Servlet_ShoppingCart. Chọn Target Runtime là Apache Tomcat.
2> Tạo đối tượng đặc tả 1 món hàng trong giỏ hàng. Ở đâ, mỗi món hàng đơn giản gồm các thuộc tính: Tên 1 món hàng, giá 1 đơn vị và số lượng của món hàng đó trong giỏ.
Sau đây là code đặc tả cho đối tượng này
public class Monhang { private String ten; @Override public String getTen() { public void setTen(String ten) { public double getGia1donvi() { public void setGia1donvi(double gia1donvi) { public int getSoluong() { public void setSoluong(int soluong) { public Monhang(String ten, double gia1donvi, int soluong) { public Monhang() { @Override public int hashCode() { @Override public boolean equals(Object obj) { |
3> Tạo đối tượng là 1 giỏ hàng. Ở đây ta dùng 1 tập hợp là ArrayList để chứa danh sách các món hàng. Lớp này gồm 1 số phương thức căn bản như thêm món hàng vào giỏ, bỏ hàng khỏi giỏ,…
Code chi tiết như sau:
import java.util.ArrayList;public class Giohang { private ArrayList<Monhang>giohang; public Giohang(){ /** public void ThemMonhang(Monhang mh){ if(giohang.contains(mh)){ Monhang mhang=giohang.get(giohang.indexOf(mh)); mhang.setSoluong(mhang.getSoluong()+mh.getSoluong()); } else{ giohang.add(mh); } } /** public Monhang LayMonHang(int i){ if(i<0||i>giohang.size()–1) return null; return giohang.get(i); } public ArrayList<Monhang> getGiohang(){ return giohang; } /** public boolean XoaMonHang(String ten){ Monhang mh=new Monhang(ten,0d,0); if(!giohang.contains(mh)) return false; giohang.remove(mh); return true; } /** public int soMonHang(){ return giohang.size(); } /** public double tongtien(){ double t=0d; for(Monhang mh:giohang) t+=mh.getGia1donvi()*mh.getSoluong(); return t; } } |
4> Ta tạo trang cho khách hàng lựa chọn hàng và số lượng mua.
Đầu tiên ta dùng biến HttpSession để đọc 1 biến session có tên “giohang”. Nếu lần đầu ghé thăm thì biến session này sẽ rỗng, còn không thì chúng ta sẽ đọc các mẫu tin trong giỏ hàng và xuất nó ra trên table.
Code cho lớp này như sau:
import java.io.IOException;import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;public class EShop extends HttpServlet { private Giohang gh=null; public EShop() { super(); gh=new Giohang(); } public void init(ServletConfig config) throws ServletException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(“text/html;charset=UTF-8”); PrintWriter out = response.getWriter(); double tongtien=0d; try { HttpSession session = request.getSession(true); out.println(“<h2 align=\”center\”>THÔNG TIN GIỎ HÀNG</h2>”); if(gh!=null){ tongtien=gh.tongtien(); for(int i=0;i<=gh.soMonHang()–1;i++){ vovanhai.wordpress.com.Monhang mh=gh.LayMonHang(i); out.println(“<tr><td>”+i+“</td><td>”+mh.getTen()+“</td><td>”+ mh.getSoluong()+“</td><td>”+mh.getGia1donvi()+“</td>”+ “<td>”+mh.getSoluong()*mh.getGia1donvi()+“</td>”+ “</tr>”); } out.println(“”); out.println(“”); } out.println(“</table>”); out.println(“<h2>Tổng tiề:”+tongtien+” đồng</h2>”); out.println(“”); out.println(“</form>”); out.println(“</body>”); out.println(“</html>”); } finally { out.println(“</html>”); out.close(); } } } |
5> Khi người dùng nhấn nút mua hàng ta sẽ gọi đến 1 servlet có tên là Xuly để thao tác với giỏ hàng. Sau khi xử lý xong servlet này sẽ chuyển trang lại cho trong EShop ở bước 4.
Code cho lớp này như sau:
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class Xuly extends HttpServlet { /** * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods. * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(“text/html;charset=UTF-8”); PrintWriter out = response.getWriter(); try { HttpSession session = request.getSession(true); vovanhai.wordpress.com.Giohang gh=(vovanhai.wordpress.com.Giohang)(session.getAttribute(“giohang”)); if(gh==null) gh=new Giohang(); String hang=request.getParameter(“cbohang”); String sl=request.getParameter(“tfSoluong”); int soluong=Integer.parseInt(sl); if(soluong>0){ double gia=Tinhgia(hang); Monhang mh=new Monhang(hang,gia,soluong); gh.ThemMonhang(mh); session.setAttribute(“giohang”, gh); //System.out.println(mh); } RequestDispatcher rd=request.getRequestDispatcher(“EShop”); rd.forward(request, response); } finally { out.close(); } } private double Tinhgia(String sp){ if(sp.startsWith(“Xoà i”))return 10000; if(sp.startsWith(“Cóc”))return 7000; if(sp.startsWith(“MÃt”))return 16500; if(sp.startsWith(“Máºn”))return 8000; return 4000;//me } /** * Handles the HTTP <code>GET</code> method. * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } /** * Handles the HTTP <code>POST</code> method. * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } } |
6> Nếu đến đây chúng ta thự thi ứng dụng thì việc hiển thị tiếng Việt sẽ có lỗi xảy ra. Để giải quyết vần đề này ta dùng 1 Filter để qui định charset là UTF-8.
Code cho filter này như sau:
import java.io.IOException; public class UTF8Filter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(“UTF-8”); chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { } |
7> Cấu hình web.xml
<?xml version=”1.0″ encoding=”UTF-8″?> <web-app xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:web=”http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd” xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd” id=”WebApp_ID” version=”2.5″><servlet> <servlet-name>EShop</servlet-name> <servlet-class>vovanhai.wordpress.com.EShop</servlet-class> </servlet> <servlet> <servlet-mapping> <filter> </web-app> |
Thực thi ứng dụng bằng cách chạy Servlet EShop trong eclipse hoặc sau khi triển khai ứng dụng ta vào url: http://localhost:8080/Servlet_ShoppingCart/EShop
Kết quả sau vài thao tác mua hàng như sau
Chúc thành công!
dangkyweb said
Hay quá.Thật sự cảm ơn bác Hải đã có những bài hướng dẫn bổ ích ho anh em.
learnJava said
Thanks Thầy. Blog rất bổ ích
kdung said
anh oi e ko hiue ham hashcode(),toString() va equals(),co phai 3 ham nay luon di cung voi nhua ko.cach su dung va much dich cua chung la gi vay a.
final int prime = 31minh co the khoi tao bang bat ki gia tri nao dc ko anh.
a co the noi cho e hieu hon ve code trong ham hashcode()dc ko a.cam on a nhieu:D
vovanhai said
cái này có nói ở đâu đấy rồi trong blog!
dinhnguyen said
Em chào Thầy!Em cũng đã xây dựng thành công giỏ hàng này trên JSP nhưng em còn vướng một số điểm mà vẫn chưa có cách khắc phục hợp lí.
Em dùng một textfield để cho người sử dụng thay đổi số lượng hàng mua. Khi thay đổi số lượng thì ta phải cập nhật lại số lượng tổng số tiền mua hàng. Vậy thì làm sao để cập nhật được thông tin này?
Nếu dùng Session thì ta phải dùng một Submit để load lại hoàn toàn giỏ hàng cách này thì quá dễ dàng nhưng phải load lại toàn bộ giỏ hàng. Có cách nào (không dùng Ajax)mà có thể cập nhật giỏ hàng này không Thầy! Em xin cảm ơn Thầy!
dthien said
Bài viết này rất hay. Cám ơn Thầy nhiều nhiều.
Lam said
sao em làm đúng như hướng dẫn mà kết quả sau khi nhấp chọn nút mua hàng nó ra trang trắng tinh.
Võ Văn Hải said
Chắc đâu đó còn sai.
VoDanh said
Xin chao anh Hai,
Truoc tien, Xin cam on anh nhieu vi da cat cong tao blog huu ich de anh em lap trinh cung nhu nhung sinh vien dang theo hoc nghe lap trinh.
Sau, Toi xin nho*` anh tu van them mot so van de sau:
1: Toi da doc nhung bai vi du cua anh ve cac gio hang ma anh lam vi du, dai da so, anh chuyen dung session de luu tru tam thoi nhung thong tin ma nguoi su dung da chon. Nhu vay, trong thuc te, minh co nen lam nhu the hay khong? Toi khong biet neu nhu trien khai thuc te thi khong biet server co ton qua nhieu tai nguyen qua hay khong.
2: Neu nhu trien khai thuc te, Minh co the co giai phap nao khac de luu nhung thong tin san pham ma nguoi dung da chon truoc khi khach hang tao order chinh thuc cho minh.
3: Anh da vi du rat nhieu mo hinh de co the trien khai cac loai gio hang. Toi thi thich nhat la mo hinh MVC voi bai vi du cua anh. Tuy nhien, neu nhu co nguoi dat hang anh lam mot he thong website de co the quan ly them cac thong tin khach nhu don hang, khach hang… Anh se chon mo hinh nao de trien khai doi voi nhung du an lon hon.
Ghi chu:
Toi chuyen ve phan tich thiet ke DB.
Hien nay, toi phai chon mot mo hinh de anh em chung toi trien khai nghien cuu va thuc hien thuc te. Trong qua trinh tham khao cac mo hinh ung dung web application (Framework for java web application) toi dang doc blog cua anh rat ky~.
Da lau lam roi, toi moi tim duoc mot site co nhieu thong tin huu ich nhu the. Khong biet co phai tai anh la mot giao vien hay khong ma toi doc nhung comment cua cac thanh vien cung rat nhe nhang va gop y lan nhau, cung nhau ho tro hoan thanh bai viet ngay cang hoan thien hon.
Con dai da so cac forum khac thi anh em lap trinh dung qua nhieu tu khong hay. Toi mong rang se co nhieu site nhu the nay nua va phong cach comment cua nhung nguoi khac cung tot hon.
Ve ca nhan toi, toi nghi minh can phai comment mot cach nghiem tuc va dung tu ngu de hieu, Dung dung nhung tu ngu khong hay mot cach vo toi va chi vi mot vai thanh kien voi ca nhan khac ma lam anh huong den nguoi chu cua blog.
—
Cuoi cung, xin chuc anh Hai doi dao suc khoe de co the thuc hien them nhieu bai viet hay nhu the nay nua.
Mong hoi am cua anh.
—
P/s Cac thanh vien khac:
Toi chi la nguoi hay nghien cuu va doc sach tren Internet, va` Toi man phep neu y kien cua minh o day, neu co gi mao pham hay bat dong suy nghi voi cac thanh vien khac thi` cung mong moi nguoi bo qua, Dung gian toi.
Võ Văn Hải said
Trước hết tôi xin Cám ơn những lời động viên của anh! Người viết chỉ mong đem lại chút gì đó cho ai cần nó. Thế thôi!
Còn các câu hỏi của anh, tôi xin trả lời như sau:
1. Về việc có nhiều session trong 1 web app thì tôi chưa thấy ai phàn nàn về việc chiếm quá nhiều tài nguyên. Tuy nhiên nếu bạn không thích dùng session trong 1 số trường hợp thì anh có thể đối tượng request và anh forward trong cùng context. Ví dụ như sau:
Anh đang ở servlet1(hoặc 1.jsp) và anh lưu object của anh trong request, anh muốn chuyển sang servlet2(hoặc 2.jsp) mà vẫn muốn truy xuất object đã lưu trong request thì anh có thể dùng:
ServletContext ctx=this.getServletContext();
RequestDispatcher dp=ctx.getRequestDispatcher("/servlet2");
dp.forward(request,response);
Như vậy ta có thể chuyển trang, sử dụng object trong request scope mà không cần phải qua session.
2. Anh có thể lưu trữ ở dạng serialize object, database,… nhưng đều không thể hiệu quả bằng session.
3. Tôi sẽ chọn MVC qua framework JSF(RichFaces/…) để viết.
Chúc anh luôn thành công!
a0811h02 said
that cam on anh hai anh la nguoi nhiet huyet voi moi nguoi em la nguoi moi vao nghe hoc hoi rat nhieu tu nhung thong tin anh dua ra rat mong anh ngay cang dua nhieu bai viet nhu vay giup chung em cam on anh rat nhieu
hoàng said
Cảm ơn thầy. Bọn em cũng đang được giao làm bài tập này mà lại bí.
Một lần nữa, xin cảm ơn!
Nguyễn Anh Tuấn said
Thưa thầy, e có 1 câu hỏi như sau muốn hỏi thầy.
Giả sử e có nhiều danh sách Nhóm hàng, với mỗi nhóm hàng lại có nhiều danh sách mặt hàng tương ứng.
E select trong database lên và ánh xạ chúng thành các đối tượng để thực hiện các thao tác.
Câu hỏi ở đây là:
– Làm thế nào để chỉ phải build các danh sách kia 1 lần rồi cứ 5′ lại tự động do Reload lại danh sách này để làm mới.
– Làm thế nào để tất cả các request đều sử dụng chung dữ liệu đã build trước đó mà ko phải build lại mỗi khi truy cập.
Mong nhận được sự giải đáp của thầy. E cảm ơn.
Lê Huỳnh Anh Tiến said
Cám ơn thầy vì bài viết.
em đang gặp 1 vấn đề sau khi làm bai trên. Chỉ có lần đầu chạy add được món hàng thứ 1 vào giỏ hàng . add món hàng thứ 2 thì thanh địa chỉ : http://localhost:8084/ShoppingCartSession/ATC (ATC là servlet Xuly) . Và ko add thêm dòng 2 được .
Mong thầy giúp em !
Thanks
tin tuc bat dong san said
What a data of un-ambiguity and preserveness of precious
experience concerning unpredicted feelings.
Xuân Hiếu said
Em chao thay. Em xin hoi.
O bai gio hang o tren neu nhu lam viec voi CSDL gom nhieu bang o trong MySQL. Ten san pham se luu o mot bang khac, bay gio muon lay ten san pham thi se su dung ID cua san pham ay nhung tren the select no van hien thi ten cua san pham, va khi nhan nut mua hang thi id cua san pham ay se duoc luu vao bang mua hang chu khong phai la ten cua san pham.
Tuyenbk said
Em làm được rồi. Cám ơn thầy
Hoàng Minh Phúc said
thầy ơi, sao em tạo project như thầy rồi nhưng không chạy được, báo lỗi The requested resource is not available.
Em đã đặt source code trong thư muc webapps của apache-tomcat rồi nhưng không hiểu sao lại bị lỗi này
Mong thầy giúp ạ!
Đô Đô said
e thưa thầy…cho e hỏi được không ạ….bây giờ em muốn hiện thị người dùng trong trang index.jsp sau khi login…thầy có thể giúp e dc k ạ…thanks thầy 🙂
Võ Văn Hải said
thì em gắn giá trị tên người đã logon vào parameter hoặc session rồi lấy ra.
Thái Đức Phương said
sao minh làm giống hướng dẫn mà chạy trang xử lí nó báo lỗi 404 mong thầy trợ giúp