閱讀214 返回首頁    go 小米 go 小米6


《Servlet、JSP和Spring MVC初學指南》——2.4 HttpSession對象

本節書摘來自異步社區《Servlet、JSP和Spring MVC初學指南》一書中的第2章,第2.4節,作者:【加】Budi Kurniawan(克尼亞萬) , 【美】Paul Deck著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.4 HttpSession對象

在所有的會話跟蹤技術中,HttpSession 對象是最強大和最通用的。一個用戶可以有且最多有一個HttpSession,並且不會被其他用戶訪問到。

HttpSession對象在用戶第一次訪問網站的時候自動被創建,你可以通過調用HttpServletRequest的getSession方法獲取該對象。getSession有兩個重載方法:

HttpSession getSession()

HttpSession getSession(boolean create)

沒有參數的getSession方法會返回當前的HttpSession,若當前沒有,則創建一個返回。getSession(false)返回當前HttpSession,如當前存在,則返回null。getSession(true)返回當前HttpSession,若當前沒有,則創建一個getSession(true)同getSession()一致。

可以通過HttpSession的setAttribute方法將值放入HttpSession,該方法簽字如下:

void setAttribute(java.lang.String name, java.lang.Object value)
請注意,不同於URL重新、隱藏域或cookie,放入到HttpSession 的值,是存儲在內存中的,因此,不要往HttpSession放入太多對象或大對象。盡管現代的Servlet容器在內存不夠用的時候會將保存在HttpSessions的對象轉儲到二級存儲上,但這樣有性能問題,因此小心存儲。

此外,放到HttpSession的值不限於String類型,可以是任意實現java.io.Serializable的java對象,因為Servlet容器認為必要時會將這些對象放入文件或數據庫中,尤其在內存不夠用的時候,當然你也可以將不支持序列化的對象放入HttpSession,隻是這樣,當Servlet容器視圖序列化的時候會失敗並報錯。

調用setAttribute方法時,若傳入的name參數此前已經使用過,則會用新值覆蓋舊值。
通過調用HttpSession的getAttribute方法可以取回之前放入的對象,該方法的簽名如下:

java.lang.Object getAttribute(java.lang.String name)
HttpSession 還有一個非常有用的方法,名為getAttributeNames,該方法會返回一個Enumeration 對象來迭代訪問保存在HttpSession中的所有值:

java.util.Enumeration<java.lang.String> getAttributeNames()
注意,所有保存在HttpSession的數據不會被發送到客戶端,不同於其他會話管理技術,Servlet容器為每個HttpSession 生成唯一的標識,並將該標識發送給瀏覽器,或創建一個名為JSESSIONID的cookie,或者在URL後附加一個名為jsessionid 的參數。在後續的請求中,瀏覽器會將標識提交給服務端,這樣服務器就可以識別該請求是由哪個用戶發起的。Servlet容器會自動選擇一種方式傳遞會話標識,無須開發人員介入。

可以通過調用 HttpSession的getId方法來讀取該標識:

java.lang.String getId()
此外,HttpSession.還定義了一個名為invalidate 的方法。該方法強製會話過期,並清空其保存的對象。默認情況下,HttpSession 會在用戶不活動一段時間後自動過期,該時間可以通過部署描述符的 session-timeout 元素配置,若設置為30,則會話對象會在用戶最後一次訪問30分鍾後過期,如果部署描述符沒有配置,則該值取決於Servlet容器的設定。

大部分情況下,你應該主動銷毀無用的HttpSession,以便釋放相應的內存。

可以通過調用HttpSession 的getMaxInactiveInterval 方法來查看會話多久會過期。該方法返回一個數字類型,單位為秒。調用setMaxInactiveInterval 方法來單獨對某個HttpSession 設定其超時時間:

void setMaxInactiveInterval(int seconds)
若設置為0,則該HttpSession 永不過期。通常這不是一個好的設計,因此該 HttpSession 所占用的堆內存將永不釋放,直到應用重加載或Servlet容器關閉。

清單2.9 ShoppingCartServlet 為一個小的有4個商品的在線商城,用戶可以將商品添加到購物車中,並可以查看購物車內容,所用到的Product類可見清單2.7,ShoppingItem 類可見清單2.8,Product類定義了4個屬性(id、name、description和price),ShoppingItem 有兩個屬性,即quantity和Product。
清單2.7 Product類

package app02a.httpsession;
public class Product {
    private int id;
    private String name;
    private String description;
    private float price;

