日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

超大数据量的xlsx格式的excel文件的读取和解析,解决了POI方式的内存溢出和性能问题

發布時間:2024/1/1 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 超大数据量的xlsx格式的excel文件的读取和解析,解决了POI方式的内存溢出和性能问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在之前的博文《 POI讀取并解析xlsx格式的excel文件》中,在小數據量的情況下是可以輕松愉快的處理的,但是當excel文件的數據量達到百萬級的時候,
  • InputStream?is?=?files[i].getInputStream();??
  • XSSFWorkbook?xssFWorkbook?=?new?XSSFWorkbook(is);?
  • 在02處直接就會內存溢出了。無論怎么搶救都沒用,看來得要換一條路走走了。

    在不停的Google查資料折騰了兩天之后,在POI官網成功的找到了解決方案。此處請允許我稍微吐槽一下POI,有瓶頸問題的解決方案卻隱藏的很深,只有一個不起眼的小鏈接,難道是怕大家都知道有點丟臉?

    總結一下該方案的主要原理:超大數據量的excel文件通過頁面上傳后(nginx的默認最大文件字節要調大一些:client_max_body_size ?xxxm),后臺接收到該文件的對象CommonsMultipartFile。首先獲取該文件對象的inputStream,然后用OPCPackage來打開該文件流,將excel在內存中轉化為xml格式卻不會出現內存溢出的問題,根據該xml的標簽就可以識別是格式,標題還是內容。然后在內存中通過POI框架中的XSSFSheetXMLHandler類中的sheetContentsHandler接口來根據上述的標簽來解析內容。可以將解析到的內容存入list或者map容器中便于后續的業務處理(純內容數據,幾百萬的數據量輕松勝任,親測不會內存溢出)。當然根據業務需要,需要復寫sheetContentsHandler接口的startRow,endRow,cell,headerFooter四大方法。

    當然了,筆者也親測了另一種方案:就是用OPCPackage來打開該文件流并且將excel在內存中轉化為xml格式之后,一股腦兒的用緩沖流分批的將所有原excel內容數據寫入到本地的txt文件,再去分批的readLine該文件中的數據,進行業務處理。該方案的好處是交易導入的文件可以物理的落地,作為后期查驗的依據和憑證。當然了,缺點是多了一次物理轉儲的過程,耗時會延長。如何選擇看個人的業務需求咯。

    本文中重點講述第一種方案吧,話不多說,貼代碼:

    /*** @return* @throws Exception* @author jason.gao* 功能描述:交易導入*/@RequestMapping(value = "/transDetail/upload", method = {RequestMethod.POST, RequestMethod.GET})@RequestGuard(perm = "transaction.import.upload")public ResponseEntity<ResponseEnvelope<RestApiResp>> uploadFile(@RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest req, HttpServletResponse resp) throws IOException {logger.info("uploadFile == >upload button start; fileName:[{}], CommonsMultipartFile[]:[{}]", files[0].getFileItem().getName(), files);long start = System.currentTimeMillis();String result = "完成交易文件的導入!";if (null == files || files.length != 1) {return RestApiResp.getSuccResponseEntity("必須上傳一個文件", null);}//重置buffer,在可能會超時的地方輸出resp的字節,避免前端ajax請求斷開!resp.setBufferSize(1);ServletOutputStream out = resp.getOutputStream();XlsxProcessAbstract xlsxProcess = new XlsxProcessAbstract();long getFileAndDataTime;ProcessTransDetailDataDto data;try {//獲取明細行累積的支付/退款的總金額/總筆數等數據的DTOdata = xlsxProcess.processAllSheet(files[0]);logger.info("匯總行的數據:[{}]", data.dtoToString());//獲取匯總行和明細行數據(包含標題)List<String> contentList = data.contentList;logger.info("明細行的數據條數為:[{}]", JSON.toJSONString(contentList.size() - 3));getFileAndDataTime = System.currentTimeMillis();logger.info("獲取文件并得到數據完成。耗時:[{}]秒", (getFileAndDataTime - start)/1000);//校驗匯總行數據正確性checkDetailSummary(contentList, data, out);logger.info("匯總行數據正確性的校驗已通過!");//分批調用OSP插入過程String handleResult = doOspHandle(contentList, data, out);if (!handleResult.equals(TransImportJobStatus.Success.getValue())) {result = TransImportJobStatus.getDescByKey(handleResult);logger.error(result);}} catch (CellDataException e) {logger.error("CellDataException: Error:[{}]", e);return RestApiResp.getSuccResponseEntity(e.getMessage(), null);} catch (OspException e) {logger.error("OspException:[{}]", e);return RestApiResp.getSuccResponseEntity(e.getMessage(), null);} catch (IOException e) {logger.error("IOException:[{}]", e);return RestApiResp.getSuccResponseEntity(e.getMessage(), null);} catch (Exception e) {logger.error("未知異常:[{}]", e);return RestApiResp.getSuccResponseEntity("未知異常,請排查日志:" + e.getMessage(), null);}long finishCheckAndInsertTime = System.currentTimeMillis();logger.info("完成數據校驗和數據分批插入。耗時:[{}]秒", (finishCheckAndInsertTime - getFileAndDataTime)/1000);logger.info("[{}],整個后臺處理過程共耗時:[{}]秒", result, (finishCheckAndInsertTime - start)/1000);return RestApiResp.getSuccResponseEntity(result, HttpStatus.OK);}

    上面代碼塊是整個后臺的主流程,注意的是要充分的捕捉異常,將異常信息呈獻給前端頁面和日志系統,便于生產故障時排查問題。

    接下來的四個代碼塊是對excel中字段的業務處理,屬于業務部分,不關心業務的可以忽略這些代碼片段

    public String doOspHandle (List<String> contentList, ProcessTransDetailDataDto data, ServletOutputStream out) throws CellDataException, OspException, IOException{// 獲取當前工作薄的明細行int start = 3;int size = 1000;String importStatus = "";//分批調用OSP接口執行插入while(start < contentList.size()) {importStatus = handleTransImport(contentList, start, size, data);if (!importStatus.equals(TransImportJobStatus.Success.getValue())) {logger.error("從第[{}]到[{}]行的數據,分批調用OSP接口失敗", start + 1, start + size + 1);return importStatus;}start += size;out.write(new String(" ").getBytes());out.flush();}//最終狀態:交易全部成功if (importStatus.equals(TransImportJobStatus.Success.getValue())){logger.info("調用“交易明細導入”的OSP接口成功!");TransDetailResp confirmResp;OspTransDetailServiceHelper.OspTransDetailServiceClient ospTransDetailServiceClient = new OspTransDetailServiceHelper.OspTransDetailServiceClient();logger.info("調用“確認交易明細成功”的OSP接口的請求參數:商戶號=[{}],結算單號=[{}],總條數=[{}]", data.getMerchantId(), data.getSettleOrderNo(), contentList.size()-3);try{confirmResp = ospTransDetailServiceClient.transDetailConfirm(data.getMerchantId(), data.getSettleOrderNo(), contentList.size()-3);} catch (OspException e) {logger.error("調用“確認交易明細成功”的OSP接口的拋出異常![{}]", e);throw e;} finally {out.write(new String("").getBytes());out.flush();}logger.info("調用“確認交易明細成功”的OSP接口的返回參數為:{}", JSON.toJSONString(confirmResp));if (!confirmResp.getResponseCode().equals(MessageEnum.SUCCESS.getValue())) {throw new OspException(TransImpFileExceptEnums.OspTransDetailConfirm.getValue(), TransImpFileExceptEnums.OspTransDetailConfirm.getDesc());}}return importStatus;}


    /*** 調用osp接口:執行交易明細的導入* 返回OSP操作完成的狀態*/public String handleTransImport(List<String> contentList, int start, int size, ProcessTransDetailDataDto data) throws CellDataException, OspException{//分批的調用osp接口:執行交易明細的導入OspTransDetailServiceHelper.OspTransDetailServiceClient ospTransDetailServiceClient = new OspTransDetailServiceHelper.OspTransDetailServiceClient();TransDetailResp transDetailResp;List<TransDetailImport> transDetailImportList = new ArrayList<>();//組織好一個list數據:讀取從start -> start+size行的數據for (int i = start; i < start + size && i < contentList.size(); i++) {TransDetailImport transDetailImport = new TransDetailImport();String[] detailRow = contentList.get(i).split("\\|@\\|");if (detailRow != null || !detailRow.equals("")) {try {transDetailImport.setMerchantId(data.getMerchantId());transDetailImport.setMerchantName(data.getMerchantName());transDetailImport.setMerchantBatchNo(data.getSettleOrderNo()); //商戶批次號transDetailImport.setMerchantBatchSerialNo(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[0], i, 0)); //商戶批次序號<來源:頁面導入模板中明細行的序號>模板必填transDetailImport.setMerchantOrderNo(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[1], i, 1)); //商戶訂單號:模板必填transDetailImport.setPlatformOrderNo(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[2], detailRow[1])); //平臺訂單號(支付退款訂單號):如果不送默認商戶訂單號transDetailImport.setMerchantTransDate(detailRow[4].equals("") ? new Date() : new Date(detailRow[4])); //商戶交易日期:如果不送默認上送日期transDetailImport.setTransType(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[5], TransTypeEnums.Payment.getValue())); //交易類型:如果不送默認支付transDetailImport.setOriginOrderNo(XssfCellValueCheckHelper.checkAndGetOriginOrderNo(detailRow[3], transDetailImport.getTransType(), i)); //原支付訂單號transDetailImport.setCurrency(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[6], "CNY")); //幣種:三位貨幣代碼,如果不送默認CNY:人民幣transDetailImport.setAmount(XssfCellValueCheckHelper.getAmount(detailRow[7], i)); //交易金額:外部交易上傳金額,內部商戶訂單金額transDetailImport.setCustomerName(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[9], i, 9)); //客戶名稱:模板必填transDetailImport.setIdType(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[10], i, 10)); //證件類型:模板必填transDetailImport.setCustomerType(XssfCellValueCheckHelper.checkAndGetCustomerType(detailRow, i, 8)); //客戶類型:根據證件類型確定transDetailImport.setIdNo(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[11], i, 11)); //證件號碼:模板必填transDetailImport.setMoneyType(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[12], MoneyTypeEnums.Currency.getValue())); //款項類型:默認:A 預付款項transDetailImport.setIsPayUnderBonded(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[13], IsPayUnderBondedEnums.YES.getValue())); //是否保稅貨物項下付款:默認:是transDetailImport.setTradingCode(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[14], TradingCodeEnums.GoodsTrade.getValue())); //交易編碼:交易編碼 默認:122030貨物貿易transDetailImport.setRmbAccount(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[15], "")); //人民幣賬號transDetailImport.setTrmo(XssfCellValueCheckHelper.getRealOrDefaultValue(detailRow[16], "一般貿易")); //交易附言:默認"一般貿易"transDetailImport.setProductDesc(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[17], i, 17)); //產品描述transDetailImport.setWaybillNum(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[18], i, 18)); //運單號transDetailImport.setProductNum(XssfCellValueCheckHelper.getStringNotEmpty(detailRow[19], i, 19).trim()); //銷售數量transDetailImport.setTransFrom("3"); //交易來源:1支付引擎、2門戶導入、3運營控制臺導入、4外部商戶導入} catch (Exception e) {logger.error("組裝數據時檢測到數據轉換異常,調用“交易明細刪除”的OSP接口,將未檢測到錯誤的已插入部分數據全部回滾掉,請求參數為:[{}],[{}],錯誤詳情:[{}]", data.getMerchantId(), data.getSettleOrderNo(), e);TransDetailResp delResp = ospTransDetailServiceClient.transDetailDel(data.getMerchantId(), data.getSettleOrderNo());if (!delResp.getResponseCode().equals(MessageEnum.SUCCESS.getValue())) {throw new OspException(TransImpFileExceptEnums.OspTransDetailDelRrror.getValue(), TransImpFileExceptEnums.OspTransDetailDelRrror.getDesc());}return TransImportJobStatus.InsetFailAndRollBack.getValue();}} else {throw new CellDataException(TransImpFileExceptEnums.EmptyHeadLine.getValue(), TransImpFileExceptEnums.EmptyHeadLine.getDesc());}transDetailImportList.add(transDetailImport);}logger.info("開始調用“導入交易明細”的OSP接口,從第[{}]行到第[{}]行的數據", start, (start + size) < contentList.size() ? (start + size) : contentList.size());try{transDetailResp = ospTransDetailServiceClient.transDetailImport(transDetailImportList);} catch (OspException e) {logger.error("調用“導入交易明細”的OSP接口的拋出異常![{}]", e);logger.info("調用“交易明細刪除”的OSP接口的請求參數為:[{}],[{}]", data.getMerchantId(), data.getSettleOrderNo());TransDetailResp delResp = ospTransDetailServiceClient.transDetailDel(data.getMerchantId(), data.getSettleOrderNo());if (!delResp.getResponseCode().equals(MessageEnum.SUCCESS.getValue())) {throw new OspException(TransImpFileExceptEnums.OspTransDetailDelRrror.getValue(), TransImpFileExceptEnums.OspTransDetailDelRrror.getDesc());}return TransImportJobStatus.InsetFailAndRollBack.getValue();}logger.info("調用“導入交易明細”的OSP接口的返回參數為:{}", JSON.toJSONString(transDetailResp));if (!transDetailResp.getResponseCode().equals(MessageEnum.SUCCESS.getValue())) {logger.info("調用“交易明細刪除”的OSP接口的請求參數為:[{}],[{}]", data.getMerchantId(), data.getSettleOrderNo());TransDetailResp delResp;try{delResp = ospTransDetailServiceClient.transDetailDel(data.getMerchantId(), data.getSettleOrderNo());} catch (OspException e) {logger.error("調用“交易明細刪除”的OSP接口的拋出異常![{}]", e);throw e;}logger.info("調用“交易明細刪除”的OSP接口的返回參數為:{}", JSON.toJSONString(delResp));if (!delResp.getResponseCode().equals(MessageEnum.SUCCESS.getValue())) {throw new OspException(TransImpFileExceptEnums.OspTransDetailDelRrror.getValue(), TransImpFileExceptEnums.OspTransDetailDelRrror.getDesc());}return TransImportJobStatus.InsetFailAndRollBack.getValue();}return TransImportJobStatus.Success.getValue();}
    /*** 校驗匯總行所有必填項*/public void checkHeadNotEmpty(ProcessTransDetailDataDto dataDto) throws CellDataException{if (dataDto.getMerchantId()==null || dataDto.getMerchantId().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(1).getDesc());}if (dataDto.getMerchantName()==null || dataDto.getMerchantName().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(2).getDesc());}if (dataDto.getSettleOrderNo()==null || dataDto.getSettleOrderNo().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(3).getDesc());}if (dataDto.getTotalPaymentCount() == null || dataDto.getTotalPaymentCount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(4).getDesc());}if (dataDto.getTotalPaymentAmount()==null || dataDto.getTotalPaymentAmount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(5).getDesc());}if (dataDto.getTotalRefundCount()==null || dataDto.getTotalRefundCount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(6).getDesc());}if (dataDto.getTotalRefundAmount()==null || dataDto.getTotalRefundAmount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(7).getDesc());}if (dataDto.getNetTotalCount()==null || dataDto.getNetTotalCount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(8).getDesc());}if (dataDto.getNetTotalAmount()==null || dataDto.getNetTotalAmount().equals("")) {throw new CellDataException(TransImpFileExceptEnums.HeadDataRrror.getValue(), TransImpFileExceptEnums.HeadDataRrror.setParams(9).getDesc());}}

    package com.vip.vpal.mgr.controller;import com.vip.vpal.mgr.enums.IdTypeCustomerTypeEnums; import com.vip.vpal.mgr.enums.TransImpFileExceptEnums; import com.vip.vpal.mgr.enums.TransTypeEnums; import com.vip.vpal.mgr.exception.CellDataException; import org.springframework.beans.factory.annotation.Autowired;/*** Created by jason.gao on 2017/8/11 0011.*/ public class XssfCellValueCheckHelper {public static String getStringNotEmpty(String cellValue, int row, int col) throws CellDataException {if (cellValue.equals("")) {throw new CellDataException(TransImpFileExceptEnums.EmptyFieldError.getValue(), TransImpFileExceptEnums.EmptyFieldError.setParams(row+1, col +1).getDesc());}return cellValue;}public static String getRealOrDefaultValue(String cellValue, String defVlaue) {if (cellValue.equals("")) {return defVlaue;}return cellValue;}/*** 校驗原支付訂單號在退款時必填* 返回原支付訂單號*/public static String checkAndGetOriginOrderNo(String cellValue, String transType, int row) throws CellDataException {if (transType.equals(TransTypeEnums.Refund.getValue()) && cellValue.equals("")) {throw new CellDataException(TransImpFileExceptEnums.EmptyFieldError.getValue(), TransImpFileExceptEnums.EmptyFieldError.setParams(row +1, 4).getDesc());}return cellValue; //原支付訂單號}/*** 校驗證件類型和客戶類型的關系一致性* 返回客戶類型的值*/public static String checkAndGetCustomerType(String[] cellRow, int row, int cell) throws CellDataException {//校驗證件類型是否正確String idType = cellRow[10];String customerTypeByDict = IdTypeCustomerTypeEnums.getDesc(idType);if (customerTypeByDict.equals("")) {throw new CellDataException(TransImpFileExceptEnums.DetailDateError.getValue(), TransImpFileExceptEnums.DetailDateError.setParams(row + 1, 11).getDesc());}//校驗客戶類型是否與證件類型相匹配String cusTomerType = cellRow[8]; //客戶類型,可不填,默認為證件類型對應的if (cusTomerType.equals("")) {return customerTypeByDict;}if (!customerTypeByDict.equals(cusTomerType)){throw new CellDataException(TransImpFileExceptEnums.DetailDateError.getValue(), TransImpFileExceptEnums.DetailDateError.setParams(row+1, 9).getDesc());}return cusTomerType;}public static long getAmount(String cellValue, int row) throws CellDataException {if (cellValue.equals("")) {throw new CellDataException(TransImpFileExceptEnums.EmptyFieldError.getValue(), TransImpFileExceptEnums.EmptyFieldError.setParams(row+1, 8).getDesc());}return (long) (new Double(cellValue) * 100);}}

    上面四個代碼塊是主流程對excel中字段的業務處理,其中調用OSP接口(一種rpc)的時候要注意,由于是分布式的遠程調用,所以不可以使用事物的失敗回滾方案,只能手動的捕捉異常并且手動的調用失敗的補償方法。

    下面注意了,是超大數據量的excel文件解析的核心代碼了:

    package com.vip.vpal.mgr.controller;import java.io.IOException; import java.io.InputStream;import javax.xml.parsers.ParserConfigurationException;import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable; import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler; import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFComment; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.SAXHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader;import com.vip.vpal.mgr.dto.ProcessTransDetailDataDto;/*** Excle xxls 批量讀取大文件操作類* */ public class XlsxProcessAbstract {private final Logger logger = LoggerFactory.getLogger(XlsxProcessAbstract.class);//開始讀取行數從第0行開始計算private int rowIndex = -1;private final int minColumns = 0;/*** Destination for data*/private final StringBuffer rowStrs = new StringBuffer();ProcessTransDetailDataDto processTransDetailData = new ProcessTransDetailDataDto();/*** 支持遍歷同一個excle文件下多個sheet的解析* excel記錄行操作方法,以行索引和行元素列表為參數,對一行元素進行操作,元素為String類型* @param filename* @return* @throws Exception*/public ProcessTransDetailDataDto processAllSheet(String filename) throws Exception {OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ);ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);XSSFReader xssfReader = new XSSFReader(pkg);StylesTable styles = xssfReader.getStylesTable();XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();InputStream stream = null;while (iter.hasNext()) {try {stream = iter.next();parserSheetXml(styles, strings, new SheetToCSV(), stream);} catch (Exception e) {logger.error("parserSheetXml error: ",e);} finally {stream.close();}}return processTransDetailData;}/*** 支持遍歷同一個excle文件下多個sheet的解析* excel記錄行操作方法,以行索引和行元素列表為參數,對一行元素進行操作,元素為String類型* @param xlsxFile* @return* @throws Exception* @author nevin.zhang*/public ProcessTransDetailDataDto processAllSheet(CommonsMultipartFile xlsxFile) throws Exception {OPCPackage pkg = OPCPackage.open(xlsxFile.getInputStream());ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);XSSFReader xssfReader = new XSSFReader(pkg);StylesTable styles = xssfReader.getStylesTable();XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();InputStream stream = null;while (iter.hasNext()) {try {stream = iter.next();parserSheetXml(styles, strings, new SheetToCSV(), stream);} catch (Exception e) {logger.error("parserSheetXml error: ",e);} finally {stream.close();}}return processTransDetailData;}/*** 解析excel 轉換成xml* * @param styles* @param strings* @param sheetHandler* @param sheetInputStream* @throws IOException* @throws SAXException*/public void parserSheetXml(StylesTable styles, ReadOnlySharedStringsTable strings, SheetContentsHandler sheetHandler, InputStream sheetInputStream) throws IOException, SAXException {DataFormatter formatter = new DataFormatter();InputSource sheetSource = new InputSource(sheetInputStream);try {XMLReader sheetParser = SAXHelper.newXMLReader();ContentHandler handler = new XSSFSheetXMLHandler(styles, null, strings, sheetHandler, formatter, false);sheetParser.setContentHandler(handler);sheetParser.parse(sheetSource);} catch (ParserConfigurationException e) {throw new RuntimeException("SAX parser appears to be broken - " + e);}}/*** 讀取excel行、列值* * @author nevin.zhang*/private class SheetToCSV implements SheetContentsHandler {private boolean firstCellOfRow = false;private int currentRowNumber = -1;private int currentColNumber = -1;/*** 處理cell中為空值的情況* @param number*/private void processCellBlankCells(int number) {for (int i = 0; i < number; i++) {for (int j = 0; j < minColumns; j++) {rowStrs.append("|@|");}rowStrs.append('\n');}}@Overridepublic void startRow(int rowNum) {processCellBlankCells(rowNum - currentRowNumber - 1);firstCellOfRow = true;currentRowNumber = rowNum;currentColNumber = -1;}@Overridepublic void endRow(int rowNum) {for (int i = currentColNumber; i < minColumns; i++) {rowStrs.append("|@|");}// 從設置的rowIndex的行數開始加入到list,前三行為標題,多個sheet都從第三行開始讀取的數據加入到listString endRowStrs=rowStrs.toString();if(currentRowNumber>rowIndex && !rowStrs.toString().equals("|@|")){processTransDetailData.contentList.add(endRowStrs);}if(!rowStrs.toString().equals("|@|")) {processTransDetailData.processTransTotalData(endRowStrs, currentRowNumber);}rowStrs.delete(0, rowStrs.length());// 清空buffer}@Overridepublic void cell(String cellReference, String cellValue, XSSFComment comment) {if (firstCellOfRow) {firstCellOfRow = false;} else {rowStrs.append("|@|");}if (cellReference == null) {cellReference = new CellAddress(currentRowNumber, currentColNumber).formatAsString();}int thisCol = (new CellReference(cellReference)).getCol();int missedCols = thisCol - currentColNumber - 1;for (int i = 0; i < missedCols; i++) {// excel中為空的值設置為“|@|”rowStrs.append("|@|");}currentColNumber = thisCol;rowStrs.append(cellValue);}@Overridepublic void headerFooter(String text, boolean isHeader, String tagName) {}} }


    由于導入的excel文件的格式是:第一行為匯總數據的標題,第二行為匯總數據,第三行為明細行的標題,其余行為明細數據,所以需要一個ProcessTransDetailDataDto實體類
    來封裝一下。

    package com.vip.vpal.mgr.dto;import com.vip.vpal.mgr.enums.TransTypeEnums; import org.apache.commons.lang.StringUtils;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;/*** 交易導入明細文件值處理*/ public class ProcessTransDetailDataDto{private String merchantId; //商戶號private String merchantName; //商戶名稱private String settleOrderNo; //批次號private String totalPaymentCount; // 支付總筆數private String totalPaymentAmount;// 支付總金額private String totalRefundAmount;// 退款總金額private String totalRefundCount; // 支付退款筆數private String netTotalAmount;// 凈金額匯總private String netTotalCount;// 凈筆數匯總private int currentRowNumber;private int paymentCount = 0;private BigDecimal paymentAmount = BigDecimal.ZERO;private int refundCount = 0;private BigDecimal refundAmount = BigDecimal.ZERO;private int paymentIndex = 0;private int refundIndex = 0;private int readRowTitleIndex = 1; //讀取標題匯總行private int readDetailRowIndex = 2;//讀取交易明細行public List<String> contentList = new ArrayList<>();public void processTransTotalData(String rowStrs, int currentRowNumber) {String[] cellStrs = rowStrs.split("\\|@\\|");// 讀取第二行匯總行if (currentRowNumber == readRowTitleIndex) {this.setMerchantId(cellStrs[0]);this.setMerchantName(cellStrs[1]);this.setSettleOrderNo(cellStrs[2]);this.setTotalPaymentCount(cellStrs[3]);this.setTotalPaymentAmount(cellStrs[4]);this.setTotalRefundCount(cellStrs[5]);this.setTotalRefundAmount(cellStrs[6]);this.setNetTotalCount(cellStrs[7]);this.setNetTotalAmount(cellStrs[8]);}// 讀取交易明細行if (currentRowNumber > readDetailRowIndex) {//原支付訂單號不為空則為支付交易if (cellStrs[5].toString().equals(TransTypeEnums.Refund.getValue())) {refundIndex++;this.setRefundCount(refundIndex);// 累積退款筆數this.setRefundAmount(this.getRefundAmount().add(stringToBigDecimal(cellStrs[7])));// 累積退款金額} else if (cellStrs[5].toString().equals("") || cellStrs[5].toString().equals(TransTypeEnums.Payment.getValue())){paymentIndex++;this.setPaymentCount(paymentIndex);this.setPaymentAmount(this.getPaymentAmount().add(stringToBigDecimal(cellStrs[7])));//累加支付金額}}}private static BigDecimal stringToBigDecimal(String str) {if (StringUtils.isBlank(str)) {return BigDecimal.ZERO;}BigDecimal bd = new BigDecimal(str);return bd;}public String dtoToString(){StringBuffer sb = new StringBuffer("");sb.append("商戶號="+ this.merchantId);sb.append(", 商戶名稱="+ this.merchantName);sb.append(", 批次號="+ this.settleOrderNo);sb.append(", 支付總筆數="+ this.totalPaymentCount);sb.append(", 支付總金額="+ this.totalPaymentAmount);sb.append(", 退款總金額="+ this.totalRefundAmount);sb.append(", 支付退款筆數="+ this.totalRefundCount);sb.append(", 凈金額匯總="+ this.netTotalAmount);sb.append(", 凈筆數匯總="+ this.netTotalCount);return sb.toString();}public String getMerchantId() {return merchantId;}public void setMerchantId(String merchantId) {this.merchantId = merchantId;}public String getMerchantName() {return merchantName;}public void setMerchantName(String merchantName) {this.merchantName = merchantName;}public String getSettleOrderNo() {return settleOrderNo;}public void setSettleOrderNo(String settleOrderNo) {this.settleOrderNo = settleOrderNo;}public String getTotalPaymentCount() {return totalPaymentCount;}public void setTotalPaymentCount(String totalPaymentCount) {this.totalPaymentCount = totalPaymentCount;}public String getTotalPaymentAmount() {return totalPaymentAmount;}public void setTotalPaymentAmount(String totalPaymentAmount) {this.totalPaymentAmount = totalPaymentAmount;}public String getTotalRefundAmount() {return totalRefundAmount;}public void setTotalRefundAmount(String totalRefundAmount) {this.totalRefundAmount = totalRefundAmount;}public String getTotalRefundCount() {return totalRefundCount;}public void setTotalRefundCount(String totalRefundCount) {this.totalRefundCount = totalRefundCount;}public String getNetTotalAmount() {return netTotalAmount;}public void setNetTotalAmount(String netTotalAmount) {this.netTotalAmount = netTotalAmount;}public String getNetTotalCount() {return netTotalCount;}public void setNetTotalCount(String netTotalCount) {this.netTotalCount = netTotalCount;}public int getCurrentRowNumber() {return currentRowNumber;}public void setCurrentRowNumber(int currentRowNumber) {this.currentRowNumber = currentRowNumber;}public int getPaymentCount() {return paymentCount;}public void setPaymentCount(int paymentCount) {this.paymentCount = paymentCount;}public BigDecimal getPaymentAmount() {return paymentAmount;}public void setPaymentAmount(BigDecimal paymentAmount) {this.paymentAmount = paymentAmount;}public int getRefundCount() {return refundCount;}public void setRefundCount(int refundCount) {this.refundCount = refundCount;}public BigDecimal getRefundAmount() {return refundAmount;}public void setRefundAmount(BigDecimal refundAmount) {this.refundAmount = refundAmount;}public List<String> getContentList() {return contentList;}public void setContentList(List<String> contentList) {this.contentList = contentList;}}
    上述代碼考慮到了原excel文件空行和空值的問題,做了處理。在開發的時候踩了一個坑:將空值的處理成“,”導致了其他數據帶逗號的時候,數據和列不匹配的問題,所以本文中就將逗號寫成了“ |@|”,盡量的避免偶然性。

    下面貼上依賴的POI的jar包中的最核心源碼,供各位參考:

    /* ====================================================================Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE file distributed withthis work for additional information regarding copyright ownership.The ASF licenses this file to You under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance withthe License. You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License. ==================================================================== */ package org.apache.poi.xssf.eventusermodel;import static org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML;import java.util.LinkedList; import java.util.Queue;import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFComment; import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler;/*** This class handles the processing of a sheet#.xml * sheet part of a XSSF .xlsx file, and generates* row and cell events for it.*/ public class XSSFSheetXMLHandler extends DefaultHandler {private static final POILogger logger = POILogFactory.getLogger(XSSFSheetXMLHandler.class);/*** These are the different kinds of cells we support.* We keep track of the current one between* the start and end.*/enum xssfDataType {BOOLEAN,ERROR,FORMULA,INLINE_STRING,SST_STRING,NUMBER,}/*** Table with the styles used for formatting*/private StylesTable stylesTable;/*** Table with cell comments*/private CommentsTable commentsTable;/*** Read only access to the shared strings table, for looking* up (most) string cell's contents*/private ReadOnlySharedStringsTable sharedStringsTable;/*** Where our text is going*/private final SheetContentsHandler output;// Set when V start element is seenprivate boolean vIsOpen;// Set when F start element is seenprivate boolean fIsOpen;// Set when an Inline String "is" is seenprivate boolean isIsOpen;// Set when a header/footer element is seenprivate boolean hfIsOpen;// Set when cell start element is seen;// used when cell close element is seen.private xssfDataType nextDataType;// Used to format numeric cell values.private short formatIndex;private String formatString;private final DataFormatter formatter;private int rowNum;private int nextRowNum; // some sheets do not have rowNums, Excel can read them so we should try to handle them correctly as wellprivate String cellRef;private boolean formulasNotResults;// Gathers characters as they are seen.private StringBuffer value = new StringBuffer();private StringBuffer formula = new StringBuffer();private StringBuffer headerFooter = new StringBuffer();private Queue<CellAddress> commentCellRefs;/*** Accepts objects needed while parsing.** @param styles Table of styles* @param strings Table of shared strings*/public XSSFSheetXMLHandler(StylesTable styles,CommentsTable comments,ReadOnlySharedStringsTable strings,SheetContentsHandler sheetContentsHandler,DataFormatter dataFormatter,boolean formulasNotResults) {this.stylesTable = styles;this.commentsTable = comments;this.sharedStringsTable = strings;this.output = sheetContentsHandler;this.formulasNotResults = formulasNotResults;this.nextDataType = xssfDataType.NUMBER;this.formatter = dataFormatter;init();}/*** Accepts objects needed while parsing.** @param styles Table of styles* @param strings Table of shared strings*/public XSSFSheetXMLHandler(StylesTable styles,ReadOnlySharedStringsTable strings,SheetContentsHandler sheetContentsHandler,DataFormatter dataFormatter,boolean formulasNotResults) {this(styles, null, strings, sheetContentsHandler, dataFormatter, formulasNotResults);}/*** Accepts objects needed while parsing.** @param styles Table of styles* @param strings Table of shared strings*/public XSSFSheetXMLHandler(StylesTable styles,ReadOnlySharedStringsTable strings,SheetContentsHandler sheetContentsHandler,boolean formulasNotResults) {this(styles, strings, sheetContentsHandler, new DataFormatter(), formulasNotResults);}private void init() {if (commentsTable != null) {commentCellRefs = new LinkedList<CellAddress>();for (CTComment comment : commentsTable.getCTComments().getCommentList().getCommentArray()) {commentCellRefs.add(new CellAddress(comment.getRef()));}} }private boolean isTextTag(String name) {if("v".equals(name)) {// Easy, normal v text tagreturn true;}if("inlineStr".equals(name)) {// Easy inline stringreturn true;}if("t".equals(name) && isIsOpen) {// Inline string <is><t>...</t></is> pairreturn true;}// It isn't a text tagreturn false;}@Override@SuppressWarnings("unused")public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {if (uri != null && ! uri.equals(NS_SPREADSHEETML)) {return;}if (isTextTag(localName)) {vIsOpen = true;// Clear contents cachevalue.setLength(0);} else if ("is".equals(localName)) {// Inline string outer tagisIsOpen = true;} else if ("f".equals(localName)) {// Clear contents cacheformula.setLength(0);// Mark us as being a formula if not alreadyif(nextDataType == xssfDataType.NUMBER) {nextDataType = xssfDataType.FORMULA;}// Decide where to get the formula string fromString type = attributes.getValue("t");if(type != null && type.equals("shared")) {// Is it the one that defines the shared, or uses it?String ref = attributes.getValue("ref");String si = attributes.getValue("si");if(ref != null) {// This one defines it// TODO Save it somewherefIsOpen = true;} else {// This one uses a shared formula// TODO Retrieve the shared formula and tweak it to // match the current cellif(formulasNotResults) {logger.log(POILogger.WARN, "shared formulas not yet supported!");} else {// It's a shared formula, so we can't get at the formula string yet// However, they don't care about the formula string, so that's ok!}}} else {fIsOpen = true;}}else if("oddHeader".equals(localName) || "evenHeader".equals(localName) ||"firstHeader".equals(localName) || "firstFooter".equals(localName) ||"oddFooter".equals(localName) || "evenFooter".equals(localName)) {hfIsOpen = true;// Clear contents cacheheaderFooter.setLength(0);}else if("row".equals(localName)) {String rowNumStr = attributes.getValue("r");if(rowNumStr != null) {rowNum = Integer.parseInt(rowNumStr) - 1;} else {rowNum = nextRowNum;}output.startRow(rowNum);}// c => cellelse if ("c".equals(localName)) {// Set up defaults.this.nextDataType = xssfDataType.NUMBER;this.formatIndex = -1;this.formatString = null;cellRef = attributes.getValue("r");String cellType = attributes.getValue("t");String cellStyleStr = attributes.getValue("s");if ("b".equals(cellType))nextDataType = xssfDataType.BOOLEAN;else if ("e".equals(cellType))nextDataType = xssfDataType.ERROR;else if ("inlineStr".equals(cellType))nextDataType = xssfDataType.INLINE_STRING;else if ("s".equals(cellType))nextDataType = xssfDataType.SST_STRING;else if ("str".equals(cellType))nextDataType = xssfDataType.FORMULA;else {// Number, but almost certainly with a special style or formatXSSFCellStyle style = null;if (stylesTable != null) {if (cellStyleStr != null) {int styleIndex = Integer.parseInt(cellStyleStr);style = stylesTable.getStyleAt(styleIndex);} else if (stylesTable.getNumCellStyles() > 0) {style = stylesTable.getStyleAt(0);}}if (style != null) {this.formatIndex = style.getDataFormat();this.formatString = style.getDataFormatString();if (this.formatString == null)this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);}}}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {if (uri != null && ! uri.equals(NS_SPREADSHEETML)) {return;}String thisStr = null;// v => contents of a cellif (isTextTag(localName)) {vIsOpen = false;// Process the value contents as required, now we have it allswitch (nextDataType) {case BOOLEAN:char first = value.charAt(0);thisStr = first == '0' ? "FALSE" : "TRUE";break;case ERROR:thisStr = "ERROR:" + value.toString();break;case FORMULA:if(formulasNotResults) {thisStr = formula.toString();} else {String fv = value.toString();if (this.formatString != null) {try {// Try to use the value as a formattable numberdouble d = Double.parseDouble(fv);thisStr = formatter.formatRawCellContents(d, this.formatIndex, this.formatString);} catch(NumberFormatException e) {// Formula is a String result not a Numeric onethisStr = fv;}} else {// No formating applied, just do raw value in all casesthisStr = fv;}}break;case INLINE_STRING:// TODO: Can these ever have formatting on them?XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());thisStr = rtsi.toString();break;case SST_STRING:String sstIndex = value.toString();try {int idx = Integer.parseInt(sstIndex);XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));thisStr = rtss.toString();}catch (NumberFormatException ex) {logger.log(POILogger.ERROR, "Failed to parse SST index '" + sstIndex, ex);}break;case NUMBER:String n = value.toString();if (this.formatString != null && n.length() > 0)thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);elsethisStr = n;break;default:thisStr = "(TODO: Unexpected type: " + nextDataType + ")";break;}// Do we have a comment for this cell?checkForEmptyCellComments(EmptyCellCommentsCheckType.CELL);XSSFComment comment = commentsTable != null ? commentsTable.findCellComment(new CellAddress(cellRef)) : null;// Outputoutput.cell(cellRef, thisStr, comment);} else if ("f".equals(localName)) {fIsOpen = false;} else if ("is".equals(localName)) {isIsOpen = false;} else if ("row".equals(localName)) {// Handle any "missing" cells which had comments attachedcheckForEmptyCellComments(EmptyCellCommentsCheckType.END_OF_ROW);// Finish up the rowoutput.endRow(rowNum);// some sheets do not have rowNum set in the XML, Excel can read them so we should try to read them as wellnextRowNum = rowNum + 1;} else if ("sheetData".equals(localName)) {// Handle any "missing" cells which had comments attachedcheckForEmptyCellComments(EmptyCellCommentsCheckType.END_OF_SHEET_DATA);}else if("oddHeader".equals(localName) || "evenHeader".equals(localName) ||"firstHeader".equals(localName)) {hfIsOpen = false;output.headerFooter(headerFooter.toString(), true, localName);}else if("oddFooter".equals(localName) || "evenFooter".equals(localName) ||"firstFooter".equals(localName)) {hfIsOpen = false;output.headerFooter(headerFooter.toString(), false, localName);}}/*** Captures characters only if a suitable element is open.* Originally was just "v"; extended for inlineStr also.*/@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {if (vIsOpen) {value.append(ch, start, length);}if (fIsOpen) {formula.append(ch, start, length);}if (hfIsOpen) {headerFooter.append(ch, start, length);}}/*** Do a check for, and output, comments in otherwise empty cells.*/private void checkForEmptyCellComments(EmptyCellCommentsCheckType type) {if (commentCellRefs != null && !commentCellRefs.isEmpty()) {// If we've reached the end of the sheet data, output any// comments we haven't yet already handledif (type == EmptyCellCommentsCheckType.END_OF_SHEET_DATA) {while (!commentCellRefs.isEmpty()) {outputEmptyCellComment(commentCellRefs.remove());}return;}// At the end of a row, handle any comments for "missing" rows before usif (this.cellRef == null) {if (type == EmptyCellCommentsCheckType.END_OF_ROW) {while (!commentCellRefs.isEmpty()) {if (commentCellRefs.peek().getRow() == rowNum) {outputEmptyCellComment(commentCellRefs.remove());} else {return;}}return;} else {throw new IllegalStateException("Cell ref should be null only if there are only empty cells in the row; rowNum: " + rowNum);}}CellAddress nextCommentCellRef;do {CellAddress cellRef = new CellAddress(this.cellRef);CellAddress peekCellRef = commentCellRefs.peek();if (type == EmptyCellCommentsCheckType.CELL && cellRef.equals(peekCellRef)) {// remove the comment cell ref from the list if we're about to handle it alongside the cell contentcommentCellRefs.remove();return;} else {// fill in any gaps if there are empty cells with comment mixed in with non-empty cellsint comparison = peekCellRef.compareTo(cellRef);if (comparison > 0 && type == EmptyCellCommentsCheckType.END_OF_ROW && peekCellRef.getRow() <= rowNum) {nextCommentCellRef = commentCellRefs.remove();outputEmptyCellComment(nextCommentCellRef);} else if (comparison < 0 && type == EmptyCellCommentsCheckType.CELL && peekCellRef.getRow() <= rowNum) {nextCommentCellRef = commentCellRefs.remove();outputEmptyCellComment(nextCommentCellRef);} else {nextCommentCellRef = null;}}} while (nextCommentCellRef != null && !commentCellRefs.isEmpty());}}/*** Output an empty-cell comment.*/private void outputEmptyCellComment(CellAddress cellRef) {XSSFComment comment = commentsTable.findCellComment(cellRef);output.cell(cellRef.formatAsString(), null, comment);}private enum EmptyCellCommentsCheckType {CELL,END_OF_ROW,END_OF_SHEET_DATA}/*** You need to implement this to handle the results* of the sheet parsing.*/public interface SheetContentsHandler {/** A row with the (zero based) row number has started */public void startRow(int rowNum);/** A row with the (zero based) row number has ended */public void endRow(int rowNum);/** * A cell, with the given formatted value (may be null), * and possibly a comment (may be null), was encountered */public void cell(String cellReference, String formattedValue, XSSFComment comment);/** A header or footer has been encountered */public void headerFooter(String text, boolean isHeader, String tagName);} }

    本文在性能測試時處理100W數據的excel文件的時候,“獲取前臺導入的文件并得到分類匯總的文件數據和明細的文件數據”只需要25秒,這一點上性能已經很高了,本系統中的性能瓶頸已經完美解決了。




    總結

    以上是生活随笔為你收集整理的超大数据量的xlsx格式的excel文件的读取和解析,解决了POI方式的内存溢出和性能问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    99久久精品免费看国产 | 精品字幕| 免费国产黄线在线观看视频 | 久久a v电影 | 国产高清av在线播放 | 国产色资源 | 日日操日日插 | 成人av免费播放 | 热久久精品在线 | 伊人伊成久久人综合网站 | 天天插天天色 | 99久热在线精品 | 日韩欧美在线观看一区 | 超碰97免费| 亚洲视频精品在线 | 97色在线视频 | 在线视频 区 | 国产无吗一区二区三区在线欢 | 干 操 插| 91xav | 亚洲欧美视屏 | 久草在线视频在线 | 日本精品一区二区在线观看 | 久久精品导航 | 国产一级不卡视频 | 97精品国产91久久久久久久 | 久久精品黄 | 亚洲精品www| 中文国产在线观看 | 免费高清看电视网站 | 国产乱码精品一区二区蜜臀 | 国产高清视频免费最新在线 | 97人人模人人爽人人喊网 | 国产一级91 | www.久久久.cum | 国产综合精品一区二区三区 | 香蕉视频免费看 | 黄色毛片在线 | 天天操天天舔天天干 | 伊人久久电影网 | 超碰97人人干 | 亚洲专区欧美 | 午夜资源站| 中文字幕中文字幕在线中文字幕三区 | 日韩一区二区免费播放 | 久久午夜精品视频 | 成人福利在线 | 天天人人综合 | 99久久久久成人国产免费 | 碰碰影院 | 中文字幕日本在线 | 日韩成人免费在线电影 | 日韩在线网址 | 国产精品2019 | 一区二区视频欧美 | www黄| 亚洲高清网站 | 国产精品一区二区三区视频免费 | 欧美日本不卡视频 | 成年人免费观看在线视频 | 麻豆91在线播放 | 国产精品久久久久毛片大屁完整版 | 成人在线电影观看 | 黄色综合 | 91热精品| 在线av资源 | 99精品国产99久久久久久福利 | 中文字幕免费高清 | 五月亚洲| 亚洲精品一区二区三区在线观看 | 久久99视频 | 日韩精品一区二区三区中文字幕 | 中文字幕亚洲国产 | 日本三级不卡视频 | 看片在线亚洲 | 欧美久久久久久 | 天堂视频一区 | 色综合久久网 | 91视频成人免费 | 国产精品v a免费视频 | 最新免费av在线 | 91看片淫黄大片一级在线观看 | 最近高清中文字幕在线国语5 | 国产精华国产精品 | 国产精品麻| 久久久久久毛片 | 免费看v片| 天天插天天爱 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 国产大陆亚洲精品国产 | 日韩美av在线 | 天天草天天干天天 | 一本大道久久精品懂色aⅴ 五月婷社区 | 久久国产欧美日韩精品 | 日韩精品免费在线观看 | 五月天婷婷在线播放 | 日韩欧美精品在线 | 91激情视频在线播放 | 国产精品 久久 | 国产日韩高清在线 | 日韩有码第一页 | 美女搞黄国产视频网站 | 国产在线中文字幕 | 国产伦精品一区二区三区高清 | 中文在线a√在线 | 首页av在线 | 国产涩涩在线观看 | 亚洲最大在线视频 | 一区二区 精品 | 日韩精品免费一区二区三区 | 天天天干夜夜夜操 | 97成人免费视频 | 黄色大片中国 | 人人爽人人爽人人爽 | 国产在线播放观看 | 日韩色在线观看 | 国产精品久99 | 国产婷婷色 | 亚洲精品视频播放 | av一级久久 | 婷婷亚洲综合五月天小说 | 欧美日韩18 | 日韩a在线看 | 久久综合色8888 | 久久综合影院 | 高清av免费一区中文字幕 | 成人四虎| 免费看国产一级片 | 久久久久久久久福利 | 久久福利国产 | 欧美激情精品久久久 | 国产系列 在线观看 | 日韩一区精品 | 国产99久久99热这里精品5 | 91福利在线观看 | 久久综合九色综合网站 | 在线免费观看视频你懂的 | 亚洲女人av| 亚洲精品视频在线观看网站 | 91精品在线免费 | 国产对白av | 日韩精品播放 | 日韩1页 | 国产群p | 欧美日韩一区二区免费在线观看 | 国产精品久久久久永久免费看 | 国产护士av | 色狠狠干 | 午夜视频色 | 狠狠五月婷婷 | 色播五月激情五月 | 超碰人人草 | 久久久久国产精品一区 | 在线观看视频国产一区 | 天天爽天天爽 | 日韩特黄av | 男女男视频 | a爱爱视频 | 日本最新一区二区三区 | 色婷婷丁香 | 国产中文自拍 | 91九色国产在线 | 天天射夜夜爽 | 视频在线观看日韩 | 欧美日韩在线观看不卡 | 伊人色播| 在线观看91 | 亚洲午夜精品久久久久久久久 | 亚洲日韩精品欧美一区二区 | 欧美成人91 | 在线成人免费 | 精品色综合 | 色婷婷激情电影 | 深爱激情婷婷网 | 中文在线免费一区三区 | 99综合电影在线视频 | 人人爱在线视频 | 91视频在线自拍 | 黄色一级大片在线观看 | 91av中文字幕 | 在线电影a| 五月天久久婷 | 99精品视频免费在线观看 | 精品久久久国产 | 69亚洲精品 | 亚洲一区二区视频 | 成人在线视频在线观看 | 久久久精品久久日韩一区综合 | 国产在线观看h | 久久精品日韩 | 亚洲国产精品久久 | 在线观看亚洲国产精品 | av动态图片| 精品亚洲免费视频 | 黄色一级网| 国产高清一级 | 日韩精品视频一二三 | 一区二区三区四区五区在线 | 中文av在线播放 | 夜色.com | 精品久久久久久久久久久久 | 国产精品男女视频 | 手机av在线网站 | 欧美另类成人 | 在线观看视频一区二区三区 | 久久一线| 欧美另类xxx | 欧洲一区二区三区精品 | 亚洲日本va在线观看 | 毛片精品免费在线观看 | 日韩在线免费电影 | 国产区精品在线 | 99热精品国产 | 国产精品久久久久久久午夜片 | 成年人在线观看网站 | 国产一级片免费视频 | av在线一级 | 精品久久一区 | 9i看片成人免费看片 | 婷婷色在线视频 | 福利片视频区 | 天天综合狠狠精品 | 黄污网站在线观看 | 十八岁以下禁止观看的1000个网站 | 欧美污网站 | 天天爽天天碰狠狠添 | 国产又黄又爽又猛视频日本 | 久久精彩免费视频 | 高清不卡一区二区在线 | 国产午夜激情视频 | 日本99干网| 久久久91精品国产一区二区三区 | 麻豆精品在线视频 | 国产一二三四在线观看视频 | 97人人澡人人添人人爽超碰 | 国产精品欧美久久久久无广告 | 在线精品在线 | 韩国一区二区三区在线观看 | 97精品国自产拍在线观看 | 日日夜夜精品免费视频 | 日韩中文字幕在线观看 | 亚洲高清91 | 最近中文字幕视频完整版 | 国产精品福利av | 色在线观看网站 | 一区二区中文字幕在线播放 | 成人h动漫在线看 | 91视频免费网站 | 国产中文字幕第一页 | 久久婷婷五月综合色丁香 | 最新免费中文字幕 | 日日夜夜噜| 欧美疯狂性受xxxxx另类 | 欧美一区二区三区免费观看 | 欧美日韩国产一二三区 | 色橹橹欧美在线观看视频高清 | 国产在线精品国自产拍影院 | 正在播放国产精品 | 久草在线观看 | 国产视频在线观看一区 | 香蕉免费 | 国内精品视频一区二区三区八戒 | 国产亚洲精品久久久久久移动网络 | 在线观看国产一区 | 九九久久婷婷 | 中文字幕国产 | 亚洲免费高清视频 | 91亚洲精品在线观看 | 亚色视频在线观看 | 香蕉视频4aa | 在线观看电影av | 国产小视频在线播放 | 亚洲成人国产精品 | 超碰在线97免费 | 日韩69av| 久久午夜精品影院一区 | 国产一区二区午夜 | 亚洲国产中文在线 | 国产一区二区精 | 在线国产精品一区 | 亚洲第一区在线观看 | 日韩高清在线观看 | 欧美精品v国产精品 | 亚洲精品中文字幕在线观看 | 日韩免费观看一区二区 | 国产亚洲精品久久久久久电影 | 九九免费精品视频 | 国产精品手机在线 | 在线视频 影院 | 综合网av | 91视频91自拍 | 黄色大片视频网站 | 国产在线看 | 91免费视频网站在线观看 | 久草免费新视频 | 日韩成人不卡 | 午夜美女福利直播 | 久久你懂的| 欧美日韩中文另类 | 麻豆视频成人 | 激情伊人五月天久久综合 | av片中文 | 奇米影视四色8888 | 国产精久久久久久久 | 久草在线手机观看 | 中文字幕免费观看 | 欧美激情精品久久久久久变态 | 欧美成人亚洲 | 国产精品一区二区三区电影 | 又色又爽又激情的59视频 | 久久免费99 | 免费视频三区 | 国内精品久久久久影院优 | 区一区二区三区中文字幕 | 亚洲免费av在线播放 | 国产视频久 | 成年人在线免费看视频 | av直接看 | 操夜夜操 | 99re亚洲国产精品 | 欧美日韩一区久久 | 久久综合久久伊人 | 久久在草 | 午夜视频在线观看一区二区三区 | 亚洲欧美日韩不卡 | 片黄色毛片黄色毛片 | 国产欧美久久久精品影院 | av大片网址 | 久久不卡av | 亚洲欧美日本国产 | 韩日电影在线观看 | 欧美日韩中文字幕综合视频 | 精品欧美日韩 | 日韩色在线 | 亚洲精品小视频 | 天天干天天碰 | 国产精品欧美激情在线观看 | 国产精品原创视频 | 欧美成人理伦片 | 免费看黄网站在线 | 狠狠插狠狠干 | 欧洲精品视频一区二区 | 人人人爽 | 狠狠躁夜夜av | 日韩有码专区 | 亚洲精品一区二区精华 | 日韩欧美aaa | 一区三区视频在线观看 | 久久久久伊人 | 久久伦理电影 | 久久精品播放 | 成人一区二区三区中文字幕 | 五月激情片 | 毛片无卡免费无播放器 | 国产v在线观看 | 免费一级毛毛片 | 日韩动漫免费观看高清完整版在线观看 | 国产色婷婷在线 | 丁香资源影视免费观看 | 黄色片网站 | 欧美成人手机版 | 又黄又爽又色无遮挡免费 | www.eeuss影院av撸 | 日本激情视频中文字幕 | 国产成人免费在线 | 国产美女精品人人做人人爽 | 婷婷综合影院 | 天堂av免费看 | 91污视频在线 | 一区二区中文字幕在线播放 | 久久香蕉电影 | 808电影 | 在线播放国产一区二区三区 | 日韩理论片在线 | 成人中文字幕在线 | 日韩r级在线 | 91污视频在线观看 | 国产精成人品免费观看 | 在线观看视频99 | 国产一性一爱一乱一交 | 日韩精品视频在线免费观看 | 国产精品1区2区在线观看 | 综合久久久久 | 欧美日韩免费观看一区二区三区 | 日韩免费电影 | 二区三区中文字幕 | 亚洲免费在线播放视频 | 日韩在线视频国产 | 最近日韩中文字幕中文 | 最新色站 | 人人要人人澡人人爽人人dvd | 国模精品一区二区三区 | 欧美在线一级片 | 中文字幕黄色 | 91一区二区三区在线观看 | 69视频在线 | 日韩av中文在线观看 | av亚洲产国偷v产偷v自拍小说 | 亚洲国产一二三 | 久久久久久久影视 | 国产精品美女免费视频 | 在线观看免费黄视频 | 97精品一区二区三区 | 天天做天天爱天天综合网 | 国产午夜精品一区二区三区 | 日韩色一区二区三区 | 国产精品理论在线观看 | 国产精品综合久久久久久 | 精品国产精品国产偷麻豆 | 国产99精品 | 四虎www.| 中文字幕av最新更新 | 亚洲美女精品视频 | 99 精品 在线 | 在线看片91| 国产亚洲成av片在线观看 | 亚洲一区二区高潮无套美女 | 中文字幕av有码 | 国产一级免费视频 | 婷婷精品视频 | 欧美一区日韩一区 | 91久久人澡人人添人人爽欧美 | 人人射人人爱 | 99超碰在线观看 | 国产精品九九久久99视频 | 国产v在线 | 中文字幕免费一区二区 | 国产精品视频在线观看 | 黄色在线免费观看网址 | 久久国产精品久久w女人spa | 91丨九色丨蝌蚪丨老版 | 久久精品亚洲精品国产欧美 | 亚洲日日射 | 9i看片成人免费看片 | 在线免费黄网站 | 国产精品热视频 | 色噜噜狠狠狠狠色综合 | 免费成人在线视频网站 | 黄色免费观看网址 | 亚洲视频在线免费看 | 午夜精品视频一区二区三区在线看 | 久草亚洲视频 | 在线播放国产一区二区三区 | 超碰免费成人 | 97精品国产97久久久久久久久久久久 | 成 人 黄 色 免费播放 | 黄色电影在线免费观看 | 夜夜躁日日躁狠狠躁 | 婷婷色中文网 | 久久美女精品 | 久久综合狠狠综合久久狠狠色综合 | 久久午夜电影 | 国产一区欧美日韩 | 狠狠狠狠狠狠狠狠 | 在线观看精品一区 | 五月天激情在线 | 综合国产视频 | 欧美人体xx| 麻豆91网站| 欧美一区二区三区四区夜夜大片 | 狠狠干综合| 精品美女久久久久久免费 | 亚洲国产精品一区二区久久hs | 欧美精品一区二区蜜臀亚洲 | 久久试看 | 欧美日韩免费在线观看视频 | 日夜夜精品视频 | 在线激情影院一区 | 国产色综合天天综合网 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 日韩精品一区二区免费 | 国产午夜小视频 | 欧美成人影音 | 日韩高清dvd | 久久综合五月 | 日韩精品视频免费看 | 99精品一级欧美片免费播放 | 精品9999 | 国产色影院 | 精品久久久免费视频 | www.玖玖玖 | 97国产情侣爱久久免费观看 | 久久久久久久免费观看 | 国产做爰视频 | 国产精品第54页 | 国产精品久免费的黄网站 | 日本黄色免费播放 | 久久精品国产一区二区 | 狠狠狠狠干 | 九月婷婷人人澡人人添人人爽 | 成人av影视 | 成在人线av| 国产区在线视频 | 成人午夜精品久久久久久久3d | 中文字幕在线免费看 | 国产私拍在线 | 欧美少妇xxxxxx | 久久9视频 | 中文字幕成人在线 | 久久精品视频在线免费观看 | 欧美aⅴ在线观看 | 久草网视频在线观看 | 国产免费观看视频 | 中文字幕日韩精品有码视频 | 日本中文乱码卡一卡二新区 | 免费在线观看一区 | 91在线文字幕 | 丁香六月婷婷开心 | 国产一线二线三线性视频 | 91成人破解版 | www.五月婷婷 | 99久久精品国产系列 | 在线成人高清电影 | 国产123区在线观看 国产精品麻豆91 | 精品久久99| 国产日韩欧美综合在线 | 亚洲精品免费在线观看 | 免费在线观看av的网站 | 最新中文字幕在线资源 | av不卡网站 | 日本在线视频一区二区三区 | 在线观看自拍 | 热re99久久精品国产66热 | 一区二区三区在线播放 | 中文字幕在线看视频国产中文版 | 天天天综合网 | 久久er99热精品一区二区 | 欧洲高潮三级做爰 | 综合伊人av | 色欧美成人精品a∨在线观看 | 99免费在线视频观看 | 狠狠ri| av在线播放国产 | 国产涩图 | 国产精品久久久久久久久久东京 | 丁香婷五月 | 伊人亚洲精品 | 日本中文字幕网 | 国产精品aⅴ | 2019中文字幕网站 | 久久精品影视 | 婷婷免费视频 | 在线看成人 | 九九视频网 | 国产九色在线播放九色 | 国产精品乱码久久久久久1区2区 | 久久久久久视频 | 国产网站在线免费观看 | 国产美女精品人人做人人爽 | 成人午夜剧场在线观看 | 一区二区三区在线观看免费 | 欧美最猛性xxxxx(亚洲精品) | 天天亚洲 | 五月婷影院 | 免费成人av电影 | 久久国产精品精品国产色婷婷 | 成人免费一区二区三区在线观看 | 日韩精品一区二区三区免费观看 | 天无日天天操天天干 | 欧美国产视频在线 | 色姑娘综合网 | 中文字幕中文字幕在线中文字幕三区 | 超碰97中文| 精品国产精品一区二区夜夜嗨 | 久久不见久久见免费影院 | 日本久久久影视 | 日韩三区在线 | 国产精品99久久久久久久久 | 看片网站黄色 | 国产在线中文字幕 | 在线99| 国产999精品久久久影片官网 | 国产 色 | 爱爱av网站 | 国产一二区精品 | 特级黄色视频毛片 | 毛片精品免费在线观看 | 国产xxxx做受性欧美88 | 99在线精品视频在线观看 | 97超视频在线观看 | 精品国产一区二区三区在线观看 | av免费在线免费观看 | 日韩一二三 | 99视频这里有精品 | 中文字幕亚洲综合久久五月天色无吗'' | 日韩精品免费在线观看视频 | 国产成人l区 | 国产精品久久久久久久久久久免费看 | 久久免费视频一区 | 亚洲综合成人专区片 | 九九爱免费视频 | 97国产人人| 亚洲午夜久久久久久久久 | 在线电影中文字幕 | 亚洲精品456在线播放乱码 | 欧美精品一区二区三区四区在线 | 亚洲一区二区视频在线 | 九九色在线 | 免费视频91蜜桃 | 一区二区三高清 | 亚洲欧洲一级 | 久久www免费视频 | 色五丁香| 国内精品在线看 | 久久免费试看 | 夜夜干夜夜 | 国产精品欧美一区二区三区不卡 | 欧美日韩一区二区在线 | 色网免费观看 | 亚洲国产中文字幕 | 国产亚洲日| 天堂在线v | 99国产精品一区二区 | 色综合久久久久综合 | 97电影在线 | 免费成人av网站 | 精品超碰 | 国产69精品久久99不卡的观看体验 | 亚洲高清av | 日韩特黄一级欧美毛片特黄 | 欧美地下肉体性派对 | 国内精品久久久久影院日本资源 | 成人在线免费看视频 | 欧美另类巨大 | 久久人人爽人人爽人人片av免费 | bbbbb女女女女女bbbbb国产 | 男女啪啪网站 | 国产午夜精品一区二区三区欧美 | 正在播放五月婷婷狠狠干 | 91高清免费在线观看 | 999久久久| 久久久久久看片 | 99re中文字幕 | 国产高清不卡av | 91视频91色 | 天天操天天弄 | 亚洲视频在线看 | 一区久久久 | 久久国产精品久久精品国产演员表 | 久草免费在线视频 | 香蕉视频在线视频 | 99久久久国产精品 | 国产拍在线 | 在线黄色国产 | 久久精品国产久精国产 | 国产中文字幕视频 | 天天操网址 | 玖玖视频 | 国产精品初高中精品久久 | 天天操比 | 日韩精品中字 | 国产精品黄色影片导航在线观看 | 亚洲影院国产 | 久久电影网站中文字幕 | 国产精品美女免费视频 | 激情深爱.com | 国产一二三四在线观看视频 | 国产精品毛片久久久久久 | 日韩久久精品一区 | 国产亚洲成av人片在线观看桃 | 草久草久| 激情五月婷婷综合 | 久久综合加勒比 | 永久免费观看视频 | av888av.com| 亚洲春色综合另类校园电影 | 欧美va在线观看 | 日韩一区精品 | 毛片视频电影 | 午夜精品视频在线 | 综合视频在线 | 日本性生活一级片 | 久久精品牌麻豆国产大山 | 国产成人精品一区二区三区 | 国产精品18毛片一区二区 | 久久综合亚洲鲁鲁五月久久 | 色综合天天综合网国产成人网 | 国产成人精品免高潮在线观看 | 伊人色播 | 国产精品破处视频 | 青青河边草观看完整版高清 | 操少妇视频 | 伊人国产在线观看 | 欧美三级高清 | 中文免费在线观看 | 在线亚洲欧美日韩 | 婷五月天激情 | 国产日韩av在线 | 日韩欧美视频免费看 | 99精彩视频在线观看免费 | 亚洲最新在线视频 | 四虎国产精品成人免费4hu | 亚洲成人资源在线观看 | 黄色三级av | 男女免费视频观看 | 国产最顶级的黄色片在线免费观看 | 亚洲va欧美va | 一二三区高清 | 中文字幕无吗 | 美女福利视频 | 天天鲁一鲁摸一摸爽一爽 | 精品国产福利在线 | 日本黄色大片儿 | 久久久久国产精品免费免费搜索 | 曰本三级在线 | 国产亚洲视频在线免费观看 | 久久久国产在线视频 | 在线观看电影av | 97日日碰人人模人人澡分享吧 | 久久久69| 国产欧美精品一区二区三区 | 手机av电影在线观看 | 色综合久久天天 | 日韩色av色资源 | 久久久亚洲网站 | 日日爱影视 | 国产精品h在线观看 | 91豆花在线 | 免费在线观看污 | 国产无遮挡又黄又爽馒头漫画 | 亚洲精品视频一 | 热久久免费国产视频 | 久久成人精品电影 | 久草视频看看 | 日本精品视频在线 | 成人黄色小说网 | 久久综合婷婷综合 | 日韩高清一二区 | 日日麻批40分钟视频免费观看 | 欧美极度另类 | 国产又粗又猛又色 | 久久九九影视网 | 中文字幕色综合网 | 日韩视频在线不卡 | 久久夜夜操| 狠狠躁日日躁 | 国产麻豆精品免费视频 | 免费视频区 | 亚洲欧美日本一区二区三区 | av在线电影网站 | 日韩高清免费无专码区 | 激情五月婷婷综合 | 亚洲视频 视频在线 | 久久久免费国产 | 精品在线观看一区二区三区 | 粉嫩aⅴ一区二区三区 | 国产麻豆精品传媒av国产下载 | 国产精品1区2区在线观看 | 国产成人99久久亚洲综合精品 | 免费h视频| 欧美精品在线视频 | 国产色网 | 国产在线欧美日韩 | 九九视频免费观看视频精品 | 国产剧情在线一区 | 黄色电影网站在线观看 | 99爱视频 | 国产福利在线免费观看 | 免费在线观看av片 | 欧美极品久久 | 中文字幕在线播放一区 | 亚洲区另类春色综合小说 | 天天干夜夜 | 日本二区三区在线 | 日韩视频免费在线观看 | 欧美激情精品久久久 | 色综合天天综合在线视频 | 麻豆传媒视频观看 | 手机成人免费视频 | 精品无人国产偷自产在线 | 精品日韩在线一区 | 亚洲国产精品500在线观看 | 中文字幕第一页av | 国产xxxx性hd极品 | 韩国一区二区av | 激情五月婷婷综合网 | 夜夜视频欧洲 | 免费在线观看视频一区 | 黄污污网站| 天天玩天天干 | 91日韩在线播放 | 久久久黄色av | www.久久色 | 波多野结衣电影一区 | 一本一本久久a久久精品牛牛影视 | 日韩国产欧美在线视频 | 日韩高清国产精品 | 特黄色大片 | 天堂在线免费视频 | 免费看污黄网站 | 欧美日韩在线精品 | 久久久黄视频 | 久久午夜精品 | 国产精品96久久久久久吹潮 | 97超碰国产在线 | 在线观看日韩一区 | 黄色大片免费网站 | 国产男女爽爽爽免费视频 | 日韩专区在线播放 | 91网站在线视频 | 69视频永久免费观看 | 在线成人看片 | 在线视频 亚洲 | av免费观看在线 | 日韩亚洲国产中文字幕 | 91av视频免费观看 | 婷婷婷国产在线视频 | 欧美巨乳波霸 | 久操视频在线播放 | www久久久| 国产精品99精品久久免费 | 美女视频黄免费 | 中文亚洲欧美日韩 | 亚洲在线视频播放 | 麻豆手机在线 | 国产视频精品免费 | 成年人在线免费视频观看 | 久热av在线 | 国产麻豆视频 | 国产毛片久久 | 久久99精品久久久久久三级 | 久久久综合精品 | 亚洲爱爱视频 | 欧美日韩在线精品一区二区 | 91网站在线视频 | 亚洲综合在线五月天 | 久久九九久久 | 免费亚洲视频 | 97看片网 | 免费看v片网站 | 欧洲激情综合 | 国产高清在线看 | 午夜男人影院 | 亚洲国产高清在线观看视频 | 伊人精品影院 | 五月天久久综合 | 中文字幕在线免费看 | 亚洲a成人v | 91精品国自产在线偷拍蜜桃 | 精品一区二区三区久久 | 在线草 | 国产一区二区网址 | 精品视频一区在线观看 | 在线日韩亚洲 | 五月天精品视频 | 波多野结衣视频一区二区三区 | 激情 一区二区 | 国内毛片毛片 | 成人av一区二区三区 | 岛国av在线不卡 | 亚洲精品免费在线观看视频 | 久久精品老司机 | 日韩精品欧美一区 | 在线播放国产一区二区三区 | av亚洲产国偷v产偷v自拍小说 | 亚洲精品美女久久久久 | 亚洲一区二区三区精品在线观看 | 免费一级片视频 | 国产黄色成人 | 天天摸夜夜添 | 国产精品video爽爽爽爽 | 免费视频xnxx com | 福利视频网址 | 国产99在线 | 亚洲高清av在线 | 丁香五香天综合情 | 日韩av一区二区三区四区 | 精品国产aⅴ麻豆 | 美女性爽视频国产免费app | 色夜影院 | 欧美在线观看视频免费 | 91在线porny国产在线看 | av亚洲产国偷v产偷v自拍小说 | 精品久久久久久久久久久久久久久久 | 久草在线观看视频免费 | 国产日本在线观看 | 伊人久久国产 | 日日操网站 | 91女子私密保健养生少妇 | 成年人在线免费看视频 | 亚洲激情综合网 | 五月天视频网 | 日本精品久久久一区二区三区 | 蜜桃传媒一区二区 | 综合国产在线 | 久久热首页| 日韩精品一区二区在线 | 国产精品原创av片国产免费 | 在线免费观看欧美日韩 | 亚洲精品在线看 | 国产资源在线免费观看 | 日本精品va在线观看 | 久久在线精品视频 | 91精品视频一区二区三区 | 日韩av片在线 | 在线免费av电影 | 狠狠操狠狠干天天操 | 九九九在线观看视频 | av免费高清观看 | 成人av免费在线观看 | 97电影在线观看 | 日本aaaa级毛片在线看 | 日韩av播放在线 | 精品国产一区二区三区噜噜噜 | 成人午夜av电影 | 日韩中文字幕网站 | 88av色 | 免费亚洲黄色 | 中文字幕人成一区 | 久久综合狠狠狠色97 | 草久在线观看视频 | 九九久 | 亚洲一区av | 天天爱天天射 | 成年人免费电影 | 91亚洲精品乱码久久久久久蜜桃 | 久久精品免费看 | 精品久久国产一区 | 欧美在线一级片 | 婷五月天激情 | 美女久久久久久久 | 国产精品2020 | www.久草.com | 日韩av中文字幕在线 | 青春草免费在线视频 | 久久黄色影视 | 日日干日日操 | 视频在线一区 | 中文字幕在线有码 | 国产美女精品视频 | 国产在线一区观看 | 91伊人久久大香线蕉蜜芽人口 | 中文字幕在线播放第一页 | 在线免费91 | 97成人精品区在线播放 | 在线观看中文字幕2021 | 日本一区二区高清不卡 | 午夜精品久久久久久久99水蜜桃 | 中文字幕最新精品 | 国产福利在线免费观看 | mm1313亚洲精品国产 | 五月天久久久 | 精品福利在线 | 麻豆精品传媒视频 | 国产一级淫片免费看 | 国产精品毛片一区二区在线看 | 成人在线视频在线观看 | 亚洲aⅴ一区二区三区 | 色一色在线| 悠悠av资源片| 国产v欧美 | 又污又黄的网站 | 精品国产一区二区三区久久久蜜月 | 午夜三级大片 | 亚洲精品视频偷拍 | 亚洲综合在线五月天 | 久久精品美女视频 | 国产成人av网址 | 久久国产热视频 | 美女久久一区 | 91.dizhi永久地址最新 | 日韩av影视 | 日本中文字幕在线电影 | 天天爽天天搞 | a色网站 | 一区二区三区免费播放 | 美女一二三区 | 在线观看韩国av | 亚洲在线 | 亚洲精品99久久久久中文字幕 | 国产精品久久久久久久久久ktv | 国产精品久久久久久久久久久免费 | 亚洲精品视频免费在线 | 欧美精品中文在线免费观看 | 免费网站看av片 | 国产午夜精品免费一区二区三区视频 | 亚洲男人天堂2018 | 黄色精品国产 | 国产小视频网站 | 超碰在线cao | 91亚色视频在线观看 | av免费看网站 | 黄色小网站免费看 | 免费高清国产 | 麻豆91视频 | 色欧美视频 | 国产最顶级的黄色片在线免费观看 | 国产一级视屏 | 超碰个人在线 | 午夜影院一级片 | 日韩av电影国产 | 日韩av电影中文字幕在线观看 | 国产真实精品久久二三区 | 久久成人一区 | 国产精品久久99综合免费观看尤物 | 国产精品国产亚洲精品看不卡15 | 亚洲成a人片77777kkkk1在线观看 | 狠狠操狠狠干2017 |