构建开发环境

导入需要用到的开发包

  • servlet-api.jar
  • jstl-1.2.jar
  • standard-1.1.2.jar

建立程序开发包

 

设计实体

书籍实体

public class Book {
    private String id;
    private String name;
    private String author;
    private String description;
    private double price;

    public Book(){

    }

    public Book(String id,String name,String author,String description,double price){
        this.id=id;
        this.name=name;
        this.author=author;
        this.description=description;
        this.price=price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", description='" + description + '\'' +
                ", price=" + price +
                '}';
    }

    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 String getDescription() {
        return description;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

购物项实体

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;
    }
    //书的价钱*数量
    public double getPrice() {
        return this.quantity*this.book.getPrice();
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

购物车实体

public class Cart {
    //关键字是书籍的id,只是购物项
    private Map<String, CartItem> items = new LinkedHashMap<>();
    //购物车总价
    private double price;
    //把购物项(用户传递进来的书籍)加入购物车里面,也应该是购物车的功能
    public void addBook(Book book) {
        CartItem cartItem = items.get(book.getId());
        //判断购物车是否存在该购物项
        if (cartItem == null) {
            //如果不存在,则创建这个购物项对象
            cartItem=new CartItem();
            //将用户传递过来的书籍作为购物项
            cartItem.setBook(book);
            //把该购物项的数量设置为1
            cartItem.setQuantity(1);
            //把购物项加入到购物车
            items.put(book.getId(),cartItem);
        }else{
            //如果存在该购物项,则将购物项的数量加1
            cartItem.setQuantity(cartItem.getQuantity()+1);
        }
    }

    public Map<String, CartItem> getItems() {
        return items;
    }

    public void setItems(Map<String, CartItem> items) {
        this.items = items;
    }

    //购物车的总价就是所有购物项的价钱加起来
    public double getPrice() {
        double totalPrice=0d;
        if(items!=null){
            for(Map.Entry entry:items.entrySet()){
                //得到每个购物项
                CartItem cartItem = (CartItem)entry.getValue();
                //将购物项的钱加起来,就是购物车的总价
                totalPrice+=cartItem.getPrice();
            }
        }
        return totalPrice;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

 

数据库

直接用集合模拟数据库

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

    static {
        map.put("1",new Book("1","java","jack","good",75.5));
        map.put("2",new Book("2","spring mvc","tom","not good",35.5));
        map.put("3",new Book("3","javaweb","jerry","very good",100));
        map.put("4",new Book("4","spring boot","john","just so so",50));
    }

    public static Map<String,Book> getAll(){
        return map;
    }
}

 

开发dao

public class BookDao {
    //获取存放着书籍的Map集合
    public Map getAll(){
        return BookDB.getAll();
    }
    //根据关键字获取某本书籍
    public Book find(String id){
        return BookDB.getAll().get(id);
    }

    public void buyBook(String id, Cart cart){
        Book book = find(id);
        cart.addBook(book);
    }

    public void deleteBook(String id,Cart cart) throws CartNotFoundException{
        if(cart==null){
            throw  new CartNotFoundException("购物车已为空");
        }
        cart.getItems().remove(id);
    }

    public void clearCart(Cart cart){
        cart.getItems().clear();
    }

    public void updateQuantity(String id,int quantity,Cart cart){
        cart.getItems().get(id).setQuantity(quantity);
    }
}

 

开发service

service层就是对DAO层的一个封装

public class BookService {
    private BookDao bookDao = new BookDao();

    public Map getAll() {
        return bookDao.getAll();
    }

    public Book find(String id) {
        return bookDao.find(id);
    }

    public void buyBook(String id, Cart cart) {
        bookDao.buyBook(id, cart);
    }

    public void deleteBook(String id, Cart cart) throws CartNotFoundException {
        bookDao.deleteBook(id, cart);
    }

    public void clearCart(Cart cart){
        bookDao.clearCart(cart);
    }

    public void updateQuantity(String id,int quantity,Cart cart){
        bookDao.updateQuantity(id,quantity,cart);
    }
}

 

开发web

列出所有的书

开发提供JSP页面的Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        BookServiceDao bookService=new BookServiceImpl();
        Map<String, Book> books = bookService.getAll();
        request.setAttribute("books",books);
        request.getRequestDispatcher("/WEB-INF/ListAllBook.jsp").forward(request,response);
    }

开发显示所有书籍的jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>显示所有的书籍</title>
</head>
<body>
${pageContext.request.contextPath}
<table border="1px">
    <tr>
        <td>书籍编号</td>
        <td>书名</td>
        <td>作者</td>
        <td>描述</td>
        <td>单价</td>
        <td>购买</td>
    </tr>
    <c:forEach items="${books}" var="me">
        <tr>
            <td>${me.key}</td>
            <td>${me.value.name}</td>
            <td>${me.value.author}</td>
            <td>${me.value.description}</td>
            <td>${me.value.price}</td>
            <td><a href="${pageContext.request.contextPath}/BuyServlet?bookId=${me.key}"/>购买 </td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

效果:

购买操作

开发处理购买的Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取得到传递过来的id
        String id = request.getParameter("bookId");
        //把用户想要买的书放到购物上
        //用户不单单只有一个,要让购物车上只为当前的用户服务,就需要用到会话跟踪技术了
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        //如果当前用户还没有点击购买的商品,那么用户的购物车就是空的
        if (cart == null) {
            cart = new Cart();
            request.getSession().setAttribute("cart", cart);
        }
        //调用BussinessService的方法,实现购买功能
        BookService bookService = new BookService();
        bookService.buyBook(id, cart);
        //跳转到购物车显示的页面上
        request.getRequestDispatcher("/WEB-INF/ListCart.jsp").forward(request, response);
    }

购物车的页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>购物车页面显示</title>
    <script type="text/javascript">
        function updateQuantity(obj,id,oldValue) {
           var quantity= obj.value;
           if(confirm("确定要修改数量?")){
               window.location.href="${pageContext.request.contextPath}/UpdateQuantity?bookId="+id+"&quantity="+quantity;
           }else{
               obj.value=oldValue;
           }
        }
    </script>
</head>
<%--empty函数是判断集合中有没有元素--%>
<%--如果购物车没有任何购物项--%>
<c:if test="${empty(cart.items)}">
    <h1>您还有购买过任何书籍</h1>
</c:if>
<%--如果购物车有购物项,就显示购物项--%>
<c:if test="${!empty(cart.items)}">
    <table border="1px">
        <tr>
            <td>书籍编号</td>
            <td>名称</td>
            <td>数量</td>
            <td>小计</td>
            <td>操作</td>
        </tr>
        <c:forEach items="${cart.items}" var="me">
            <tr>
                <td>${me.key}</td>
                <td>${me.value.book.name}</td>
                <td><input type="text" value="${me.value.quantity}" onchange="updateQuantity(this,${me.key},${me.value.quantity})"/> </td>
                <td>${me.value.price}</td>
                <td><a href="${pageContext.request.contextPath}/DeleteCartBook?bookId=${me.key}">删除</a> </td>

