Võ Văn Hải's blog

Chỉ có một điều tuyệt đối đó là mọi thứ đều tương đối…

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:

cautrucchuongtrinh

Kết quả thực thi của ứng dụng của chúng ta có kết xuất như  sau:
Ketqua

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


package vovanhai.wordpress.com;

public class Monhang {

private String ten;
private double gia1donvi;
private int soluong;

@Override
public String toString() {
return ten+“; “+soluong+“; “+gia1donvi;
}

public String getTen() {
return ten;
}

public void setTen(String ten) {
this.ten = ten;
}

public double getGia1donvi() {
return gia1donvi;
}

public void setGia1donvi(double gia1donvi) {
this.gia1donvi = gia1donvi;
}

public int getSoluong() {
return soluong;
}

public void setSoluong(int soluong) {
this.soluong = soluong;
}

public Monhang(String ten, double gia1donvi, int soluong) {
super();
this.ten = ten;
this.gia1donvi = gia1donvi;
this.soluong = soluong;
}

public Monhang() {
super();
}

@Override

public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((ten == null) ? 0 : ten.hashCode());
return result;
}

@Override

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Monhang other = (Monhang) obj;
if (ten == null) {
if (other.ten != null)
return false;
} else if (!ten.equals(other.ten))
return false;
return true;
}
}

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:


package vovanhai.wordpress.com;
import java.util.ArrayList;
public class Giohang {

private ArrayList<Monhang>giohang;

public Giohang(){
giohang=new ArrayList<Monhang>();
}

/**
* Thêm 1 món hàng vào giỏ hàng
* @param mh là món hàng cần thêm
*/

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);

}

}

/**
* Lấy 1 món
* @param i
* @return
*/

public Monhang LayMonHang(int i){

if(i<0||i>giohang.size()1)

return null;

return giohang.get(i);

}
/**
*
* @return
*/

public ArrayList<Monhang> getGiohang(){

return giohang;

}

/**
*
* @param ten
* @return
*/

public boolean XoaMonHang(String ten){

Monhang mh=new Monhang(ten,0d,0);

if(!giohang.contains(mh))

return false;

giohang.remove(mh);

return true;

}

/**
*
* @return
*/

public int soMonHang(){

return giohang.size();

}

/**
*
* @return
*/

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:


package vovanhai.wordpress.com;
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(“<html>”);
out.println(“<head>”);
out.println(“<title>Shopping Cart demo with servlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1 align=\”center\”>CHÀO MỪNG ĐẾN VỚI GIAN HÀNG TRÁI CÂY</h1>”);
out.println(“<form action=\”Xuly\” method=\”post\”>”);
out.println(“<p>Chọn mặt hàng:<select name=\”cbohang\”>”);
out.println(“<option>Xoài tượng</option>” +
“<option>Cóc dầm chua ngọt</option>” +
“<option>Mít tố nữ</option>” +
“<option>Mận ngọt Thái Lan</option>” +
“<option>Me dốt</option>”);
out.println(“</select>Số lượng<input type=\”text\” name=\”tfSoluong\” value=\”1\”>”);
out.println(“</p>”);
out.println(“<input type=\”submit\” value=\”Mua Hàng\”>”);

out.println(“<h2 align=\”center\”>THÔNG TIN GIỎ HÀNG</h2>”);
out.println(“<table width=\”80%\” border=\”1\”><tr>”+
“<td>STT</td><td>Tên Sản phẩm</td><td>Số lượng</td>” +
“<td>Đơn giá</td><td>Thành tiền</td>”+
“</tr>”); vovanhai.wordpress.com.Giohang gh=(vovanhai.wordpress.com.Giohang)(session.getAttribute(“giohang”));

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:


package vovanhai.wordpress.com;

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:


package vovanhai.wordpress.com;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class UTF8Filter implements Filter {
public void destroy() {
}

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&#8221;
xmlns=”http://java.sun.com/xml/ns/javaee&#8221; xmlns:web=”http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#8221;
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#8221;
id=”WebApp_ID” version=”2.5″><servlet>
<servlet-name>EShop</servlet-name>
<servlet-class>vovanhai.wordpress.com.EShop</servlet-class>
</servlet>

<servlet>
<servlet-name>Xuly</servlet-name>
<servlet-class>vovanhai.wordpress.com.Xuly</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>EShop</servlet-name>
<url-pattern>/EShop</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Xuly</servlet-name>
<url-pattern>/Xuly</url-pattern>
</servlet-mapping>

<filter>
<filter-name>utf</filter-name>
<filter-class>vovanhai.wordpress.com.UTF8Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>utf</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

</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
Ketqua

Chúc thành công!

20 Responses to “Sử dụng HttpSession tạo ứng dụng giỏ hàng trong Servlet”

  1. 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.

  2. learnJava said

    Thanks Thầy. Blog rất bổ ích

  3. 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

  4. vovanhai said

    cái này có nói ở đâu đấy rồi trong blog!

  5. 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!

  6. dthien said

    Bài viết này rất hay. Cám ơn Thầy nhiều nhiều.

  7. 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.

  8. Võ Văn Hải said

    Chắc đâu đó còn sai.

  9. 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.

  10. 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!

  11. 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

  12. 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!

  13. 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.

  14. 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

  15. What a data of un-ambiguity and preserveness of precious
    experience concerning unpredicted feelings.

  16. 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.

  17. Tuyenbk said

    Em làm được rồi. Cám ơn thầy

  18. Đô Đô 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🙂

  19. 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.

  20. 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: