Java Servlet学习笔记——6.HttpSession

写在前面

这部分学习HttpSession,这个我之前也有用过,但还是没有成体系特别了解,所以这里借机会整理一下书中所学。

声明:主要内容来源《Servlet、JSP和Spring MVC初学指南》,我只是整理一下知识内容方便自己查看,顺便做一下分享。

在所有的会话跟踪技术中, HttpSession 对象是最强大和最通用的。 一个用户可以有且最多有一个HttpSession, 并且不会被其他用户访问到。

getSession()

HttpSession对象在用户第一次访问网站的时候自动被创建, 你可以通过调用HttpServletRequest的getSession方法获取该对象。 getSession有两个重载方法:

HttpSession getSession()
HttpSession getSession(boolean create)
  • 没有参数的getSession方法会返回当前的HttpSession, 若当前没有, 则创建一个返回。
  • getSession(false)返回当前HttpSession, 如当前存在, 则返回null
  • getSession(true)返回当前HttpSession, 若当前没有, 则创建一个getSession(true)同getSession()一致。

setAttribute()与getAttribute()

可以通过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的过期设置

HttpSession.还定义了一个名为invalidate 的方法。 该方法强制会话过期, 并清空其保存的对象。 默认情况下, HttpSession 会在用户不活动一段时间后自动过期, 该时间可以通过部署描述符的 session-timeout元素配置, 若设置为30, 则会话对象会在用户最后一次访问30分钟后过期, 如果部署描述符没有配置, 则该值取决于Servlet容器的设定。

大部分情况下, 你应该主动销毁无用的HttpSession, 以便释放相应的内存。

HttpSession 的getMaxInactiveInterval方法可以查看会话多久会过期。 该方法返回一个数字类型, 单位为秒。 调用setMaxInactiveInterval 方法来单独对某个HttpSession 设定其超时时间:

void setMaxInactiveInterval(int seconds)

若设置为0, 则该HttpSession 永不过期。 通常这不是一个好的设计, 因此该 HttpSession 所占用的堆内存将永不释放, 直到应用重加载或Servlet容器关闭。

实例代码

构造一个小的有4个商品的在线商城, 用户可以将商品添加到购物车中, 并可以查看购物车内容。

  • Product类:作为商品的对象,储存商品的Id、名称、描述与价格信息。
  • ShoppingItem类:作为购物车的对象,储存Product类(商品)与数量信息。
  • ShoppingCattServlet类:在线商城的Servlet类,用来响应各种操作,向浏览器发送页面。

Product类

package app02a.Product;

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id=id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name=name;
    }

    public String getDescription() {
        return name;
    }
    public void setDescription(String description) {
        this.description=description;
    }

    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price=price;
    }
}

ShoppingItem类

package app02a.Product;

public class ShoppingItem {

    private Product product;
    private int quantity;

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

    public Product getProduct(){
        return product;
    }
    public void setProduct(Product product) {
        this.product=product;
    }

    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity=quantity;
    }
}

ShoppingCartServlet类

package app02a.Product;

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?id="
                    + product.getId() + "'>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都会调用这个Servlet:”/products”, “/viewProductDetails”,”/addToCart”, “/viewCart”。

1.初始化函数init():主要向类级变量private List< Product > products 添加四个初始化商品。初始化商品信息由Id、名称、描述与价格组成。

2.doGet()函数:主要用来相应浏览器向Servlet发出的URL请求,不同的URL将在doGet()函数中调用不同的函数来实现不同的功能。

3.doPost()函数:购物车购买页面响应,会获取用户选择的商品与用户决定购买商品的数量。然后获取当前HttpSession中用户已选择商品列表,如果列表为空创建并添加此次选择的商品,如果列表不为空,就直接向列表中添加此次选择的商品。然后将更新之后的商品发送到HttpSession中,调用sendProductList函数。

4.sendProductList()函数:向浏览器发送当前所有商品列表。

5.getProduct()函数:从当前所有商品中,根据商品Id找到对应的商品返回。

6.sendProductDetails()函数:向浏览器发送在商品列表页面选中的商品的详细信息。会有一个表单,用户可以输出购买的数量,然后点击Buy按钮,浏览器就会向服务器发送请求,调用Servlet,由于是Post方式,会调用doPost()函数。

7.showCart()函数:向浏览器发送购物车页面。主要功能是从HttpSession中读取Session中的cart信息。该信息就是之前用户选择购买数量并确定购买(点击了Buy按钮)的所有商品。然后显示购买的商品Id、名称、描述与价格,还有购买数量与该商品总共花费,在最后还会有所有商品即购物车中所有商品的总价格。

程序启用

与之前一样,通过URL调用Servlet:

http://localhost:8080/app01a/products

调用页面如下:
这里写图片描述

注意下,app01a是工程名,这个只是一个示范,还是看Servlet的路径即可。

猜你喜欢

转载自blog.csdn.net/zy2317878/article/details/80275463