    public Product(int id, String name, String description, float price)
       {
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
    }

    // get and set methods not shown to save space
}

清單2.8 ShoppingItem類

package app02a.httpsession;
public class ShoppingItem {
    private Product product;
    private int quantity;

    public ShoppingItem(Product product, int quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    // get and set methods not shown to save space
}

清單2.9 ShoppingCartServlet類

package app02a.httpsession;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet(name = "ShoppingCartServlet", urlPatterns = {
        "/products", "/viewProductDetails",
        "/addToCart", "/viewCart" })
public class ShoppingCartServlet extends HttpServlet {
    private static final long serialVersionUID = -20L;
    private static final String CART_ATTRIBUTE = "cart";

    private List<Product> products = new ArrayList<Product>();
    private NumberFormat currencyFormat = NumberFormat
            .getCurrencyInstance(Locale.US);

    @Override
    public void init() throws ServletException {
        products.add(new Product(1, "Bravo 32' HDTV",
                "Low-cost HDTV from renowned TV manufacturer",
                159.95F));
        products.add(new Product(2, "Bravo BluRay Player",
                "High quality stylish BluRay player", 99.95F));
        products.add(new Product(3, "Bravo Stereo System",
                "5 speaker hifi system with iPod player",
                129.95F));
        products.add(new Product(4, "Bravo iPod player",
                "An iPod plug-in that can play multiple formats",
                39.95F));
    }

    @Override
    public void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            IOException {
        String uri = request.getRequestURI();
        if (uri.endsWith("/products")) {
            sendProductList(response);
        } else if (uri.endsWith("/viewProductDetails")) {
            sendProductDetails(request, response);
        } else if (uri.endsWith("viewCart")) {
            showCart(request, response);
        }
    }

    @Override
    public void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            IOException {
        // add to cart
        int productId = 0;
        int quantity = 0;
        try {
            productId = Integer.parseInt(
                    request.getParameter("id"));
            quantity = Integer.parseInt(request
                    .getParameter("quantity"));
        } catch (NumberFormatException e) {
        }

        Product product = getProduct(productId);
        if (product != null && quantity >= 0) {

            ShoppingItem shoppingItem = new ShoppingItem(product,
                    quantity);
            HttpSession session = request.getSession();
            List<ShoppingItem> cart = (List<ShoppingItem>) session
                    .getAttribute(CART_ATTRIBUTE);
            if (cart == null) {
                cart = new ArrayList<ShoppingItem>();
                session.setAttribute(CART_ATTRIBUTE, cart);
            }
            cart.add(shoppingItem);
        }
        sendProductList(response);
    }

    private void sendProductList(HttpServletResponse response)
            throws IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.println("<html><head><title>Products</title>" +
                    "</head><body><h2>Products</h2>");
        writer.println("<ul>");
        for (Product product : products) {
            writer.println("<li>" + product.getName() + "("
                    + currencyFormat.format(product.getPrice())
                    + ") (" + "<a href='viewProductDetails?'>Details</a>)");
        }
        writer.println("</ul>");
        writer.println("<a href='viewCart'>View Cart</a>");
        writer.println("</body></html>");
    }

    private Product getProduct(int productId) {
        for (Product product : products) {
            if (product.getId() == productId) {
                return product;
            }
        }
        return null;
    }

    private void sendProductDetails(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        int productId = 0;
        try {
            productId = Integer.parseInt(
                    request.getParameter("id"));
        } catch (NumberFormatException e) {
        }
        Product product = getProduct(productId);
        if (product != null) {
            writer.println("<html><head>"
                    + "<title>Product Details</title></head>"
                    + "<body><h2>Product Details</h2>"
                    + "<form method='post' action='addToCart'>");
            writer.println("<input type='hidden' name='id' "
                    + "value='" + productId + "'/>");
            writer.println("<table>");
            writer.println("<tr><td>Name:</td><td>"
                    + product.getName() + "</td></tr>");
            writer.println("<tr><td>Description:</td><td>"
                    + product.getDescription() + "</td></tr>");
            writer.println("<tr>" + "<tr>"
                    + "<td><input name='quantity'/></td>"
                    + "<td><input type='submit' value='Buy'/>"
                    + "</td>"
                    + "</tr>");
            writer.println("<tr><td colspan='2'>"
                    + "<a href='products'>Product List</a>"
                    + "</td></tr>");
            writer.println("</table>");
            writer.println("</form></body>");
        } else {
            writer.println("No product found");
        }

    }

