????? ?如何把产品添加进购物车对象,需要解决两个关键问题:一是购物车对象本身的保存,二是购物车对象所持有的对象。这里为了简洁,我们只假定购物车对象持有一个购物项对象即可,至于涉及到订单相关的持有信息,这里略去。
?????
????? 购物项的主要属性:一是产品对象,二是产品数量。
????? 购物车持有购物项,购物项保存具体某项产品的信息。至此,基本解决了问题二:购物车对象持有对象的问题。
?????
????? ?购物车对象的保存问题思路:用户点击购物链接,传递产品id信息后,后台处理动作
步骤一:从当前session中获取购物车对象,如果不能获取,转至步骤二。?
步骤二:从cookie中获取保存的sessionId值所关联到的session对象,再通过此session对象获取购物车对象。这一步需要注意的一个问题是:由于执行此步时可以确定当前session中不存在购物车对象,所以获取通过cookie的一系列动作获取购物车对象后,应首先把获取到的购物车对象进加当前session中,并且要移出cookie中最初保存的sessionid值,并把当前sessionID值加进cookie中去。
步骤三,如果通过以上两步仍不能获取购物车,说明用户是首次点击购物链接(当然后也可能是用户屏蔽了cookie,对于普通用户而言,这种可能性较少)。此时我们应创建购物车对象,并把购物车对象加进当前session中,并把当前sessionId值用cookie记录。这样以后的购物时,不同的浏览器窗口可以有效(其实这主要是解决IE6不同窗口购物车不能共享的问题)。
步骤四,通过以上三步,最终一定可以获取一个购物车对象,我们要操作的就是把产品加进购物项,并把购物项加进购物车。到此,基本的购物车问题解决完成。
?
????? 两个比较细节的小问题:一是如何处理登录用户与购物车对象的绑定,二是如何保证在购物车展现页面刷新时,不增加产品数量。可能第二个问题比较难理解,它的实质是这样,当我们点击购物链接时总会向服务器传递一个产品id标识,而这个id标识经过服务器的处理后,并服务端跳转到购物车展示页面,而链接中仍会保存xxx.action?id=121这种链接,当用户点击刷新时,又会发出一次新的请求给服务器,这样就相当于又点击了购物链接。
????? 下面通过抽取的一些代码,来说明购物车的处理流程:
public String execute() throws Exception { ShoppingCar shoppingCar = (ShoppingCar) request.getSession().getAttribute("shoppingCar"); if (shoppingCar == null) { // 如果找不到,则从cookie记录的sessionId中找到session,再通过找到的session找购物车对象 String sessionid = WebUtil.getCookieByName(request, "theSessionId"); if (sessionid != null) { HttpSession session = WebSessionListener.getSession(sessionid); if (session != null) { shoppingCar = (ShoppingCar) session.getAttribute("shoppingCar"); if (shoppingCar != null) {// 如果从其它的session中能获取购物车,则把此购物车重新加到当前会话中,并移除存在sesionMap中对应的session request.getSession().setAttribute("shoppingCar", shoppingCar); WebUtil.addCookie(response, "theSessionId", request.getSession().getId(), request.getSession().getMaxInactiveInterval()); // xx以前的session时,如果用户已登录,应先保存用户登录信息 User user = (User) session.getAttribute("user"); if (user != null) { request.getSession().setAttribute("user", user); } WebSessionListener.remove(sessionid); } } } } if (shoppingCar == null) { // 如果通过当前sesion及cooiesession仍找不到购物车对象,则创建购物车对象到当前session,并加cookie记录 shoppingCar = new ShoppingCar(); request.getSession().setAttribute("shoppingCar", shoppingCar); WebUtil.addCookie(response, "theSessionId", request.getSession().getId(), request .getSession().getMaxInactiveInterval()); } if (productid != null && productid > 0) { Product product = productService.find(Product.class, productid); ShoppingItem currentItem = new ShoppingItem(product); if (!shoppingCar.getItems().contains(currentItem)) {// 此处代码的作用主要是用来处理购物车页面刷新时会增加购物项的问题 shoppingCar.addShoppingItem(new ShoppingItem(product, 1));// 把产品添加到购物车中 } } return "success"; }
????? 简要说明:if (!shoppingCar.getItems().contains(currentItem)) 此动作的一个前提条件是必须重写购物项及产品的hashCode及equals方法,并且重写它们依赖的参照是id,这样做主要是保证当产品的id相同时,它们equals返回true。这样用户刷新时,发现购物车中存在此购物项,就不会去添加购物项。
????? 上面代码中涉及到的一些代码如下:
package com.asm.base.listener; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class WebSessionListener implements HttpSessionListener { private static Map<String, HttpSession> sessions = new LinkedHashMap<String, HttpSession>(); @Override public void sessionCreated(HttpSessionEvent sessionEvent) { sessions.put(sessionEvent.getSession().getId(), sessionEvent.getSession()); } @Override public void sessionDestroyed(HttpSessionEvent sessionEvent) { sessions.remove(sessionEvent.getSession().getId()); } public static HttpSession getSession(String sessionId) { return sessions.get(sessionId); } public static void remove(String sessionId) { if (sessions.containsKey(sessionId)) { sessions.remove(sessionId); } } }
????? 它是一个xxx,需要在web.xml中作配置,监听session 动作。
?
/** * 添加cookie * * @param name:cookie的名称 * @param value:cookie的值 * @param maxAge:cookie存放的时间(以秒为单位,假如存放三天,即3*24*60*60;如果值为0,cookie将随浏览器关闭而xx */ public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) { Cookie cookie = new Cookie(name, value); cookie.setPath("/"); if (maxAge > 0) { cookie.setMaxAge(maxAge); } response.addCookie(cookie); } /** * 获取cookie的值 * * @param name:cookie的名称 */ public static String getCookieByName(HttpServletRequest request, String name) { Map<String, Cookie> cookieMap = WebUtil.readCookieMap(request); if (cookieMap.containsKey(name)) { Cookie cookie = (Cookie) cookieMap.get(name); return cookie.getValue(); } else { return null; } }
??? 说明:它是webUtil工具类提供的两个便于cookie操作的静态方法。
至于更多购物车的细节问题,可以结合实际情况进行考虑
?