目录
创建MVC架构的Web项目
分层架构的代码编写
开发domain层
开发数据访问层(dao、dao.impl)
开发service层(service层对web层提供所有的业务服务)
开发Web层
开发给用户展示所有书籍的功能
开发购买书籍的功能
开发删除购物车中购物项的功能
开发清空购物车的功能
开发改变购物车某购物项数量的功能
首页 Java java教程 以Servlet+JSP+JavaBean为基础模式的开发的购物车

以Servlet+JSP+JavaBean为基础模式的开发的购物车

Aug 10, 2017 pm 03:16 PM
javascript

上一篇以一个最常用的用户登录注册程序来讲解Servlet+JSP+JavaBean开发模式,所以我们也初步了解了Servlet+JSP+JavaBean(MVC)模式。现在我们以一个网上购物时的购物车程序来重新回顾这种开发模式。

创建MVC架构的Web项目

在Eclipse中新创建一个day10项目,导入项目所需要的开发包(jar包),创建项目所需要的包,在java开发中,架构的层次是以包的形式体现出来的。
项目所需要的开发包(jar包)

序号 开发包名称 描述
1 stl-1.2.jar jstl标签库和EL表达式依赖包

注释:不同于上一篇的用户登录注册程序,该购物车程序是创建一个类来代表数据库,所以不需要用到其他一些jar包,只需用到stl-1.2.jar就行。
项目所需要的包

序号 包名 描述 所属层次
1 cn.itcast.DB 存放代表数据库的类
2 cn.itcast.domain 存放系统的JavaBean类(只包含简单的属性以及属性对应的get和set方法,不包含具体的业务处理方法),提供给【数据访问层】、【业务逻辑层】、【Web层】来使用 domain(域模型)层
3 cn.itcast.dao 存放访问数据库的操作接口的实现类 数据访问层
4 cn.itcast.service 存放处理系统业务接口的实现类 业务逻辑层
5 cn.itcast.web.controller 存放作为系统控制器的Servlet(处理请求的servlet) Web层(表现层)
6 cn.itcast.web.UI 给用户提供用户界面。由于在严格的MVC模式下,jsp被保护起来,禁止外界直接访问,如用户要注册,需要拿一个表单页面,需要用一个servlet转到jsp上面去,有一部分servlet专门给用户提供用户界面,也即是说在实际开发里面有一部分servlet是用来处理请求,有一部分servlet专门用来接收请求之后转到jsp,给用户提供用户界面 Web层(表现层)
7 cn.itcast.utils 存放系统的通用工具类,提供给【数据访问层】、【业务逻辑层】、【Web层】来使用

以上就是根据此项目的实际情况创建的包,可能还需要创建其他的包,这个得根据项目的需要来定了。  
创建代表数据库的类
假设这是一个网上书城的项目,用户购买的商品即为书,所以在数据库中存储的商品就是书。在cn.itcast.DB包下创建一个DB类。
这里写图片描述
DB类具体代码如下:

public class DB {    private static Map<String, Book> map = new LinkedHashMap<String, Book>();

    static {        map.put("1", new Book("1", "javaweb开发", "老张", 38, "一本好书"));        map.put("2", new Book("2", "jdbc开发", "老黎", 18, "一本好书"));        map.put("3", new Book("3", "ajax开发", "老佟", 328, "一本好书"));        map.put("4", new Book("4", "jbpm开发", "老毕", 58, "一本好书"));        map.put("5", new Book("5", "struts开发", "老方", 28, "一本好书"));        map.put("6", new Book("6", "spring开发", "老方", 98, "一本好书"));
    }    public static Map<String, Book> getAll() {        return map;
    }
}1234567891011121314151617
登录后复制

注释:关于怎样创建代表数据库的类——DB.java,可参考我的使用Cookie进行会话管理
在WEB-INF目录下创建一个jsp目录,jsp目录存放系统的一些受保护(不允许用户直接通过URL地址访问)的jsp页面,用户要想访问这些受保护的jsp页面,那么只能通过cn.itcast.web.UI这个包里面的Servlet。
创建好的项目架构如下图所示:
这里写图片描述

分层架构的代码编写

分层架构的代码也是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务逻辑层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】→【测试类(junit.test)】的顺序进行编写的。

