成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

第三十章:SpringBoot使用MapStruct自動(dòng)映射DTO

weakish / 1668人閱讀

摘要:商品類型實(shí)體恒宇少年碼云商品基本信息實(shí)體恒宇少年碼云接下來(lái)我們繼續(xù)創(chuàng)建相關(guān)的。注解是用于標(biāo)注接口抽象類是被自動(dòng)映射的標(biāo)識(shí),只有存在該注解才會(huì)將內(nèi)部的接口方法自動(dòng)實(shí)現(xiàn)。

MapStruct是一種類型安全的bean映射類生成java注釋處理器。
我們要做的就是定義一個(gè)映射器接口,聲明任何必需的映射方法。在編譯的過(guò)程中,MapStruct會(huì)生成此接口的實(shí)現(xiàn)。該實(shí)現(xiàn)使用純java方法調(diào)用的源和目標(biāo)對(duì)象之間的映射,MapStruct節(jié)省了時(shí)間,通過(guò)生成代碼完成繁瑣和容易出錯(cuò)的代碼邏輯。下面我們來(lái)揭開它的神秘面紗

本章目標(biāo)

基于SpringBoot平臺(tái)完成MapStruct映射框架的集成。

構(gòu)建項(xiàng)目

我們使用idea開發(fā)工具創(chuàng)建一個(gè)SpringBoot項(xiàng)目,添加相應(yīng)的依賴,pom.xml配置文件如下所示:

...省略部分代碼

        org.springframework.boot
        spring-boot-starter-parent
        1.5.6.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
        1.2.0.CR1
    

    
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            mysql
            mysql-connector-java
            runtime
        
        
            org.springframework.boot
            spring-boot-starter-tomcat
            
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            org.mapstruct
            mapstruct-jdk8
            ${org.mapstruct.version}
        
        
            org.mapstruct
            mapstruct-processor
            ${org.mapstruct.version}
            provided
        
        
            javax.inject
            javax.inject
            1
        
        
        
            com.alibaba
            druid
            1.0.31
        
        
            org.projectlombok
            lombok
        
    
....省略部分代碼

集成MapStruct官方提供了兩種方式,上面配置文件內(nèi)我們采用的是直接添加Maven依賴,而官方文檔還提供了另外一種方式,采用Maven插件形式配置,配置如下所示:

...引用官方文檔
...

    1.2.0.CR1

...

    
        org.mapstruct
        mapstruct-jdk8
        ${org.mapstruct.version}
    

...

    
        
            org.apache.maven.plugins
            maven-compiler-plugin
            3.5.1
            
                1.8
                1.8
                
                    
                        org.mapstruct
                        mapstruct-processor
                        ${org.mapstruct.version}
                    
                
            
        
    

...

我個(gè)人比較喜歡采用第一種方式,不需要配置過(guò)多的插件,依賴方式比較方便。
接下來(lái)我們開始配置下數(shù)據(jù)庫(kù)連接信息以及簡(jiǎn)單的兩張表的SpringDataJPA相關(guān)接口。

數(shù)據(jù)庫(kù)連接信息

在resource下新創(chuàng)建一個(gè)application.yml文件,并添加如下數(shù)據(jù)庫(kù)連接配置:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
    username: root
    password: 123456
    #最大活躍數(shù)
    maxActive: 20
    #初始化數(shù)量
    initialSize: 1
    #最大連接等待超時(shí)時(shí)間
    maxWait: 60000
    #打開PSCache,并且指定每個(gè)連接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #通過(guò)connectionProperties屬性來(lái)打開mergeSql功能;慢SQL記錄
    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql將無(wú)法統(tǒng)計(jì),"wall"用于防火墻
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true

有關(guān)SpringDataJPA相關(guān)的學(xué)習(xí)請(qǐng)?jiān)L問第三章:SpringBoot使用SpringDataJPA完成CRUD,我們?cè)跀?shù)據(jù)庫(kù)內(nèi)創(chuàng)建兩張表信息分別是商品基本信息表、商品類型表。
兩張表有相應(yīng)的關(guān)聯(lián),我們?cè)诓徊捎眠B接查詢的方式模擬使用MapStruct,表信息如下所示:

