1.項(xiàng)目需求分析
javaWeb增強(qiáng):
過濾器、監(jiān)聽器、國際化、文件上傳與下載、JavaMail郵件開發(fā)
回顧項(xiàng)目開發(fā)設(shè)計(jì)模式之mvc模式:
M model 模型層 【entity/dao/service】
V view 視圖層 【jsp/html…】
C control 控制器 【servlet】

優(yōu)缺點(diǎn):
每一層各司其職! 更容易更換具體的實(shí)現(xiàn),而對(duì)其他層代碼影響較??!
目標(biāo):
1. 掌握mvc開發(fā)模式
2. 需求分析
《需求分析說明書.doc》
3. 設(shè)計(jì)數(shù)據(jù)庫
每一組用同一個(gè)數(shù)據(jù)庫。
4. 編碼
組長:分配任務(wù),每個(gè)人要做什么 (項(xiàng)目計(jì)劃)
項(xiàng)目開發(fā)生命周期
軟件項(xiàng)目開發(fā)模式:
螺旋開發(fā)模式
適合于項(xiàng)目前期部分需求不確定的情況, 對(duì)于每一個(gè)模塊一個(gè)個(gè)開發(fā):分析、設(shè)計(jì)、編碼、測試、上線;
好處: 降低軟件風(fēng)險(xiǎn)! (做出的產(chǎn)品要盡量滿足客戶需求!)
瀑布模式:
先進(jìn)行所有模塊的需求分析,當(dāng)分析結(jié)束后,才進(jìn)入項(xiàng)目下一個(gè)階段, 即設(shè)計(jì)、編碼、測試、上線;
好處: 更容易進(jìn)行項(xiàng)目把控,即項(xiàng)目質(zhì)量控制!
需求分析:
軟件工程師: 了解需求的途徑?
1. 需求文檔
2. 項(xiàng)目經(jīng)理
3. 項(xiàng)目的系統(tǒng)原型 (美工設(shè)計(jì)師)
4. 客戶
“餐館王”系統(tǒng)功能:
1. 餐桌模塊
2. 菜類別模塊(菜系)
3. 菜信息 (菜品)
4. 訂單
詳細(xì)分析:
1. 后臺(tái)錄入的餐桌, 要在前臺(tái)首頁顯示; 且只顯示未預(yù)定
2. 后臺(tái)錄入的菜類別, 在前臺(tái)主頁顯示
3. 后臺(tái)錄入的菜信息,在前臺(tái)主頁顯示
4. 前臺(tái)生成訂單后,在后臺(tái)顯示訂單詳細(xì)
2.數(shù)據(jù)庫設(shè)計(jì)
-- 創(chuàng)建數(shù)據(jù)庫
CREATE DATABASE hotel CHARACTER SET utf8;USE hotel;-- 1. 餐桌表CREATE TABLE dinnerTable( id INT PRIMARY KEY AUTO_INCREMENT, -- 餐桌主鍵 tableName VARCHAR(20), -- 餐桌名 tableStatus INT DEFAULT 0, -- 餐桌狀態(tài):0,空閑; 1,預(yù)定 orderDate DATETIME);-- 2.菜類別表CREATE TABLE foodType( id INT PRIMARY KEY AUTO_INCREMENT, -- 類別主鍵 typeName VARCHAR(20));-- 3. 菜品種表CREATE TABLE food( id INT PRIMARY KEY AUTO_INCREMENT, -- 主鍵 foodName VARCHAR(20), -- 菜名稱 foodType_id INT, -- 所屬菜系, 外鍵字段 price DOUBLE, -- 價(jià)格 mprice DOUBLE, -- 會(huì)員價(jià)格 remark VARCHAR(200), -- 簡介 img VARCHAR(100) -- 圖片);-- 4. 訂單表 (訂單基本信息)CREATE TABLE orders( id INT PRIMARY KEY AUTO_INCREMENT, -- 主鍵 table_id INT, -- 外鍵: 餐桌編號(hào) orderDate DATETIME, -- 下單日期 totalPrice DOUBLE, -- 訂單所有菜需要的總金額 orderStatus INT DEFAULT 0 -- 訂單狀態(tài): 0,未結(jié)賬; 1,已結(jié)賬);-- 5. 訂單明細(xì)表 (主要是菜品種)CREATE TABLE orderDetail( id INT PRIMARY KEY AUTO_INCREMENT, -- 主鍵 orderId INT, -- 外鍵:引入的是訂單表的主鍵 food_id INT, -- 外鍵:引用的是菜信息表的主鍵 foodCount INT -- 菜的數(shù)量 );-- 添加菜品與菜類別的關(guān)系約束ALTER TABLE food ADD CONSTRAINT fk_food_foodType_id FOREIGN KEY(foodType_id) REFERENCES foodType(id);-- 訂單表: 與餐桌表的關(guān)系A(chǔ)LTER TABLE orders ADD CONSTRAINT order_table_id FOREIGN KEY(table_id) REFERENCES dinnertable(id);-- 訂單明細(xì): 與訂單表的關(guān)系A(chǔ)LTER TABLE orderDetail ADD CONSTRAINT orderDetail_order_id FOREIGN KEY(orderId) REFERENCES orders(id);-- 訂單明細(xì): 與菜信息的關(guān)系A(chǔ)LTER TABLE orderDetail ADD CONSTRAINT orderDetail_food_id FOREIGN KEY(food_id) REFERENCES food(id);系統(tǒng)設(shè)計(jì)
開源組件及jar文件:
數(shù)據(jù)庫驅(qū)動(dòng)包(1個(gè))
C3P0連接池包(2 個(gè))
DbUtils組件 (1個(gè))
BeanUtils組件(2個(gè))
FileUpload組件(2個(gè))
配置
C3p0配置文件
分層:
Entity/dao/service/servlet
3.頁面顯示如圖
4.編碼如下package com.xp.utils;import javax.sql.DataSource;import org.apache.commons.dbutils.QueryRunner;import com.mchange.v2.c3p0.ComboPooledDataSource;/** * 封裝jdbc常用的操作 * @author xiongpan * 2017年2月16日 */public class JdbcUtils { // 初始化連接池 private static DataSource dataSource; static { dataSource = new ComboPooledDataSource(); } public static DataSource getDataSource() { return dataSource; } /** * 創(chuàng)建DbUtils常用工具類對(duì)象 */ public static QueryRunner getQuerrRunner() { return new QueryRunner(dataSource); }}<c3p0-config> <default-config> <property name="driverClass">com.MySQL.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///hotel</property> <property name="user">root</property> <property name="passWord">xiongpan</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> </default-config> <named-config name="OracleConfig"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///hotel</property> <property name="user">root</property> <property name="password">xiongpan</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> </named-config></c3p0-config>package com.xp.entity;/** * 1.菜系模塊,實(shí)體類設(shè)計(jì) * @author xiongpan * 2017年2月16日 */public class FoodType { private int id;//類別主鍵 private String typeName;//類別名稱 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; }}package com.xp.dao;import java.util.List;import com.xp.entity.FoodType;/** * 菜系模塊,dao接口設(shè)計(jì) * @author xiongpan */public interface IFoodTypeDao { /** * 添加 */ void save(FoodType foodType); /** * 更新 */ void update(FoodType foodType); /** * 刪除 */ void delete(int id); /** * 根據(jù)主鍵查詢 */ FoodType findById(int id); /** * 查詢?nèi)坎俗V */ List<FoodType> getAll(); /** * 按照菜系名稱查詢 */ List<FoodType> getAll(String typeName);}package com.xp.dao.impl;import java.util.List;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import com.xp.dao.IFoodTypeDao;import com.xp.entity.FoodType;import com.xp.utils.JdbcUtils;public class FoodTypeDao implements IFoodTypeDao { @Override public void delete(int id) { String sql = "delete from foodType where id=?"; try { JdbcUtils.getQuerrRunner().update(sql, id); } catch (Exception e) { throw new RuntimeException(e); } } @Override public FoodType findById(int id) { String sql = "select * from foodType where id=?"; try { return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<FoodType>(FoodType.class), id); } catch (Exception e) { throw new RuntimeException(e); } } @Override public List<FoodType> getAll() { String sql = "select * from foodType"; try { return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<FoodType>(FoodType.class)); } catch (Exception e) { throw new RuntimeException(e); } } @Override public List<FoodType> getAll(String typeName) { String sql = "select * from foodType where typeName like ?"; try { return JdbcUtils.getQuerrRunner() .query(sql, new BeanListHandler<FoodType>(FoodType.class),"%" + typeName + "%"); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void save(FoodType foodType) { String sql = "INSERT INTO foodType(typeName) VALUES(?);"; try { JdbcUtils.getQuerrRunner().update(sql,foodType.getTypeName()); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void update(FoodType foodType) { String sql = "update foodType set typeName=? where id=?"; try { JdbcUtils.getQuerrRunner().update(sql, foodType.getTypeName(),foodType.getId()); } catch (Exception e) { throw new RuntimeException(e); } }}package com.xp.service;import java.util.List;import com.xp.entity.FoodType;public interface IFoodTypeService { /** * 添加 */ void save(FoodType foodType); /** * 更新 */ void update(FoodType foodType); /** * 刪除 */ void delete(int id); /** * 根據(jù)主鍵查詢 */ FoodType findById(int id); /** * 查詢?nèi)? */ List<FoodType> getAll(); /** * 根據(jù)菜系名稱查詢 */ List<FoodType> getAll(String typeName);}package com.xp.factory;import java.util.ResourceBundle;/*** 工廠:創(chuàng)建dao或service實(shí)例*/public class BeanFactory { // 加載配置文件 private static ResourceBundle bundle; static { bundle = ResourceBundle.getBundle("instance"); } /** * 根據(jù)指定的key,讀取配置文件獲取類的全路徑; 創(chuàng)建對(duì)象 * @return */ public static <T> T getInstance(String key,Class<T> clazz) { String className = bundle.getString(key); try { return (T) Class.forName(className).newInstance(); } catch (Exception e) { throw new RuntimeException(e); } }}package com.xp.service.impl;import java.util.List;import com.xp.dao.IFoodTypeDao;import com.xp.entity.FoodType;import com.xp.factory.BeanFactory;import com.xp.service.IFoodTypeService;public class FoodTypeService implements IFoodTypeService { //private IFoodTypeDao foodTypeDao = new FoodTypeDao();// 對(duì)象的創(chuàng)建,不能寫死。 // 工廠創(chuàng)建對(duì)象 private IFoodTypeDao foodTypeDao = BeanFactory.getInstance("foodtypeDao", IFoodTypeDao.class); @Override public void save(FoodType foodType) { try { foodTypeDao.save(foodType); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void update(FoodType foodType) { try { foodTypeDao.update(foodType); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void delete(int id) { try { foodTypeDao.delete(id); } catch (Exception e) { throw new RuntimeException(e); } } @Override public FoodType findById(int id) { try { return foodTypeDao.findById(id); } catch (Exception e) { throw new RuntimeException(e); } } @Override public List<FoodType> getAll() { try { return foodTypeDao.getAll(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public List<FoodType> getAll(String typeName) { try { return foodTypeDao.getAll(typeName); } catch (Exception e) { throw new RuntimeException(e); } }}Instance.properties# dao instancefoodtypeDao = com.xp.dao.impl.FoodTypeDao# service instance foodTypeService =com.xp.service.impl.FoodTypeServicepackage com.xp.servlet;import java.io.IOException;import java.util.List;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.xp.entity.FoodType;import com.xp.factory.BeanFactory;import com.xp.service.IFoodTypeService;/** * 4. 菜系管理Servlet開發(fā) * a. 添加菜系 * b. 菜系列表展示 * c. 進(jìn)入更新頁面 * d. 刪除 * e. 更新 */public class FoodTypeServlet extends HttpServlet { private static final long serialVersionUID = 1L; // 調(diào)用的菜系Service private IFoodTypeService foodTypeService = BeanFactory.getInstance("foodTypeService",IFoodTypeService.class); // 跳轉(zhuǎn)資源 private Object uri; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 設(shè)置編碼 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 獲取操作的類型 String method = request.getParameter("method"); // 判斷 if ("addFoodType".equals(method)) { // 添加 addFoodType(request, response); } else if ("list".equals(method)) { // 列表展示 list(request, response); } else if ("viewUpdate".equals(method)) { // 進(jìn)入更新頁面 viewUpdate(request, response); } else if ("delete".equals(method)) { // 刪除 delete(request, response); } else if ("update".equals(method)) { // 更新 update(request, response); } } //a. 添加菜系 public void addFoodType(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 1. 獲取請(qǐng)求數(shù)據(jù)封裝 String foodTypeName = request.getParameter("foodTypeName"); FoodType ft = new FoodType(); ft.setTypeName(foodTypeName); // 2. 調(diào)用service處理業(yè)務(wù)邏輯 foodTypeService.save(ft); // 3. 跳轉(zhuǎn) uri = request.getRequestDispatcher("/foodType?method=list"); } catch (Exception e) { e.printStackTrace(); uri = "/error/error.jsp"; } goTo(request, response, uri); } //b. 菜系列表展示 public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 調(diào)用Service查詢所有的類別 List<FoodType> list = foodTypeService.getAll(); // 保存 request.setAttribute("listFoodType", list); // 跳轉(zhuǎn)的菜系列表頁面 uri = request.getRequestDispatcher("/sys/type/foodtype_list.jsp"); } catch (Exception e) { e.printStackTrace(); uri = "/error/error.jsp"; } // 跳轉(zhuǎn) goTo(request, response, uri); } //c. 進(jìn)入更新頁面 public void viewUpdate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 1. 獲取請(qǐng)求id String id = request.getParameter("id"); // 2. 根據(jù)id查詢對(duì)象 FoodType ft = foodTypeService.findById(Integer.parseInt(id)); // 3. 保存 request.setAttribute("foodType", ft); // 4. 跳轉(zhuǎn) uri = request.getRequestDispatcher("/sys/type/foodtype_update.jsp"); } catch (Exception e) { e.printStackTrace(); uri = "/error/error.jsp"; } goTo(request, response, uri); } //d. 刪除 public void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 1. 獲取請(qǐng)求id String id = request.getParameter("id"); // 2. 調(diào)用Service foodTypeService.delete(Integer.parseInt(id)); // 3. 跳轉(zhuǎn) uri = "/foodType?method=list"; } catch (Exception e) { e.printStackTrace(); uri = "/error/error.jsp"; } goTo(request, response, uri); } // e. 更新 public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //1. 獲取請(qǐng)求數(shù)據(jù)封裝 int id = Integer.parseInt(request.getParameter("id")); String name = request.getParameter("foodTypeName"); FoodType foodType = new FoodType(); foodType.setId(id); foodType.setTypeName(name); //2. 調(diào)用Service更新 foodTypeService.update(foodType); //3. 跳轉(zhuǎn) //list(request,response); uri = "/foodType?method=list"; } catch (Exception e) { e.printStackTrace(); uri = "/error/error.jsp"; } // 跳轉(zhuǎn) goTo(request, response, uri); } /** * 跳轉(zhuǎn)的通用方法 */ private void goTo(HttpServletRequest request, HttpServletResponse response, Object uri) throws ServletException, IOException { if (uri instanceof RequestDispatcher){ ((RequestDispatcher)uri).forward(request, response); } else if (uri instanceof String) { response.sendRedirect(request.getContextPath() + uri); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> <!-- 包含公共的JSP代碼片段 --><title>無線點(diǎn)餐平臺(tái)</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/Javascript" src="${pageContext.request.contextPath }/sys/style/js/jquery.js"></script><script type="text/javascript" src="${pageContext.request.contextPath }/sys/style/js/page_common.js"></script><link href="${pageContext.request.contextPath }/sys/style/CSS/common_style_blue.css" rel="stylesheet" type="text/css"><link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/sys/style/css/index_1.css" /></head><body> <!-- 頁面標(biāo)題 --> <div id="TitleArea"> <div id="TitleArea_Head"></div> <div id="TitleArea_Title"> <div id="TitleArea_Title_Content"> <img border="0" width="13" height="13" src="${pageContext.request.contextPath }/sys/style/images/title_arrow.gif" /> 菜系列表 </div> </div> <div id="TitleArea_End"></div> </div> <!-- 過濾條件 --> <div id="QueryArea"> <form action="/wirelessplatform/cuisine.html" method="get"> <input type="hidden" name="method" value="search"> <input type="text" name="keyword" title="請(qǐng)輸入菜系名稱"> <input type="submit" value="搜索"> </form> </div> <!-- 主內(nèi)容區(qū)域(數(shù)據(jù)列表或表單顯示) --> <div id="MainArea"> <table class="MainArea_Content" align="center" cellspacing="0" cellpadding="0"> <!-- 表頭--> <thead> <tr align="center" valign="middle" id="TableTitle"> <td>菜系編號(hào)</td> <td>菜系名稱</td> <td>操作</td> </tr> </thead> <!--顯示數(shù)據(jù)列表 --> <tbody id="TableData"> <c:choose> <c:when test="${not empty requestScope.listFoodType}"> <c:forEach var="foodType" items="${requestScope.listFoodType}"> <tr> <td>${foodType.id }</td> <td>${foodType.typeName }</td> <td> <a href="${pageContext.request.contextPath }/foodType?id=${foodType.id}&method=viewUpdate" class="FunctionButton">更新</a> <a href="${pageContext.request.contextPath }/foodType?id=${foodType.id}&method=delete" class="FunctionButton">刪除</a> </td> </tr> </c:forEach> </c:when> <c:otherwise> <tr> <td colspan="3">沒有你要找找的數(shù)據(jù),請(qǐng)先保存記錄再查看!</td> </tr> </c:otherwise> </c:choose> </tbody> </table> <!-- 其他功能超鏈接 --> <div id="TableTail" align="center"> <div class="FunctionButton"> <a href="${pageContext.request.contextPath }/sys/type/foodtype_save.jsp">添加</a> </div> </div> </div></body></html><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> <!-- 包含公共的JSP代碼片段 --><title>無線點(diǎn)餐平臺(tái)</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript" src="${pageContext.request.contextPath }/sys/style/js/jquery.js"></script><script type="text/javascript" src="${pageContext.request.contextPath }/sys/style/js/page_common.js"></script><link href="${pageContext.request.contextPath }/sys/style/css/common_style_blue.css" rel="stylesheet" type="text/css"><link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/sys/style/css/index_1.css" /></head><body><!-- 頁面標(biāo)題 --><div id="TitleArea"> <div id="TitleArea_Head"></div> <div id="TitleArea_Title"> <div id="TitleArea_Title_Content"> <img border="0" width="13" height="13" src="${pageContext.request.contextPath }/sys/style/images/title_arrow.gif"/> 添加菜系 </div> </div> <div id="TitleArea_End"></div></div><!-- 主內(nèi)容區(qū)域(數(shù)據(jù)列表或表單顯示) --><div id="MainArea"> <!-- 表單內(nèi)容 --> <form action="${pageContext.request.contextPath }/foodType?method=addFoodType" method="post"> <!-- 本段標(biāo)題(分段標(biāo)題) --> <div class="ItemBlock_Title"> <img width="4" height="7" border="0" src="${pageContext.request.contextPath }/sys/style/images/item_point.gif"> 菜系信息 </div> <!-- 本段表單字段 --> <div class="ItemBlockBorder"> <div class="ItemBlock"> <div class="ItemBlock2"> <table cellpadding="0" cellspacing="0" class="mainForm"> <tr> <td width="80px">菜系名稱</td> <td> <input type="text" name="foodTypeName" class="InputStyle" value=""/> * </td> </tr> </table> </div> </div> </div> <!-- 表單操作 --> <div id="InputDetailBar"> <input type="submit" value="添加" class="FunctionButtonInput"> <a href="javascript:history.go(-1);" class="FunctionButton">返回</a> </div> </form> </div></body></html><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> <!-- 包含公共的JSP代碼片段 --> <title>無線點(diǎn)餐平臺(tái)</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript" src="${pageContext.request.contextPath }/sys/style/js/jquery.js"></script><script type="text/javascript" src="${pageContext.request.contextPath }/sys/style/js/page_common.js"></script><link href="${pageContext.request.contextPath }/sys/style/css/common_style_blue.css" rel="stylesheet" type="text/css"><link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/sys/style/css/index_1.css" /></head><body><!-- 頁面標(biāo)題 --><div id="TitleArea"> <div id="TitleArea_Head"></div> <div id="TitleArea_Title"> <div id="TitleArea_Title_Content"> <img border="0" width="13" height="13" src="${pageContext.request.contextPath }/sys/style/images/title_arrow.gif"/> 更新菜系 </div> </div> <div id="TitleArea_End"></div></div><!-- 主內(nèi)容區(qū)域(數(shù)據(jù)列表或表單顯示) --><div id="MainArea"> <!-- 表單內(nèi)容 --> <form action="${pageContext.request.contextPath }/foodType?method=update" method="post"> <!-- 本段標(biāo)題(分段標(biāo)題) --> <div class="ItemBlock_Title"> <img width="4" height="7" border="0" src="${pageContext.request.contextPath }/sys/style/images/item_point.gif"> 菜系信息 </div> <!-- 本段表單字段 --> <div class="ItemBlockBorder"> <div class="ItemBlock"> <div class="ItemBlock2"> <table cellpadding="0" cellspacing="0" class="mainForm"> <tr> <td width="80px">菜系名稱</td> <td> <input type="text" name="foodTypeName" class="InputStyle" value="${foodType.typeName }"/> * <input type="hidden" name="id" value="${foodType.id }"/> </td> </tr> </table> </div> </div> </div> <!-- 表單操作 --> <div id="InputDetailBar"> <input type="submit" value="修改" class="FunctionButtonInput"> <a href="javascript:history.go(-1);" class="FunctionButton">返回</a> </div> </form></div></body></html>
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注