开发domain层

在cn.itcast.domain包下创建一个Book类。
这里写图片描述
Book类具体代码如下:

public class Book {    private String id;    private String name;    private String author;    private double price;    private String description;    public Book() {        super();        // TODO Auto-generated constructor stub
    }    public Book(String id, String name, String author, double price, String description) {        super();        this.id = id;        this.name = name;        this.author = author;        this.price = price;        this.description = description;
    }    public String getId() {        return id;
    }    public void setId(String id) {        this.id = id;
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public String getAuthor() {        return author;
    }    public void setAuthor(String author) {        this.author = author;
    }    public double getPrice() {        return price;
    }    public void setPrice(double price) {        this.price = price;
    }    public String getDescription() {        return description;
    }    public void setDescription(String description) {        this.description = description;
    }

}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
登录后复制

开发数据访问层(dao、dao.impl)

在cn.itcast.dao包下创建一个UserDao类。
这里写图片描述
UserDao类具体代码如下:

public class BookDao {    public Map<String, Book> getAll() {        return DB.getAll();
    }    public Book find(String id) {        return DB.getAll().get(id);
    }

}1234567891011
登录后复制

开发service层(service层对web层提供所有的业务服务)

我们在第一次开发一个新项目的过程当中,并不清楚要开发的所有项目的功能,所以我们可以先开发出最容易想到的功能,然后将自己伪装成一个用户,在浏览网站页面的过程中,看用户需要什么功能,那我们程序员就开发什么功能,然后步步为营,将整个项目的功能完成。
例如,我第一次开发这个购物车功能模块的过程当中,首先想到的是要给用户展示所有书籍,以及根据书的ID查询书的信息。其他的功能我没想到,所以可以等这些功能完成之后,根据前端页面来看需要什么功能。
在cn.itcast.service包下创建一个BusinessService类。
这里写图片描述
先编写实现如下两个业务服务的BusinessService类。

  • 给用户展示所有书籍

  • 根据书的ID查询书的信息

具体代码如下:

// 业务类,统一对web层提供所有服务public class BusinessService {    private BookDao dao = new BookDao();    public Map<String, Book> getAllBook() {        return dao.getAll();
    }    public Book findBook(String id) {        return dao.find(id);
    }
}12345678910111213
登录后复制

开发Web层

开发给用户展示所有书籍的功能

在cn.itcast.web.controller包下编写用于处理给用户展示所有书籍的ListBookServlet。
这里写图片描述
ListBookServlet类的具体代码如下:

// 获取所有书public class ListBookServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        BusinessService service = new BusinessService();
        Map<String, Book> map = service.getAllBook();
        request.setAttribute("map", map);

        request.getRequestDispatcher("/WEB-INF/jsp/listbook.jsp").forward(request, response);

    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}12345678910111213141516171819
登录后复制

在/WEB-INF/jsp/目录下编写给用户展示所有书籍的jsp页面listbook.jsp。
这里写图片描述
凡是位于WEB-INF目录下的jsp页面是无法直接通过URL地址直接访问的。在开发中如果项目中有一些敏感web资源不想被外界直接访问,那么可以考虑将这些敏感的web资源放到WEB-INF目录下,这样就可以禁止外界直接通过URL来访问了。
listbook.jsp页面的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>书籍列表页面</title></head><body style="text-align: center;">    <h1>书籍列表</h1>    <table width="70%" border="1" align="center">        <tr>            <td>书名</td>            <td>作者</td>            <td>售价</td>            <td>描述</td>            <td>操作</td>        </tr>        <c:forEach var="entry" items="${map }">            <tr>                <td>${entry.value.name }</td>                <td>${entry.value.author }</td>                <td>${entry.value.price }</td>                <td>${entry.value.description }</td>                <td>                    <a href="${pageContext.request.contextPath }/BuyServlet?id=${entry.key }" target="_blank">购买</a>                </td>            </tr>        </c:forEach>    </table></body></html>12345678910111213141516171819202122232425262728293031323334
登录后复制

网站一般都有一个首页,在该项目中我们的首页index.jsp中,用户点击浏览书籍超链接即可浏览网站所有书籍。
index.jsp页面的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>网站首页</title></head><body>    <a href="${pageContext.request.contextPath }/ListBookServlet">浏览书籍</a></body></html>123456789101112
登录后复制