--商品類型信息表
CREATE TABLE `good_types` (
  `tgt_id` int(11) NOT NULL AUTO_INCREMENT,
  `tgt_name` varchar(30) DEFAULT NULL,
  `tgt_is_show` int(1) DEFAULT NULL,
  `tgt_order` int(255) DEFAULT NULL,
  PRIMARY KEY (`tgt_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

--商品基本信息表
CREATE TABLE `good_infos` (
  `tg_id` int(11) NOT NULL AUTO_INCREMENT,
  `tg_type_id` int(11) DEFAULT NULL,
  `tg_title` varchar(30) DEFAULT NULL,
  `tg_price` decimal(8,2) DEFAULT NULL,
  `tg_order` int(2) DEFAULT NULL,
  PRIMARY KEY (`tg_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `good_types` VALUES ("1", "青菜", "1", "1");
INSERT INTO `good_infos` VALUES ("1", "1", "芹菜", "12.40", "1");

下面我們根據(jù)這兩張表創(chuàng)建對(duì)應(yīng)的實(shí)體類。

商品類型實(shí)體
package com.yuqiyu.chapter30.bean;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:17
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
@Entity
@Table(name = "good_types")
@Data
public class GoodTypeBean
{
    @Id
    @Column(name = "tgt_id")
    private Long id;

    @Column(name = "tgt_name")
    private String name;
    @Column(name = "tgt_is_show")
    private int show;
    @Column(name = "tgt_order")
    private int order;

}
商品基本信息實(shí)體
package com.yuqiyu.chapter30.bean;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:16
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
@Entity
@Table(name = "good_infos")
@Data
public class GoodInfoBean
{
    @Id
    @Column(name = "tg_id")
    private Long id;
    @Column(name = "tg_title")
    private String title;
    @Column(name = "tg_price")
    private double price;
    @Column(name = "tg_order")
    private int order;
    @Column(name = "tg_type_id")
    private Long typeId;
}

接下來(lái)我們繼續(xù)創(chuàng)建相關(guān)的JPA。

商品類型JPA
package com.yuqiyu.chapter30.jpa;

import com.yuqiyu.chapter30.bean.GoodTypeBean;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:24
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
public interface GoodTypeJPA
    extends JpaRepository
{
}
商品信息JPA
package com.yuqiyu.chapter30.jpa;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:23
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
public interface GoodInfoJPA
    extends JpaRepository
{
    
}
配置MapStruct

到目前為止我們的準(zhǔn)備工作差不多完成了,下面我們開始配置使用MapStruct。我們的最終目的是為了返回一個(gè)自定義的DTO實(shí)體,那么我們就先來(lái)創(chuàng)建這個(gè)DTO,DTO的代碼如下所示:

package com.yuqiyu.chapter30.dto;

import lombok.Data;

/**
 * 轉(zhuǎn)換Dto
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:25
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
@Data
public class GoodInfoDTO
{
    //商品編號(hào)
    private String goodId;
    //商品名稱
    private String goodName;
    //商品價(jià)格
    private double goodPrice;
    //類型名稱
    private String typeName;
}

可以看到GoodInfoDTO實(shí)體內(nèi)集成了商品信息、商品類型兩張表內(nèi)的數(shù)據(jù),對(duì)應(yīng)查詢出信息后,我們需要使用MapStruct自動(dòng)映射到GoodInfoDTO。

創(chuàng)建Mapper

Mapper這個(gè)定義一般是被廣泛應(yīng)用到MyBatis半自動(dòng)化ORM框架上,而這里的Mapper跟Mybatis沒有關(guān)系。下面我們先來(lái)看下代碼,如下所示:

package com.yuqiyu.chapter30.mapper;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

/**
 * 配置映射
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:26
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
@Mapper(componentModel = "spring")
//@Mapper
public interface GoodInfoMapper
{
    //public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);

    @Mappings({
            @Mapping(source = "type.name",target = "typeName"),
            @Mapping(source = "good.id",target = "goodId"),
            @Mapping(source = "good.title",target = "goodName"),
            @Mapping(source = "good.price",target = "goodPrice")
    })
    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type);
}

可以看到GoodInfoMapper是一個(gè)接口的形式存在的,當(dāng)然也可以是一個(gè)抽象類,如果你需要在轉(zhuǎn)換的時(shí)候才用個(gè)性化的定制的時(shí)候可以采用抽象類的方式,相應(yīng)的代碼配置官方文檔已經(jīng)聲明。
@Mapper注解是用于標(biāo)注接口、抽象類是被MapStruct自動(dòng)映射的標(biāo)識(shí),只有存在該注解才會(huì)將內(nèi)部的接口方法自動(dòng)實(shí)現(xiàn)。
MapStruct為我們提供了多種的獲取Mapper的方式,比較常用的兩種分別是

默認(rèn)配置

默認(rèn)配置,我們不需要做過(guò)多的配置內(nèi)容,獲取Mapper的方式就是采用Mappers通過(guò)動(dòng)態(tài)工廠內(nèi)部反射機(jī)制完成Mapper實(shí)現(xiàn)類的獲取。
默認(rèn)方式獲取Mapper如下所示:

//Mapper接口內(nèi)部定義
public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);

//外部調(diào)用
GoodInfoMapper.MAPPER.from(goodBean,goodTypeBean);
Spring方式配置

Spring方式我們需要在@Mapper注解內(nèi)添加componentModel屬性值,配置后在外部可以采用@Autowired方式注入Mapper實(shí)現(xiàn)類完成映射方法調(diào)用。
Spring方式獲取Mapper如下所示:

//注解配置
@Mapper(componentModel = "spring")

//注入Mapper實(shí)現(xiàn)類
@Autowired
private GoodInfoMapper goodInfoMapper;

//調(diào)用
goodInfoMapper.from(goodBean,goodTypeBean);
@Mappings & @Mapping

Mapper接口定義方法上面聲明了一系列的注解映射@Mapping以及@Mappings,那么這兩個(gè)注解是用來(lái)干什么工作的呢?
@Mapping注解我們用到了兩個(gè)屬性,分別是source、target

source代表的是映射接口方法內(nèi)的參數(shù)名稱,如果是基本類型的參數(shù),參數(shù)名可以直接作為source的內(nèi)容,如果是實(shí)體類型,則可以采用實(shí)體參數(shù)名.字段名的方式作為source的內(nèi)容,配置如上面GoodInfoMapper內(nèi)容所示。

target代表的是映射到方法方法值內(nèi)的字段名稱,配置如上面GoodInfoMapper所示。

查看Mapper實(shí)現(xiàn)

下面我們執(zhí)行maven compile命令,到target/generated-sources/annotations目錄下查看對(duì)應(yīng)Mapper實(shí)現(xiàn)類,實(shí)現(xiàn)類代碼如下所示:

package com.yuqiyu.chapter30.mapper;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2017-08-20T12:52:52+0800",
    comments = "version: 1.2.0.CR1, compiler: javac, environment: Java 1.8.0_111 (Oracle Corporation)"
)
@Component
public class GoodInfoMapperImpl implements GoodInfoMapper {

    @Override
    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type) {
        if ( good == null && type == null ) {
            return null;
        }

        GoodInfoDTO goodInfoDTO = new GoodInfoDTO();

        if ( good != null ) {
            if ( good.getId() != null ) {
                goodInfoDTO.setGoodId( String.valueOf( good.getId() ) );
            }
            goodInfoDTO.setGoodName( good.getTitle() );
            goodInfoDTO.setGoodPrice( good.getPrice() );
        }
        if ( type != null ) {
            goodInfoDTO.setTypeName( type.getName() );
        }

        return goodInfoDTO;
    }
}

MapStruct根據(jù)我們配置的@Mapping注解自動(dòng)將source實(shí)體內(nèi)的字段進(jìn)行了調(diào)用target實(shí)體內(nèi)字段的setXxx方法賦值,并且做出了一切參數(shù)驗(yàn)證。
我們采用了Spring方式獲取Mapper,在自動(dòng)生成的實(shí)現(xiàn)類上MapStruct為我們自動(dòng)添加了@ComponentSpring聲明式注入注解配置。

運(yùn)行測(cè)試

下面我們來(lái)創(chuàng)建一個(gè)測(cè)試的Controller,用于訪問具體請(qǐng)求地址時(shí)查詢出商品的基本信息以及商品的類型后調(diào)用GoodInfoMapper.from(xxx,xxx)方法完成返回GoodInfoDTO實(shí)例。Controller代碼實(shí)現(xiàn)如下所示:

package com.yuqiyu.chapter30.controller;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import com.yuqiyu.chapter30.jpa.GoodInfoJPA;
import com.yuqiyu.chapter30.jpa.GoodTypeJPA;
import com.yuqiyu.chapter30.mapper.GoodInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 測(cè)試控制器
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:12:24
 * 碼云:http://git.oschina.net/jnyqy
 * ========================
 */
@RestController
public class GoodInfoController
{
    /**
     * 注入商品基本信息jpa
     */
    @Autowired
    private GoodInfoJPA goodInfoJPA;
    /**
     * 注入商品類型jpa
     */
    @Autowired
    private GoodTypeJPA goodTypeJPA;
    /**
     * 注入mapStruct轉(zhuǎn)換Mapper
     */
    @Autowired
    private GoodInfoMapper goodInfoMapper;

    /**
     * 查詢商品詳情
     * @param id
     * @return
     */
    @RequestMapping(value = "/detail/{id}")
    public GoodInfoDTO detail(@PathVariable("id") Long id)
    {
        //查詢商品基本信息
        GoodInfoBean goodInfoBean = goodInfoJPA.findOne(id);
        //查詢商品類型基本信息
        GoodTypeBean typeBean = goodTypeJPA.findOne(goodInfoBean.getTypeId());
        //返回轉(zhuǎn)換dto
        return goodInfoMapper.from(goodInfoBean,typeBean);
    }
}

在Controller內(nèi)我們注入了GoodInfoJPA、GoodTypeJPA以及GoodInfoMapper,在查詢商品詳情方法時(shí)做出了映射處理。接下來(lái)我們啟動(dòng)項(xiàng)目訪問地址http://127.0.0.1:8080/detail/1查看界面輸出效果,如下所示:

{
goodId: "1",
goodName: "芹菜",
goodPrice: 12.4,
typeName: "青菜"
}

可以看到界面輸出了GoodInfoDTO內(nèi)的所有字段內(nèi)容,并且通過(guò)from方法將對(duì)應(yīng)配置的target字段賦值。

總結(jié)

本章主要講述了基于SpringBoot開發(fā)框架上集成MapStruct自動(dòng)映射框架,完成模擬多表獲取數(shù)據(jù)后將某一些字段通過(guò)@Mapping配置自動(dòng)映射到DTO實(shí)體實(shí)例指定的字段內(nèi)。
MapStruct官方文檔地址:http://mapstruct.org/documentation/dev/reference/html/

本章代碼已經(jīng)上傳到碼云:
網(wǎng)頁(yè)地址:http://git.oschina.net/jnyqy/lessons
Git地址:https://git.oschina.net/jnyqy/lessons.git
SpringBoot相關(guān)系列文章請(qǐng)?jiān)L問:目錄:SpringBoot學(xué)習(xí)目錄
QueryDSL相關(guān)系列文章請(qǐng)?jiān)L問:QueryDSL通用查詢框架學(xué)習(xí)目錄
SpringDataJPA相關(guān)系列文章請(qǐng)?jiān)L問:目錄:SpringDataJPA學(xué)習(xí)目錄
感謝閱讀!
歡迎加入QQ技術(shù)交流群,共同進(jìn)步。
QQ技術(shù)交流群

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67660.html