            </tr>
        </c:forEach>
        <tr>
            <td colspan="2"><a href="${pageContext.request.contextPath}/ClearCart" onclick="return confirm('确定要清空购物车?');">清空购物车</a> </td>
            <td colspan="2">合计</td>
            <td>${cart.price}</td>
        </tr>
    </table>
</c:if>
<body>

</body>
</html>

效果:

删除操作

开发删除功能的Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //获取得到用户想要删除的那本书的id
            String id = request.getParameter("bookId");
            //获取该用户相对应的购物车对象
            Cart cart = (Cart) request.getSession().getAttribute("cart");
            //删除购物车的商品
            BookService bookService = new BookService();
            bookService.deleteBook(id, cart);
            //删除购物车的商品后,也应该直接跳转回去购物车的显示页面
            request.getRequestDispatcher("/WEB-INF/ListCart.jsp").forward(request, response);
        } catch (CartNotFoundException e) {
            request.setAttribute("message", "购物车空了");
            request.getRequestDispatcher("/WEB-INF/Message.jsp").forward(request, response);
        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("message", "删除出现异常,待会再试");
            request.getRequestDispatcher("/WEB-INF/Message.jsp").forward(request, response);
        }
    }
}

效果:

修改数量

购物车上,数量的值改成输入框,写javascript代码,监控着输入框的变动,如果有变动,就响应事件,将变动的数据传递给服务器,更新数据。(见前面代码)

编写修改数量的Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取用户想要修改数量的书的id
        String id=request.getParameter("bookId");
        //获取修改的数量
        int quantity=Integer.parseInt(request.getParameter("quantity"));
        //得到当前用户的购物车
        Cart cart =(Cart) request.getSession().getAttribute("cart");
        //调用BusinessService的方法去修改对应的数据
        BookService bookService = new BookService();
        bookService.updateQuantity(id,quantity,cart);
        //修改完再跳转回去购物车的页面中
        request.getRequestDispatcher("/WEB-INF/ListCart.jsp").forward(request,response);
    }
}

效果:

清空购物车

首先通过javascript代码询问用户是否要清空,如果要清空就跳转到相对应的Servlet中把购物车的数据清空了。(见前面页面)

开发清空购物车的Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //得到用户相对应的购物车
        BookService bookService = new BookService();
        //调用相对应BusinessService的方法
        Cart cart =(Cart) request.getSession().getAttribute("cart");
        if(cart==null){
            cart=new Cart();
            request.getSession().setAttribute("cart",cart);
        }
        //清空购物车
        bookService.clearCart(cart);
        request.getRequestDispatcher("/WEB-INF/ListCart.jsp").forward(request,response);
    }
}

效果:

 

总结:

  1. 购物车的应该是一个以id作为key,以购物项作为value的一个Map集合。这样在显示商品的时候,就不会重复显示同一种类型的商品。
  2. 购物项代表该商品,并且应该给予购物项数量和价钱的属性。购物项的价钱应该是数量*单价。
  3. 购物车应该提供把商品添加到购物车的功能。当然,购物项代表着商品,所以首先要判断该购物车是否有同类的商品,如果有,直接在购物项的数量上加1即可;如果没有,就设置该购物项的属性,并把购物项添加到购物车中。
  4. 购物车的总价就是所有购物项的总价。
  5. 无论增删改查购物车的数据,其实就是操作这个集合。

 

 posted on 2019-06-29 22:32  会飞的金鱼  阅读(140)  评论(0)    收藏  举报