至此,给用户展示所有书籍的功能就算是开发完成了!下面测试一下开发好的该功能:
这里写图片描述

开发购买书籍的功能

在现实中购买商品时,用户都是将商品放到购物车中,所以我们应该按照现实中的情况设计一个代表用户购物车的类——Cart.java。
现在再来思考一个问题:在设计代表用户购物车的Cart类时,应该使用private Book book字段(或属性)来代表用户所购买的商品吗?
答案显然不是。若是使用这样的字段,结果就是不可避免地在购物车中出现重复商品,即用户如果购买一本书多次,那么购物车中就出现一本书多次,显然在现实中这是不合理的。那么到底该怎么做呢?——为了避免在购物车里面出现重复商品,我们这时会设计一个专门的对象——CartItem(购物项,代表某个商品以及这个商品出现的次数)
在cn.itcast.domain包下创建一个CartItem类,用于代表某个商品,以及商品出现的次数(购物项)。
这里写图片描述
CartItem类的具体代码如下:

// 用于代表某个商品,以及商品出现的次数(购物项)public class CartItem {    private Book book;    private int quantity;    private double price;    public Book getBook() {        return book;
    }    public void setBook(Book book) {        this.book = book;
    }    public int getQuantity() {        return quantity;
    }    public void setQuantity(int quantity) {        this.quantity = quantity;        this.price = this.book.getPrice() * this.quantity;
    }    public double getPrice() {        return price;
    }    public void setPrice(double price) {        this.price = price;
    }

}12345678910111213141516171819202122232425262728
登录后复制

在cn.itcast.domain包中创建一个代表用户购物车的Cart类。
这里写图片描述
Cart类的具体代码如下:

// 代表用户的购物车public class Cart {    /*
     * 为了避免在购物车里面出现重复商品,
     * 我们这时会设计一个专门的对象——CartItem(购物项,代表某个商品以及这个商品出现的次数)
     */    private Map<String, CartItem> map = new LinkedHashMap<>();    private double price; // 记住购物车中的所有商品多少钱    public void add(Book book) {        // 看购物车中有没有,要添加的书对应的购物项
        CartItem item = map.get(book.getId());        if(item==null) {
            item = new CartItem();
            item.setBook(book);
            item.setQuantity(1);
            map.put(book.getId(), item);
        } else {
            item.setQuantity(item.getQuantity()+1);
        }
    }    public Map<String, CartItem> getMap() {        return map;
    }    public void setMap(Map<String, CartItem> map) {        this.map = map;
    }    public double getPrice() {        double totalprice = 0;        for(Map.Entry<String, CartItem> entry : map.entrySet()) {
            CartItem item = entry.getValue();
            totalprice += item.getPrice();
        }        this.price = totalprice;        return price;
    }    public void setPrice(double price) {        this.price = price;
    }

}12345678910111213141516171819202122232425262728293031323334353637383940414243
登录后复制

用户浏览网站首页时,会看到网站所有书籍,用户即可对自己感兴趣的书籍进行购买,点击购物超链接时,跳转到一个servlet对用户的请求进行处理。所以在cn.itcast.web.controller包中创建一个代表完成书籍购买的BuyServlet类。
这里写图片描述
BuyServlet类的具体代码如下:

// 完成书籍购买@WebServlet("/BuyServlet")public class BuyServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {

        String id = request.getParameter("id");
        BusinessService service = new BusinessService();
        Book book = service.findBook(id);        // 得到用户的购物车
        Cart cart = (Cart) request.getSession().getAttribute("cart");        // 用户第一次购买,为用户创建购物车        if(cart==null) {
            cart = new Cart();
            request.getSession().setAttribute("cart", cart);
        }        // 把书加到用户的购物车中,完成购买
        cart.add(book);        /* 
         * 浏览器重新访问地址:/WEB-INF/jsp/listcart.jsp
         * 但这个地址被保护起来,外面是无法直接访问的,
         * 要实现的话,会比较麻烦,需要先跳到servlet,然后再转到jsp。
         */        // response.sendRedirect("/WEB-INF/jsp/listcart.jsp");

        request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}1234567891011121314151617181920212223242526272829303132333435363738