    private void showCart(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.println("<html><head><title>Shopping Cart</title>"
                    + "</head>");
        writer.println("<body><a href='products'>" +
                    "Product List</a>");
        HttpSession session = request.getSession();
        List<ShoppingItem> cart = (List<ShoppingItem>) session
                .getAttribute(CART_ATTRIBUTE);
        if (cart != null) {
            writer.println("<table>");
            writer.println("<tr><td style='width:150px'>Quantity"
                    + "</td>"
                    + "<td style='width:150px'>Product</td>"
                    + "<td style='width:150px'>Price</td>"
                    + "<td>Amount</td></tr>");
            double total = 0.0;
            for (ShoppingItem shoppingItem : cart) {
                Product product = shoppingItem.getProduct();
                int quantity = shoppingItem.getQuantity();
                if (quantity != 0) {
                    float price = product.getPrice();
                    writer.println("<tr>");
                    writer.println("<td>" + quantity + "</td>");
                    writer.println("<td>" + product.getName()
                            + "</td>");
                    writer.println("<td>"
                            + currencyFormat.format(price)
                            + "</td>");
                    double subtotal = price * quantity;

                    writer.println("<td>"
                            + currencyFormat.format(subtotal)
                            + "</td>");
                    total += subtotal;
                    writer.println("</tr>");
                }
            }
            writer.println("<tr><td colspan='4' "
                    + "style='text-align:right'>"
                    + "Total:"
                    + currencyFormat.format(total)
                    + "</td></tr>");
            writer.println("</table>");
        }
        writer.println("</table></body></html>");

    }
}

ShoppingCartServlet 映射有如下URL:

/products:顯示所有商品。
/viewProductDetails:展示一個商品的細節。
/addToCart:將一個商品添加到購物車中。
/viewCart:展示購物車的內容。
除/addToCart外,其他URL都會調用doGet方法。doGet 首先根據所請求的URL來生成相應內容:

String uri = request.getRequestURI();
        if (uri.endsWith("/products")) {
            sendProductList(response);
        } else if (uri.endsWith("/viewProductDetails")) {
            sendProductDetails(request, response);
        } else if (uri.endsWith("viewCart")) {
            showCart(request, response);
        }

如下URL訪問應用的主界麵:

https://localhost:8080/app02a/products
該URL會展示商品列表,如圖2.9所示。
screenshot
單擊Details(詳細)鏈接,Servlet會顯示所選產品的詳細信息,如圖2.10所示。請注意頁麵上的輸入框和Buy按鈕,輸入一個數字並單擊Buy按鈕,就可以添加該產品到購物車中。
screenshot
提交購物表單,Web容器會調用ShoppingCartServlet的doPost方法,該方法將一個商品添加到該用戶的HttpSession。

doPost方法首先構造一個ShoppingItem實例,傳入用戶所編輯的商品和數量:

        ShoppingItem shoppingItem = new ShoppingItem(product,
                quantity);

然後獲取當前用戶的HttpSession,並檢查是否已經有一個名為“cart”的List對象:

        HttpSession session = request.getSession();
        List<ShoppingItem> cart = (List<ShoppingItem>) session
                .getAttribute(CART_ATTRIBUTE);

若不存在,則創建一個並添加到HttpSession中:

if (cart == null) {
                cart = new ArrayList<ShoppingItem>();
                session.setAttribute(CART_ATTRIBUTE, cart);
            }

最後,將所創建的ShoppingItem添加到該list中:

        cart.add(shoppingItem);

當用戶單擊View Cart(查看購物車)鏈接時,Web容器調用showCart方法,獲取當前用戶的HttpSession並調用其getAttribute方法來獲取購物商品列表:

    HttpSession session = request.getSession();
    List<ShoppingItem> cart = (List<ShoppingItem>) session
            .getAttribute(CART_ATTRIBUTE);

然後迭代訪問List對象,並將購物項發送給瀏覽器:

    if (cart != null) {
        for (ShoppingItem shoppingItem : cart) {
            Product product = shoppingItem.getProduct();
            int quantity = shoppingItem.getQuantity();
        …

最後更新:2017-05-27 18:31:10

  上一篇:go  《Servlet、JSP和Spring MVC初學指南》——2.5 小結
  下一篇:go  《Servlet、JSP和Spring MVC初學指南》——2.3 Cookies