相關(guān)文章

  • 推薦一個(gè) Java 實(shí)體映射工具 MapStruct

    摘要:聲明業(yè)務(wù)實(shí)體對(duì)象,數(shù)據(jù)傳輸對(duì)象。這種對(duì)象與對(duì)象之間的互相轉(zhuǎn)換,就需要有一個(gè)專門用來(lái)解決轉(zhuǎn)換問題的工具,畢竟每一個(gè)字段都會(huì)很麻煩。就是這樣的一個(gè)屬性映射工具,只需要定義一個(gè)接口,就會(huì)自動(dòng)實(shí)現(xiàn)這個(gè)映射接口,避免了復(fù)雜繁瑣的映射實(shí)現(xiàn)。 聲明: 1、DO(業(yè)務(wù)實(shí)體對(duì)象),DTO(數(shù)據(jù)傳輸對(duì)象)。 2、我的代碼中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略這條就好。 在一個(gè)成熟的...

    wayneli 評(píng)論0 收藏0
  • [開源作品] skadmin 管理系統(tǒng)

    摘要:簡(jiǎn)介項(xiàng)目基于的前后端分離的管理系統(tǒng),項(xiàng)目采用分模塊開發(fā)方式,權(quán)限控制采用,基于角色的訪問控制,支持?jǐn)?shù)據(jù)字典數(shù)據(jù)權(quán)限管理前端菜單支持動(dòng)態(tài)路由,另外還有其他的功能模塊日志管理代碼生成器系統(tǒng)監(jiān)控云存儲(chǔ)管理系統(tǒng)工具等等。 簡(jiǎn)介 項(xiàng)目基于 Spring Boot 2.1.0 、 Spring Data JPA、 Spring Security、Redis、Vue的前后端分離的管理系統(tǒng),項(xiàng)目采用分...

    codergarden 評(píng)論0 收藏0
  • 從零開始搭建SSM框架(Spring + Spring MVC + Mybatis)

    摘要:打開,,選中,然后再選中,輸入項(xiàng)目的和,指定等配置,修改,打開項(xiàng)目,添加一些必要的目錄,最終項(xiàng)目框架目錄圖如下修改文件,指定各依賴和插件的版本等信息在標(biāo)簽里面管理各依賴的版本號(hào)添加項(xiàng)目依賴管理依賴配置好之后,開始整合。 最近在回顧和總結(jié)一些技術(shù),想到了把之前比較火的 SSM 框架重新搭建出來(lái),作為一個(gè)小結(jié),同時(shí)也希望本文章寫出來(lái)能對(duì)大家有一些幫助和啟發(fā),因本人水平有限,難免可能會(huì)有一些...

    MiracleWong 評(píng)論0 收藏0
  • 【微信開發(fā)】SpringBoot 集成微信小程序授權(quán)登錄

    文章目錄 【微信開發(fā)】SpringBoot 集成微信小程序授權(quán)登錄1、SprinBoot 后端(1)準(zhǔn)備工作(2)相關(guān)配置類(3)相關(guān)實(shí)體類(4)處理后端邏輯 2、Uniapp 前端(1)授權(quán)登錄(2)效果樣式 微信公眾號(hào) 【微信開發(fā)】SpringBoot 集成微信小程序授權(quán)登錄 我這里采用了第三方的依賴,目前是最火的微信開發(fā)工具吧,WxJava 1、SprinBoot 后端 (1)準(zhǔn)備...

    whinc 評(píng)論0 收藏0
  • 如何根據(jù)動(dòng)態(tài)SQL代碼自動(dòng)生成DTO

    摘要:如何修改代碼為了盡量減少程序員的工作,我們的代碼生成器在生成完后,還需要將方法的返回值自動(dòng)修改成這個(gè)類。具體的實(shí)現(xiàn)到此為止,基本上代碼生成器的主要障礙都有了相應(yīng)的處理辦法。 當(dāng)前的狀況 一般做數(shù)據(jù)庫(kù)相關(guān)開發(fā), 除非學(xué)習(xí), 否則很少有人愿意直接使用JDBC。本來(lái)Java代碼就比較啰嗦了,而直接用JDBC寫代碼之啰嗦簡(jiǎn)直有些令人發(fā)狂!所以在實(shí)際開發(fā)過(guò)程中,我們通常都會(huì)使用一些框架/庫(kù)來(lái)幫助...

    weij 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<