登录后复制

注意:显示购物车时,记住千万不要用请求转发,而应该使用重定向技术。若不是产生的后果可参考我的笔记Session——使用Session完成简单的购物功能。我上面的代码使用的是请求转发,这是不行的,读者要注意了啊!既然要使用重定向技术,下面这行代码可行吗?

response.sendRedirect("/WEB-INF/jsp/listcart.jsp");1
登录后复制

答案不言而喻,这是不行的。因为这是浏览器重新访问地址/WEB-INF/jsp/listcart.jsp,listcart.jsp页面是被保护起来了,外界是无法直接访问的。如果一定要实现的话,会比较麻烦,还需要先跳到一个servlet,然后再跳转到listcart.jsp。所以正规的做法是:BuyServlet类中使用重定向技术,即添加如下代码:

response.sendRedirect(request.getContextPath()+"/ListCartUIServlet");1
登录后复制

然后在cn.itcast.web.UI包下创建一个ListCartUIServlet类,专门用来接收请求之后转到jsp,给用户提供用户界面。
这里写图片描述
ListCartUIServlet类的具体代码如下:

public class ListCartUIServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}12345678910111213
登录后复制

这毕竟不是一个真实项目,所以不想把其搞得这么复杂哈!所以就干脆用了请求转发,但是读者一定要知道这还是不行的,要知道用重定向技术,怎么使用我也已经写的很明白了!
购物车显示页面listcart.jsp代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>购物车列表</title><script type="text/javascript">    function deleteitem(id) {        var b = window.confirm("您确认删除吗?");        if(b) {            // window代表当前浏览器窗口,location代表当前浏览器窗口的地址栏
            window.location.href = "${pageContext.request.contextPath }/DeleteItemServlet?id="+id;
        }
    }    function clearCart() {        var b = window.confirm("您确认清空吗?");        if(b) {
            window.location.href = "${pageContext.request.contextPath }/ClearCartServlet"
        }
    }    function changeQuantity(input, id, oldValue) {        var quantity = input.value; // 得到要修改的数量        /*
        // 检查用户输入的数量是不是一个数字
        if(isNaN(quantity)) {
            alert("请输入数字!!!");
            // 得到输入项原来的值
            input.value = oldValue;
            return;
        }
        */        // 检查用户输入的数量是不是一个正整数        if(quantity<0 || quantity!=parseInt(quantity)) {    // 1.1 != 1     parseInt("abc")返回NaN
            alert("请输入一个正整数!!!");
            input.value = oldValue;            return;
        }        var b = window.confirm("您确定把书的数量修改为"+quantity+"吗?")        if(b) {
            window.location.href = "${pageContext.request.contextPath }/ChangeQuantityServlet?id="+id+"&quantity="+quantity;
        }
    }</script></head><body style="text-align: center;">    <h1>购物车列表</h1>    <c:if test="${empty(cart.map) }"> <!-- cart.map.empty:map为空,没东西       el表达式的函数:empty()——检测map是否为null或"",若是则返回true   -->
        您没有购买任何商品!!!    </c:if>    <c:if test="${!empty(cart.map) }">    <table width="70%" border="1" align="center">        <tr>            <td>书名</td>            <td>作者</td>            <td>单价</td>            <td>数量</td>            <td>小计</td>            <td>操作</td>        </tr>        <c:forEach var="entry" items="${cart.map }">   <!-- entry<id, CartItem> -->            <tr>                <td>${entry.value.book.name }</td>                <td>${entry.value.book.author }</td>                <td>${entry.value.book.price }</td>                <td>                                                                                                <!-- this代表input输入项 -->              
                    <input type="text" name="quantity" value="${entry.value.quantity }" style="width: 35px" onchange="changeQuantity(this, ${entry.key }, ${entry.value.quantity })" />                </td>                <td>${entry.value.price }</td>                <td>                    <!-- javascript:void(0):去掉超链接的默认行为 -->                    <a href="javascript:void(0)" onclick="deleteitem(${entry.key })">删除</a>                </td>            </tr>        </c:forEach>        <tr>            <td colspan="3">总价</td>            <td colspan="2">${cart.price }元</td>            <td colspan="1">                <a href="javascript:void(0)" onclick="clearCart()">清空购物车</a>            </td>        </tr>    </table>    </c:if></body></html>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
