转载

浅谈实现基于Javabean与JSP的购物车功能

首先呢,在买了东西之后要放在购物车里,当车子里的物品有相同时就叠加,不再创建物品对象,有了物品之后肯 定要有价格,数量等等对象。这些对象我们要封装在JAVABEAN 中的!有了Javabean就需要建立SERVLET来进行与业务层连接,我们就需要有,增加购物车,删除购物车,清楚购物车等一系列的Servlet和SERVICE层连接!SERVICE层调用DAO层,这些步骤正体现出了MVC的设计模式!下面我们看具体的实现基于Javabean与JSP的购物车功能吧!

(1) 1. 代表购物车的ShoppingCart 类

  1. public class ShoppingCart {  
  2.  //装载 ShoppingCartItem 的数据结构: Map, 键: 书的 id, 值: 书对应的 ShoppingCartItem  
  3.  private Map<String, ShoppingCartItem> books = null;  
  4.    
  5.  public ShoppingCart(){  
  6.   books = new HashMap<String, ShoppingCartItem>();  
  7.  }   
  8.  
  9.  public Map<String, ShoppingCartItem> getBooks() {  
  10.   return books;  
  11.  }  
  12.    
  13.  public Book getBook(String bookId){  
  14.   Book book = null;  
  15.     
  16.   ShoppingCartItem sci = this.books.get(bookId);  
  17.   if (sci == null)  
  18.    return null;  
  19.     
  20.   return sci.getBook ();  
  21.  }  
  22.    
  23.  public float getTotalPrice(){  
  24.   float totalPrice = 0.0f;  
  25.     
  26.   //对 books 中的 value 进行遍历, 取其 price 属性的和   
  27.   Iterator<ShoppingCartItem> iterator = books.values().iterator ();  
  28.   while(iterator.hasNext()){  
  29.    ShoppingCartItem sci = iterator.next();  
  30.    totalPrice += sci.getPrice();  
  31.   }   
  32.     
  33.   return totalPrice;  
  34.  }  
  35.    
  36.  public int getTotalQuantity(){  
  37.   int quantity = 0;  
  38.     
  39.   //对 books 中的 value 进行遍历, 取其 quantity 属性的和  
  40.   Iterator<ShoppingCartItem> iterator = books.values().iterator();  
  41.   while(iterator.hasNext()) {  
  42.    ShoppingCartItem sci = iterator.next();  
  43.    quantity += sci.getQuantity();  
  44.   }  
  45.     
  46.   return quantity;  
  47.  }   
  48.    
  49.  public boolean isExistInShoppingCart(String bookId){  
  50.   return this.books.get(bookId) != null;  
  51.  }  
  52.    
  53.  public ShoppingCartItem getShoppingCartItemByBookId(String bookId){  
  54.   return this.books.get(bookId);  
  55.  }   
  56.    
  57.  public void addNewItemToShoppingCart(ShoppingCartItem sci) {  
  58.   this.books.put(sci.getBook().getId(), sci);  
  59.  }  

2. 代表购物车中的物品

  1. public class ShoppingCartItem {  
  2.  //具体指向某本书  
  3.  private Book book;  
  4.    
  5.  //当前商品在购物车中的数量  
  6.  private int quantity;  
  7.    
  8.  public ShoppingCartItem(Book book) {  
  9.   this.book = book;  
  10.   this.quantity = 1;  
  11.  }  
  12.  
  13.  //当前商品的总价格  
  14.  private float price;  
  15.    
  16.  public void incrementQuantity(){  
  17.   this.quantity++;  
  18.  }  
  19.  
  20.  public Book getBook() {  
  21.   return book;  
  22.  }  
  23.  
  24.  public void setBook(Book book) {  
  25.   this.book = book;  
  26.  }  
  27.  
  28.  public int getQuantity() {  
  29.   return quantity;  
  30.  }  
  31.  
  32.  public void setQuantity(int quantity) {  
  33.   this.quantity = quantity;  
  34.  }   
  35.  
  36.  public float getPrice() {  
  37.   return this.book.getPrice() * this.quantity;  
  38.  }  
  39.  

(2)建立DAO,此时有人会问,这次DAO为什么没有购物车呢,因为购物车是没有数据的,而是里面的物品才有 数据的,当有更新购物车里面的物品时才会早DAO里面写方法!

  1. public class BookDAO {  
  2.    
  3.  //  
  4.  public void upadateBookQuantityByBookId(Connection conn, String bookId, int quantity){  
  5.   String sql = "UPDATE books SET saleAmount = saleAmount + ? WHERE id = ?";  
  6.   Object [] params = new Object[]{quantity, bookId};  
  7.     
  8.   QueryRunner queryRunner = new QueryRunner ();  
  9.     
  10.   try {  
  11.    queryRunner.update(conn, sql, params);  
  12.   } catch (SQLException e) {  
  13.    // TODO Auto-generated catch block  
  14.    e.printStackTrace();  
  15.    throw new RuntimeException (MyBookStoreConstants.UPDATE_BOOK_SALEAMOUNT_BY_BOOK_ID_EXCEPTION);  
  16.   }  
  17.  } 

(3) 建立业务层,涉及到添加,清空等方法!这边佟刚老师的代码都有详细的解释!

  1. public class BookService {  
  2.  //根据给定的 ShoppingCart 对象, 调用 DAO 方法进行数据库更新操作  
  3.  public void buyBooks(ShoppingCart sc){  
  4.   //对 sc 中的 ShoppingCartItem 对象进行遍历, 调用 BookDAO.upadateBookQuantityByBookId 方法  
  5.   Connection conn = null;  
  6.   conn = DBHelper.getConnection();  
  7.     
  8.   try {  
  9.    Iterator<ShoppingCartItem> shoppingCartItemSet = sc.getBooks().values ().iterator();  
  10.    BookDAO bookDAO = new BookDAO ();  
  11.      
  12.    while(shoppingCartItemSet.hasNext()) {  
  13.     ShoppingCartItem sci = shoppingCartItemSet.next ();  
  14.       
  15.     String bookId = sci.getBook().getId ();  
  16.     int quantity = sci.getQuantity ();  
  17.       
  18.     bookDAO.upadateBookQuantityByBookId(conn, bookId, quantity);  
  19.    }  
  20.   }finally {  
  21.    DBHelper.releaseDBSource(null, null, conn);  
  22.   }   
  23.     
  24.     
  25.  }  
  26.    
  27.  //参数 items 中的键为 书的 id 号, 值为购 物车中对应的 数量  
  28.  public void updateShoppingCart(Map<String,Integer> items, ShoppingCart sc){  
  29.   Set<String> keySet = null;  
  30.   keySet = items.keySet ();  
  31.     
  32.   for(Iterator<String> it = keySet.iterator(); it.hasNext(); ) {  
  33.    String bookId = it.next();  
  34.    int quantity = items.get (bookId);  
  35.      
  36.    if(quantity <= 0) {  
  37.     sc.getBooks().remove(bookId);  
  38.    }else {  
  39.     sc.getShoppingCartItemByBookId(bookId).setQuantity (quantity);  
  40.    }  
  41.       
  42.   }  
  43.  }   
  44.    
  45.  //清空购物车  
  46.  public void clearShoppingCart(ShoppingCart sc) {  
  47.   sc.getBooks().clear();  
  48.  }  
  49.    
  50.  public void deleteShoppingCartItemById(String id, ShoppingCart sc){  
  51.   //删除 sc 中的 id 元素   
  52.   sc.getBooks().remove(id);  
  53.  }  
  54.    
  55.  //把 id 对应的 ShoppingCartItem 对象放入购物车 ShoppingCart 对象中  
  56.  public void addToShoppingCart(String id, ShoppingCart sc) {  
  57.     
  58.   //1. 查看 sc 中有没有 id 对应的 ShoppingCartItem 对象   
  59.   if(sc.isExistInShoppingCart(id)){  
  60.    //1.1 有: 把该对象取出, 使其数量 + 1, 调用 sci.increseQuantity(); 方法  
  61.    ShoppingCartItem scsci = sc.getShoppingCartItemByBookId(id);  
  62.    sci.incrementQuantity();  
  63.   }   
  64.   //1.2 没有: 创建一个新的 ShoppingCartItem 对象, 并将其放入 sc 中, 以书的 id 作为键   
  65.   else{  
  66.    //1.2.1 根据 id 获取相应的 Book 对象, 调用 BookDAO 的 selectBookByBookId() 方法  
  67.    Book book = null;  
  68.    BookDAO bookDAO = null;  
  69.      
  70.    bookDAO = new BookDAO();  
  71.    book = bookDAO.selectBookByBookId(id);  
  72.      
  73.    ShoppingCartItem sci = null;  
  74.    sci = new ShoppingCartItem (book);  
  75.      
  76.    sc.addNewItemToShoppingCart(sci);  
  77.   }   
  78.  }  

(4)这段是 检查购物车是有对象的,这里单独拿出来是可以很好的在WEB开发中很好的进行重用 的。

  1. public class MyBookStoreUtils {  
  2.  private MyBookStoreUtils(){}  
  3.    
  4.  public static  ShoppingCart getShppingCartForCreateOrExist(HttpServletRequest request) {  
  5.   ShoppingCart sc = null;  
  6.   //2.1 检查在 HttpSession 对象中有没有购物车对象 , 即检查 session 中是否有 MyBookStoreConstants.SHOOPING_CART_KEY 属性  
  7.   //   若 已经存在, 说明购物车存在, 直接取出  
  8.   HttpSession session = null;  
  9.   session = request.getSession();  
  10.     
  11.   Object obj = session.getAttribute (MyBookStoreConstants.SHOOPING_CART_KEY);  
  12.     
  13.   if(obj != null) {  
  14.    sc = (ShoppingCart) obj;  
  15.   }  
  16.   //2.2 若不存在 MyBookStoreConstants.SHOOPING_CART_KEY 属性, 创建一个购物车对象, 并把该对象放入 Session 中   
  17.   else{  
  18.    sc = new ShoppingCart ();  
  19.    session.setAttribute(MyBookStoreConstants.SHOOPING_CART_KEY, sc);  
  20.   }  
  21.     
  22.   return sc;  
  23.  }  
  24.    
  25.  public static  ShoppingCart getShppingCartForExist(HttpServletRequest request) {  
  26.   ShoppingCart sc = null;  
  27.   //2.1 检查在 HttpSession 对象中有没有购物车对象 , 即检查 session 中是否有 MyBookStoreConstants.SHOOPING_CART_KEY 属性  
  28.   //   若 已经存在, 说明购物车存在, 直接取出  
  29.   HttpSession session = null;  
  30.   session = request.getSession();  
  31.     
  32.   Object obj = session.getAttribute (MyBookStoreConstants.SHOOPING_CART_KEY);  
  33.     
  34.   if(obj != null) {  
  35.    sc = (ShoppingCart) obj;  
  36.   }  
  37.   //2.2 若不存在 MyBookStoreConstants.SHOOPING_CART_KEY 属性, 抛出异常, 提示用户还不存在购物车.  
  38.   else {  
  39.    throw new RuntimeException (MyBookStoreConstants.NO_SHOPPING_CART_EXCETPION);  
  40.   }   
  41.     
  42.   return sc;  
  43.  }  

(5)这里是所有与购物车相关的SERVLET.

这个是更新数据的,需要在SERVICE中调用DAO的!

  1. public class UpdateShoppingCartServlet extends HttpServlet {  
  2.  
  3.  public void doPost(HttpServletRequest request, HttpServletResponse response)   
  4.    throws ServletException, IOException {  
  5.   //获取表单信息   
  6.   // request.getParameter(""); 方法行不通, 因为表单的 name 是随时变化的   
  7.     
  8.   //获取表单中的所有 name  
  9.   Enumeration<String> nameEnums = request.getParameterNames();  
  10.     
  11.   Map items = new HashMap<String, Integer>();  
  12.   //遍历 nameEnums, 再取出对应的 Value, 封装到 items 中   
  13.     
  14.   try {  
  15.    while(nameEnums.hasMoreElements()) {  
  16.     String bookId = nameEnums.nextElement();  
  17.     String quantity = request.getParameter (bookId);  
  18.       
  19.     items.put(bookId, Integer.parseInt (quantity));  
  20.    }  
  21.   } catch (NumberFormatException e) {  
  22.    // TODO Auto-generated catch block  
  23.    e.printStackTrace ();  
  24.    throw new RuntimeException (MyBookStoreConstants.QUANTITY_FORMAT_EXCEPTION);  
  25.   }  
  26.     
  27.   //获 取购物车对象  
  28.   ShoppingCart sc = null;  
  29.   sc = MyBookStoreUtils.getShppingCartForExist(request);  
  30.     
  31.   //调用 Service 方法   
  32.   BookService bookService = new BookService ();  
  33.   bookService.updateShoppingCart(items, sc);  
  34.     
  35.   //派发页面 : showShoppingCart.jsp 页面  
  36.   String forwardPage = "/WEB- INF/jsp/showShoppingCart.jsp";  
  37.   request.getRequestDispatcher(forwardPage).forward (request, response);  
  38.  }  
  39.  
  40. }  
  41.  
  42. public class ShowShoppingCartServlet extends HttpServlet {  
  43.  
  44.  public void doGet(HttpServletRequest request, HttpServletResponse response)   
  45.    throws ServletException, IOException {  
  46.   //做一个转发   
  47.   String forwardPage = null;  
  48.     
  49.   forwardPage = "/WEB- INF/jsp/showShoppingCart.jsp";  
  50.     
  51.   RequestDispatcher dispatcher = null;  
  52.   dispatcher = request.getRequestDispatcher (forwardPage);  
  53.   dispatcher.forward(request, response);  
  54.  }  
  55.  
  56. }  
  57. public class ReceiptServlet extends HttpServlet {  
  58.  
  59.  public void doPost(HttpServletRequest request, HttpServletResponse response)   
  60.    throws ServletException, IOException {  
  61.   //1. 获取表单信息: name 和 cardId  
  62.     
  63.   //2. 调用 Service 方法, 更新 books 表各条 book 的 saleAmount 字段   
  64.     
  65.   //2.1 获取购物车  
  66.   ShoppingCart sc = MyBookStoreUtils.getShppingCartForExist(request);  
  67.     
  68.   BookService bookService = new BookService();  
  69.   bookService.buyBooks (sc);  
  70.     
  71.   //2.1 使 Session 失效  
  72.   HttpSession session = null;  
  73.   session = request.getSession();  
  74.   session.invalidate ();  
  75.     
  76.   //3. 派发页面: receipt.jsp 页面   
  77.   request.getRequestDispatcher("/WEB-INF/jsp/receipt.jsp").forward(request, response);   
  78.  }  

这段我先开始很纳闷老师为什么会这样写呢,其实很简单,写个专门的转发的SERVLET这样,在每次转发的时候就只连接一个servlet比连接多个更来的简洁!提高了效率!

  1. public class ForwardServlet extends HttpServlet {  
  2.  
  3.  public void doGet(HttpServletRequest request, HttpServletResponse response)   
  4.    throws ServletException, IOException {  
  5.   //1. 获取 path  
  6.   String path = request.getParameter("path");  
  7.     
  8.   //2. 派 发页面  
  9.   request.getRequestDispatcher(path).forward(request, response);  
  10.  }  
  11.  
  12. }  
  13. public class DeleteShoppingCartItemServlet extends HttpServlet {  
  14.  
  15.  public void doGet(HttpServletRequest request, HttpServletResponse response)   
  16.    throws ServletException, IOException {  
  17.   //1. 获取 id 号   
  18.   String id = request.getParameter("bookid");  
  19.     
  20.   //2. 调用 BookService 方法 deleteShoppingCartItemById:, 进行删除操作  
  21.   ShoppingCart sc = MyBookStoreUtils.getShppingCartForExist(request);  
  22.     
  23.   String bookTitle = sc.getBook(id).getTitle();  
  24.     
  25.   BookService bookService = new BookService ();  
  26.   bookService.deleteShoppingCartItemById(id, sc);  
  27.     
  28.   //3. 派发页面  
  29.   request.setAttribute(MyBookStoreConstants.DELETE_FROM_SHOPPING_CART_BOOK_TITLE, bookTitle);  
  30.     
  31.   String forwardPage = "/WEB- INF/jsp/showShoppingCart.jsp";  
  32.   //4. 判断购物车是否为空, 若为空则派发到 emptyCart.jsp 页面  
  33.   if(sc.getBooks().isEmpty())  
  34.    forwardPage = "/WEB- INF/jsp/emptyCart.jsp";  
  35.     
  36.   RequestDispatcher dispatcher = null;  
  37.   dispatcher = request.getRequestDispatcher (forwardPage);  
  38.   dispatcher.forward(request, response);  
  39.  }  
  40.  } 

这里是清空购物车的SERVLET.

  1. public class ClearShoppingCartServlet extends HttpServlet {  
  2.  
  3.  public void doGet(HttpServletRequest request, HttpServletResponse response)   
  4.    throws ServletException, IOException {  
  5.   //1. 调用方法   
  6.   BookService bookService = new BookService ();  
  7.     
  8.   ShoppingCart sc = null;  
  9.   sc = MyBookStoreUtils.getShppingCartForExist (request);  
  10.     
  11.   bookService.clearShoppingCart (sc);  
  12.     
  13.   //2. 派发页面  
  14.   String forwardPage = null;  
  15.   forwardPage = "/WEB- INF/jsp/emptyCart.jsp";  
  16.     
  17.   RequestDispatcher dispatcher = request.getRequestDispatcher(forwardPage);  
  18.   dispatcher.forward(request, response);  
  19.  }  
  20.  
  21. }  
  22. public class AddToShoppingCartServlet extends HttpServlet {  
  23.  
  24.  public void doGet(HttpServletRequest request, HttpServletResponse response)   
  25.    throws ServletException, IOException {  
  26.     
  27.     
  28.   //1. 获取书的 id 号  
  29.   String bookId = null;  
  30.   bookId = request.getParameter("bookId");  
  31.     
  32.   //2. 获取 购物车对象: 调用 getShppingCart 方法  
  33.   ShoppingCart sc = null;  
  34.   sc = MyBookStoreUtils.getShppingCartForCreateOrExist(request);  
  35.     
  36.   //3. 调用 Service 方法把 id 对应的 ShoppingCartItem 对象放入购物车 ShoppingCart 对象中: addToShoppingCart(id, shoppingCart);  
  37.   BookService bookService = null;  
  38.   bookService = new BookService();  
  39.     
  40.   bookService.addToShoppingCart(bookId, sc);  
  41.     
  42.   //4. 派发页面  
  43.   String forwardPage = "/index.jsp";  
  44.     
  45.   //4.1 获取书名  
  46.   String bookTitle = null;  
  47.   //bookTitle = sc.getBooks().get(bookId).getBook().getTitle ();  
  48.   bookTitle = sc.getBook(bookId).getTitle();  
  49.     
  50.   //4.2 将书 名放入请求域中, 以让页面进行显示  
  51.   request.setAttribute (MyBookStoreConstants.ADD_TO_SHOPPING_CART_BOOK_TITLE, bookTitle);  
  52.     
  53.   RequestDispatcher dispatcher = null;  
  54.   dispatcher = request.getRequestDispatcher (forwardPage);  
  55.   dispatcher.forward(request, response);  
  56.  }  
  57.  

(6)下面是显示层,对应着其相应的SERVLET.下面的JSP页面运用到了我们前段时间学的JSTL,EL表示.
'cashier.jsp'

  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"> 
  2.  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  4. <html> 
  5.   <head> 
  6.     <title>My JSP 'cashier.jsp' starting page</title> 
  7.   </head> 
  8.    
  9.   <body> 
  10.     <center> 
  11.      <br><br> 
  12.      您一共购买 了 ${sessionScope.shoppingcartkey.totalQuantity} 本书  
  13.      <br><br> 
  14.      您应付金额 是:${sessionScope.shoppingcartkey.totalPrice} 元。  
  15.      <br><br> 
  16.      <form action="receiptServlet" method="POST"> 
  17.       <table> 
  18.        <tr> 
  19.         <td>信用卡用户 名:</td> 
  20.         <td><input type="text" name="userName"/></td> 
  21.        </tr> 
  22.        <tr> 
  23.         <td>信用卡帐号:</td> 
  24.         <td><input type="text" name="cardId"/></td>          
  25.        </tr> 
  26.        <tr align="center"> 
  27.         <td colspan="2"> 
  28.          <input type="submit" value="递交 "/> 
  29.         </td> 
  30.        </tr> 
  31.       </table> 
  32.      </form> 
  33.     </center> 
  34.   </body> 
  35. </html> 
  36.  'receipt.jsp'  
  37. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
  38.  
  39. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  40. <html> 
  41.   <head> 
  42.     <title>My JSP 'emptyCart.jsp' starting page</title> 
  43.   </head> 
  44.    
  45.   <body> 
  46.     <center> 
  47.      <br><br> 
  48.      您的购物车 为空<br><br> 
  49.      <a href="${pageContext.request.contextPath }/index.jsp">继续购物<a> 
  50.     </center> 
  51.   </body> 
  52. </html> 
  53. <%@ page language="java" import="java.util.*" pageEncoding="UTF- 8"%> 
  54.  
  55. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  56. <html> 
  57.   <head> 
  58.     <title>My JSP 'receipt.jsp' starting page</title> 
  59.   </head> 
  60.    
  61.   <body> 
  62.     再见: ${param.userName }<br><br> 
  63.    <a href="${pageContext.request.contextPath }/index.jsp">继续购物</a>&nbsp;&nbsp;  
  64.   </body> 
  65. </html> 
  66.  
  67. 'showShoppingCart.jsp'  
  68. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"> 
  69. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
  70.  
  71. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  72. <html> 
  73.   <head> 
  74.     <title>My JSP 'showShoppingCart.jsp' starting page</title> 
  75.   </head> 
  76.    
  77.   <body> 
  78.     <center> 
  79.      <c:if test="${requestScope.deleteToShoppingCartBookTitle != null}"> 
  80.       <br><br> 
  81.        您已经把 ${requestScope.deleteToShoppingCartBookTitle} 从购物车中删除了!  
  82.      </c:if> 
  83.      <br><br> 
  84.        您的购物车中一共有 ${sessionScope.shoppingcartkey.totalQuantity} 本书  
  85.      <br><br> 
  86.      <form action="updateShoppingCartServlet" method="POST"> 
  87.       <table cellpadding="10" cellspacing="0"> 
  88.        <tr> 
  89.         <th>书名</th> 
  90.         <th>价 格</th> 
  91.         <th>数量 </th> 
  92.         <td></td> 
  93.        </tr> 
  94.        <c:forEach items="${sessionScope.shoppingcartkey.books}" var="sci"> 
  95.         <tr> 
  96.          <td>${sci.value.book.title }</td> 
  97.          <td>${sci.value.book.price }</td> 
  98.          <td><input type="text" value="${sci.value.quantity }" name="${sci.key }" size="2" /></td> 
  99.          <td><a href="${pageContext.request.contextPath }/deleteShoppingCartItemServlet?bookid=${sci.key }">删除 </a></td> 
  100.         <td></td> 
  101.        </tr> 
  102.        </c:forEach> 
  103.       </table> 
  104.       <input type="submit" value="保存修 改"> 
  105.      </form> 
  106.      <br> 
  107.      总价格: ${sessionScope.shoppingcartkey.totalPrice}   
  108.      <br><br> 
  109.      <a href="${pageContext.request.contextPath }/index.jsp">继续购物 </a>&nbsp;&nbsp;  
  110.      <a href="${pageContext.request.contextPath }/clearShoppingCartServlet">清空购物车 </a>&nbsp;&nbsp;  
  111.      <a href="${pageContext.request.contextPath }/forwardServlet?path=cashier.jsp">付账 </a> 
  112.     </center> 
  113.   </body> 
  114. </html> 

这样子简易JSP购物车算是完成了,当然这个JSP购物车只是简单的运用,没有涉及到大量的数据,作为入门的教学的例子是完全值得我们这些初学者消化的了!通过这次JSP购物车的联系,我对MVC的设计模式有了深刻的了解!不过其中的一些细节,还是需要我自己去慢慢的体会的!比如分页就是一个值得我去好好去研究的例子!

正文到此结束
Loading...