登录后复制

至此,用户购买书籍的功能就算是开发完成了!下面测试一下开发好的该功能:
这里写图片描述

开发删除购物车中购物项的功能

编写实现如下业务服务的BusinessService类。

  • 删除购物车中购物项

此时BusinessService类的具体代码如下:

// 业务类,统一对web层提供所有服务public class BusinessService {    private BookDao dao = new BookDao();    public Map<String, Book> getAllBook() {        return dao.getAll();
    }    public Book findBook(String id) {        return dao.find(id);
    }    // 删除购物车中购物项    public void deleteCartItem(String id, Cart cart) {
        cart.getMap().remove(id);
    }

}12345678910111213141516171819
登录后复制

在cn.itcast.web.controller下创建一个DeleteItemServlet类。
这里写图片描述
DeleteItemServlet类的具体代码如下:

public class DeleteItemServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {

        String id = request.getParameter("id");
        Cart cart = (Cart) request.getSession().getAttribute("cart");

        BusinessService service = new BusinessService();
        service.deleteCartItem(id, cart);        // 删除成功,还是跳转到listcart.jsp页面
        request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}123456789101112131415161718192021
登录后复制

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:

<script type="text/javascript">    function deleteitem(id) {        var b = window.confirm("您确认删除吗?");        if(b) {            // window代表当前浏览器窗口,location代表当前浏览器窗口的地址栏
            window.location.href = "${pageContext.request.contextPath }/DeleteItemServlet?id="+id;
        }
    }</script>123456789
登录后复制

不然的话,用户手贱,不小心删除了所选的购物项,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心删除了所选的购物项时,还要问用户是否确认删除。只有用户点击确认按钮才会删除,这样对用户来说,体验会更好。
至此,删除购物车中购物项的功能就算是开发完成了!下面测试一下开发好的该功能:
这里写图片描述

开发清空购物车的功能

编写实现如下业务服务的BusinessService类。

  • 清空购物车

编写对应的清空购物车的方法时,由于代表用户购物车的Cart类存在session中,是不是可以像下面这样写呢?

public void clearCart(HttpSession session) {    ...     }123
登录后复制

答:不可以。业务逻辑层用到Web层对象——session,业务逻辑层和Web层牢牢绑定在一起了,业务逻辑层离开Web层就跑不起来了,如果这样写,若要对业务层进行测试,需要把Web服务器起起来,传一个session进去,所以在各层之间传递的只能是JavaBean,不能让Web层的特殊对象侵入到业务逻辑层,污染业务逻辑层
此时BusinessService类的具体代码如下:

// 业务类,统一对web层提供所有服务public class BusinessService {    private BookDao dao = new BookDao();    public Map<String, Book> getAllBook() {        return dao.getAll();
    }    public Book findBook(String id) {        return dao.find(id);
    }    // 删除购物车中购物项    public void deleteCartItem(String id, Cart cart) {
        cart.getMap().remove(id);
    }    // 清空购物车    public void clearCart(Cart cart) {
        cart.getMap().clear();
    }

}123456789101112131415161718192021222324
登录后复制

在cn.itcast.web.controller包下创建一个ClearCartServlet类。
这里写图片描述
ClearCartServlet类的具体代码如下:

public class ClearCartServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {

        Cart cart = (Cart) request.getSession().getAttribute("cart");

        BusinessService service = new BusinessService();
        service.clearCart(cart);

        request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}12345678910111213141516171819
登录后复制

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:

<script type="text/javascript">    function clearCart() {        var b = window.confirm("您确认清空吗?");        if(b) {
            window.location.href = "${pageContext.request.contextPath }/ClearCartServlet";
        }
    }</script>12345678
登录后复制

不然的话,用户手贱,不小心清空了购物车,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心清空了购物车时,还要问用户是否确认清空。只有用户点击确认按钮才会清空,这样对用户来说,体验会更好。
还有一点要注意:如果用户清空了购物车,那么购物车显示页面不能没有任何显示,这也是对用户体验的一种折磨,明智的做法应该是给用户显示您没有购买任何商品!!!,这样用户体验会更好。那怎样判断用户有没有购买商品呢?——可使用el表达式的函数:empty(object),检测object对象是否为null或”“,若是则返回true。这样购物车显示页面listcart.jsp页面中的关键代码如下:

<h1>购物车列表</h1><c:if test="${empty(cart.map) }"> <!-- cart.map.empty:map为空,没东西       el表达式的函数:empty()——检测map是否为null或"",若是则返回true   -->
    您没有购买任何商品!!!</c:if><c:if test="${!empty(cart.map) }">
    ...</c:if>12345678
登录后复制

至此,清空购物车的功能就算是开发完成了!下面测试一下开发好的该功能:
这里写图片描述

开发改变购物车某购物项数量的功能

在现实中的购物中,当用户购买一件商品时,发现还需要购买这件商品,比如数量为100,用户不可能点击这件商品100次,若是这样,那这样的购物网站倒闭1万亿遍了。所以一般来说用户只需要改变其数量即可,这时就需要用到<input>控件,而且用户要输入的数量要是一个正整数,不能是其他乱七八糟的东西。
编写实现如下业务服务的BusinessService类。

  • 改变购物车某购物项的数量

此时BusinessService类的具体代码如下:

// 业务类,统一对web层提供所有服务public class BusinessService {    private BookDao dao = new BookDao();    public Map<String, Book> getAllBook() {        return dao.getAll();
    }    public Book findBook(String id) {        return dao.find(id);
    }    // 删除购物车中购物项    public void deleteCartItem(String id, Cart cart) {
        cart.getMap().remove(id);
    }    // 清空购物车    public void clearCart(Cart cart) {
        cart.getMap().clear();
    }    // 改变购物车某购物项的数量    public void changeItemQuantity(String id, String quantity, Cart cart) {
        CartItem item = cart.getMap().get(id);
        item.setQuantity(Integer.parseInt(quantity));
    }

}123456789101112131415161718192021222324252627282930
登录后复制

在cn.itcast.web.controller中创建ChangeQuantityServlet类。
这里写图片描述
ChangeQuantityServlet类的具体代码如下:

// 把购物车中的书修改为指定数量public class ChangeQuantityServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {

        String id = request.getParameter("id");
        String quantity = request.getParameter("quantity");

        Cart cart = (Cart) request.getSession().getAttribute("cart");

        BusinessService service = new BusinessService();
        service.changeItemQuantity(id, quantity, cart);

        request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
    }    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {
        doGet(request, response);
    }

}1234567891011121314151617181920212223
登录后复制

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:

<script type="text/javascript">    function changeQuantity(input, id, oldValue) {        var quantity = input.value; // 得到要修改的数量        // 检查用户输入的数量是不是一个正整数        if(quantity<0 || quantity!=parseInt(quantity)) {    // 1.1 != 1     parseInt("abc")返回NaN
            alert("请输入一个正整数!!!");
            input.value = oldValue;            return;
        }        var b = window.confirm("您确定把书的数量修改为"+quantity+"吗?")        if(b) {
            window.location.href = "${pageContext.request.contextPath }/ChangeQuantityServlet?id="+id+"&quantity="+quantity;
        }
    }</script>1234567891011121314151617
登录后复制

完整的购物车显示页面listcart.jsp代码前面已经给出了,这里不再赘写。
至此,改变购物车某购物项数量的功能就算是开发完成了!下面测试一下开发好的该功能:
这里写图片描述

以上是以Servlet+JSP+JavaBean为基础模式的开发的购物车的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统 如何使用WebSocket和JavaScript实现在线预约系统 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

javascript中如何使用insertBefore javascript中如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。

JavaScript和WebSocket:打造高效的实时图像处理系统 JavaScript和WebSocket:打造高效的实时图像处理系统 Dec 17, 2023 am 08:41 AM

JavaScript是一种广泛应用于Web开发的编程语言,而WebSocket则是一种用于实时通信的网络协议。结合二者的强大功能,我们可以打造一个高效的实时图像处理系统。本文将介绍如何利用JavaScript和WebSocket来实现这个系统,并提供具体的代码示例。首先,我们需要明确实时图像处理系统的需求和目标。假设我们有一个摄像头设备,可以采集实时的图像数

See all articles