分享一個java微服務(wù)快速開發(fā)框架

raf-framework 2.0.0

本框架基于如下構(gòu)建

Spring Boot Version: 2.7.14.RELEASE
Spring Cloud Version: 2021.0.5
Spring Cloud Alibaba Version: 2021.0.5.0

可以靈活采用基于SpringCloud Feign或SpringCloud Alibaba Dubbo構(gòu)建微服務(wù)體系

目的

簡化微服務(wù)的使用,簡化常用組件的使用,統(tǒng)一編碼風(fēng)格,用最佳實(shí)踐使用各種組件。
使開發(fā)更關(guān)注業(yè)務(wù)本身開發(fā),提升開發(fā)效率。后期組件版本修改,組件替換更加靈活。
統(tǒng)一的框架底層,更能迅速適應(yīng)高性能,高并發(fā),高可用,高安全的互聯(lián)網(wǎng)時代。

使用條件

JDK 1. 8+
Maven 3.5.2+

設(shè)計原則

  1. 組件支持熱插拔,遵循引用才使用的原則
  2. 開關(guān)模式,大部分都默認(rèn)關(guān)閉,可以靈活選擇是否啟用
  3. 底層不封裝任何硬代碼,包括地址,秘鑰等
  4. 統(tǒng)一的編碼風(fēng)格,符合代碼掃描規(guī)范
  5. 依賴第三方包無重大安全漏洞,自身代碼無重大安全漏洞
  6. maven插件只封裝基礎(chǔ)的打包功能,其它像代碼檢查,Java doc生成走第三方工具,解耦
  7. 采用flatten-maven-plugin插件,revision占位符統(tǒng)一版本
  8. 啟動日志清爽,引用jar清爽,打包的jar清爽

封裝的內(nèi)容

  1. 統(tǒng)一的異常處理,系統(tǒng)異常,組件異常,業(yè)務(wù)異常等
  2. 通用的返回結(jié)果,枚舉,常量,錯誤碼
  3. 統(tǒng)一的入?yún)ⅲ鰠⒏袷?/li>
  4. 統(tǒng)一的分頁格式
  5. 統(tǒng)一的公共類庫
  6. 接口多版本
  7. 跨域配置
  8. 統(tǒng)一的http請求輸入,輸出日志配置
  9. swagger配置
  10. 異步線程池:參數(shù)支持上報prometheus實(shí)現(xiàn)監(jiān)控,或者清空隊列等
  11. 統(tǒng)一日志輸出格式,方便采集,統(tǒng)計,分析
    采用logback,異步日志,默認(rèn)路徑/data/logs,支持路徑修改
    日志格式(co-demo/2019-10-17/application_16.log)按小時切割,單文件最大200M,默認(rèn)183天
    DEBUG,INFO,WARN,ERROR
    所有日志一個文件存儲,不重復(fù)記錄
    DEBUG默認(rèn)不開啟,調(diào)試才能開啟,INFO默認(rèn)日志級別,WARN必須減少數(shù)量,ERROR日志必須消滅掉
    敏感信息脫敏走業(yè)務(wù)方式
    日志格式統(tǒng)一,不要重復(fù)記錄日志
  12. jasypt: 敏感配置信息加密
  13. jackson:高性能,統(tǒng)一的序列化,反序列化使用方式
  14. 優(yōu)雅停機(jī) :默認(rèn)處理30s,delete 注冊中心&kill xxx,30s后強(qiáng)制kill -9
  15. 分布式日志追蹤,dubbo,feign,異步線程
  16. nacos:服務(wù)發(fā)現(xiàn),配置中心
  17. mybatis:集成Hikari,相對其它數(shù)據(jù)源有更高的性能,支持多數(shù)據(jù)源,監(jiān)控
  18. dubbo:服務(wù)調(diào)用,全局異常處理,分布式日志追蹤
  19. rabbmitmq:普通隊列,死信隊列,網(wǎng)絡(luò)抖動重發(fā)
  20. sentry:日志監(jiān)控平臺
  21. okhttp:統(tǒng)一第三方api調(diào)用
  22. redis:引入Lettuce有更高的性能,統(tǒng)一序列化方式,緩存,redisson分布式鎖
  23. monitor:actuator監(jiān)控,micrometer

框架介紹

raf-framework(聚合,倉庫信息介紹)
raf-framework-autoconfigure(基本庫)
raf-framework-dependencies(配置管理,版本管理,插件管理)
raf-framework-parent(框架父工程)

raf-framework-starter(聚合)
raf-framework-starter-parent(新項(xiàng)目父工程)
raf-framework-springmvc-starter (基礎(chǔ)starter,jasypt)
raf-framework-cloud-starter(基于springcloud feign調(diào)用構(gòu)建微服務(wù))
raf-framework-sleuth-starter
raf-framework-dubbo-starter(基于dubbo調(diào)用構(gòu)建微服務(wù))
raf-framework-nacos-config-starter
raf-framework-nacos-discovery-starter
raf-framework-mybatis-starter (依賴raf-framework-jdbc-starter)
raf-framework-redis-starter
raf-framework-okhttp-starter
raf-framework-rabbit-starter
raf-framework-monitor-starter
raf-framework-sentry-starter
raf-framework-swagger-starter

如何使用 (參考示例項(xiàng)目:co-demo)

  1. 新建springboot項(xiàng)目
    groupId命名規(guī)則: com.公司簡稱.部門或業(yè)務(wù)線簡稱(com.co.xx)
    artifactId命名規(guī)則:項(xiàng)目名稱.業(yè)務(wù)模塊名稱(co-demo)

  2. parent依賴

<!--raf starter parent-->
<parent>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-starter-parent</artifactId>
    <version>2. 0.0-SNAPSHOT</version>
    <relativePath/>
</parent>

<dependencies>
    <!--raf spring mvc-->
    <dependency>
        <groupId>com.github.raf</groupId>
        <artifactId>raf-framework-springmvc-starter</artifactId>
        <version>[2. 0.0-SNAPSHOT,)</version>
    </dependency>
</dependencies>
  1. 服務(wù)實(shí)現(xiàn)無需新增maven相關(guān)插件,facade工程需要禁用父類的插件行為
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!-- 禁用父項(xiàng)目插件 -->
            <executions>
                <execution>
                    <phase>none</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

組件使用方法

nacos使用方法

  1. 啟動類新增
@EnableDiscoveryClient
  1. 添加依賴
<!--raf nacos config-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-nacos-config-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>

<!--raf nacos discovery-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-nacos-discovery-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 新增配置
bootstrap.yml

nacos:
  addr: ${NACOS_ADDR:127.0.0.1:8890}
  namespace: ${NACOS_NAMESPACE:}

#新增nacos配置中心
spring:
  cloud:
    nacos:
      config:
        enabled: true
        fileExtension: yml
        serverAddr: ${nacos.addr}
        namespace: ${nacos.namespace}
        prefix: ${spring.application.name}
        group: default
        sharedConfigs:
          - dataId: base.yml
            group: default
            refresh: true
        extensionConfigs:
          - dataId: ${spring.application.name}-ext.yml
            group: default
            refresh: true

#新增nacos服務(wù)發(fā)現(xiàn)
spring:
  cloud:
    nacos:
      discovery:
        server-addr: ${nacos.addr}
        namespace: ${nacos.namespace}

dubbo使用方法

  1. 添加依賴
<!--raf dubbo-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-dubbo-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#dubbo配置,支持dubbo3.x 應(yīng)用或者服務(wù)方式,dubbo,grpc協(xié)議
dubbo:
 application:
   name: ${spring.application.name}
   qos-enable: false
   register-mode: service  #all,instance,service
   metadata-type: remote
   serialize-check-status: DISABLE
   check-serializable: false
 registry:
   address: nacos://${nacos.addr}?namespace=${nacos.namespace} #nacos://${nacos.addr}?registry-type=service
   protocol: grpc
   timeout: 2000
   register-mode: FORCE_INTERFACE #APPLICATION_FIRST,F(xiàn)ORCE_APPLICATION,F(xiàn)ORCE_INTERFACE
   file: ../registry/${dubbo.application.name}
  #  parameters:
  #    namespace: ${nacos.namespace}
  #    register-consumer-url: false
   use-as-metadata-center: true
   use-as-config-center: false
 protocol:
   name: grpc
   port: 28001
   corethreads: 200 #核心線程數(shù)
   serialization: hessian2
 provider:
   actives: 0 #consumer,每方法最大并發(fā)調(diào)用數(shù)
   connections: 10 #consumer,最大并發(fā)調(diào)用數(shù)
   accepts: 0 #最大可以接受的連接數(shù)
   threadpool: cached
   threads: 300 #最大線程數(shù)(隊列為0是阻塞對列,該值沒用)
   alive: 5000 #非核心線程存活時間
   queues: 0 #阻塞對列
   timeout: 60000
   executes: 0 #提供者,每方法最大并發(fā)調(diào)用數(shù)
   retries: 0
   filter: -exception
 consumer:
   check: false
   retries: 0

mybatis使用方法

  1. 添加依賴
<!--mybatis-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-mybatis-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#mybatis配置
raf.dataSource:
  oms:
    url: jdbc:mysql://${db.addr}/co_oms_db?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&allowMultiQueries=true&tinyInt1isBit=false&serverTimezone=Asia/Shanghai
    username: ${db.username}
    password: ${db.password}
    mapperLocations: mapper/oms/*.xml
    basePackage: com.company.a.dao.oms
    typeAliasesPackage: com.company.a.entity
    driver-class-name: org.mariadb.jdbc.Driver
    configLocation: classpath:mapper/mybatis-config.xml
    pool:
      maximumPoolSize: 10 #cpu數(shù)*2+磁盤數(shù)
      idleTimeout: 600000 #默認(rèn)10分鐘
      connectionTimeout: 15000 #15s比數(shù)據(jù)庫大,數(shù)據(jù)庫10s
      maxLifetime: 1740000 #29分鐘比數(shù)據(jù)庫小,數(shù)據(jù)庫30
  cms:
    url: jdbc:mysql://${db.addr}/co_cms_db?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&allowMultiQueries=true&tinyInt1isBit=false&serverTimezone=Asia/Shanghai
    username: ${db.username}
    password: ${db.password}
    mapperLocations: mapper/cms/*.xml
    basePackage: com.company.a.dao.cms
    typeAliasesPackage: com.company.a.entity
    driver-class-name: org.mariadb.jdbc.Driver
    configLocation: classpath:mapper/mybatis-config.xml
    pool:
      maximumPoolSize: 10 #cpu數(shù)*2+磁盤數(shù)
      idleTimeout: 600000 #默認(rèn)10分鐘
      connectionTimeout: 15000 #15s比數(shù)據(jù)庫大,數(shù)據(jù)庫10s
      maxLifetime: 1740000 #29分鐘比數(shù)據(jù)庫小,數(shù)據(jù)庫30

log4jdbc.sqltiming:
  warn.threshold: 300   #300ms 會打印warn級別的日志,sqltiming:info才生效
  error.threshold: 500  #500ms 會打印error級別的日志

raf.pagehelper:
  helperDialect: "mysql"
  offsetAsPageNum: false
  rowBoundsWithCount: false
  pageSizeZero: false
  reasonable: false
  params: "pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero"
  supportMethodsArguments: false
  autoRuntimeDialect: false
  closeConn: true

redis使用方法

  1. 添加依賴
<!--redis-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-redis-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#redis配置
spring.redis:
  database: 0
  host: 127.0.0.1
  port: 6379
  password:
  timeout: 2s
  lettuce:
    pool:
      max-active: 10 #連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
      max-idle: 10 #連接池中的最大空閑連接
      min-idle: 0 #連接池中的最小空閑連接
      max-wait: 2s #連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)
#    cluster.nodes:
#      - 0.0.0.0:0

spring.cache:
  redis:
    time-to-live: 86400s #默認(rèn)過期時間一天
    cacheNullValues: false
  cache-names:
  - user_cache #針對具體key設(shè)置過期時間
  - user_list_cache

raf.customCache:
  user_cache:
    time-to-live: 200s #對應(yīng)上面key
  user_list_cache:
    time-to-live: 100s

okHttp使用方法

  1. 添加依賴
<!--okhttp-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-okhttp-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#okhttp配置
raf.okhttp:
  connectTimeout: 2000
  readTimeout: 2000
  writeTimeout: 2000
  retryOnConnectionFailure: true
  followRedirects: true
  followSslRedirects: true
  connection:
    maxIdleConnections: 10
    keepAliveDuration: 30000
  level: BASIC #日志級別 NONE BASIC HEADERS BODY

rabbit mq使用方法

  1. 添加依賴
<!--rabbit mq-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-rabbit-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#rabbitMq配置
raf.rabbit:
  enabled: true
  addresses: ${mq.addr}
  username: ${mq.username}
  password: ${mq.password}
  consumer: #消費(fèi)者配置
    group: ${spring.application.name} #消費(fèi)者組,默認(rèn)寫spring.application.name即可
  provider: #生產(chǎn)者配置
    exchange: xx.demo.topic #topicExchange交換機(jī)名稱
    ack: true #是否監(jiān)聽發(fā)送返回 confirm,return
  delay: #延遲隊列,同一個業(yè)務(wù)延遲時間間隔必須一樣
    deadExchange: xx.demo.dead.topic #死信隊列
    receiveExchange: xx.demo.receive.topic #接收隊列
    queuePrefix:
      - xx.demo.delay.businessOne #業(yè)務(wù)1 接收隊列xx.demo.delay.businessOne.receive.queue
      - xx.demo.delay.businessTwo #業(yè)務(wù)2 接收隊列xx.demo.delay.businessTwo.receive.queue

swagger使用方法

  1. 啟動類添加
@EnableSwagger2Doc
  1. 添加依賴
<!--raf swagger-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-swagger-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#swagger配置
swagger:
  enabled: true
  contact:
    name: xxx
    email: xx@xx.com
  authorization:#token
    name: Authorization
    type: ApiKey
    key-name: Authorization
    auth-regex: ^.*$
  globalOperationParameters:#以下參數(shù)只限原子服務(wù)使用
  - name: x-user-id
    modelRef: string
    parameterType: header
    required: false
    description:
  - name: x-user-name-header
    modelRef: string
    parameterType: header
    required: false
    description:
  - name: x-role-header
    modelRef: string
    parameterType: header
    required: false
    description:
  docket:
    all:
      version: v-all
      title: demo項(xiàng)目接口文檔
      description: demo項(xiàng)目接口文檔
      base-package: com.company.demo.controller
      base-path: /**
  1. 訪問地址:http://xxx/doc.html 或 /swagger-ui/index.html

spring cloud eureka使用方法

  1. 添加依賴
<!--spring cloud eureka-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-eureka-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 啟動類添加
@EnableDiscoveryClient
  1. 添加配置
eureka:
  client:
    registry-fetch-interval-seconds: 10 #拉取注冊表(默認(rèn)30s)
    serviceUrl:
      defaultZone: http://eureka:eka321@localhost:1111/eureka/
  instance:
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true
    status-page-url-path: /swagger-ui.html
    lease-renewal-interval-in-seconds: 10 #服務(wù)續(xù)約間隔時間(缺省為30s)
    lease-expiration-duration-in-seconds: 30 #服務(wù)續(xù)約到期時間(默認(rèn)90s)

spring-cloud使用方法

  1. 添加依賴
<!--spring cloud-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-cloud-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 啟動類添加
@EnableFeignClients
  1. 添加配置
#熔斷配置
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 60000

#ribbon配置
ribbon:
  ConnectTimeout: 1000 # 請求連接超時時間
  ReadTimeout: 2000 # 請求處理的超時時間
  OkToRetryOnAllOperations: false
  MaxAutoRetries: 0 # 對當(dāng)前實(shí)例的重試次數(shù)
  MaxAutoRetriesNextServer: 0 # 切換實(shí)例的重試次數(shù)
  okhttp:
    enabled: true

#feign配置
feign:
  hystrix:
    enabled: true

#feign重試
raf.feign-retry:
  enabled: false
  max-attempts: 5
  
#sleuth配置
spring:
  zipkin:
    enabled: false
    base-url: http://localhost:9992
  sleuth:
    enabled: true
    sampler:
      probability: 1. 0

sentry使用

錯誤日志實(shí)時跟蹤服務(wù)

  1. 添加依賴
<!--raf sentry-->
<dependency>
    <groupId>com.github.raf</groupId>
    <artifactId>raf-framework-sentry-starter</artifactId>
    <version>[2. 0.0-SNAPSHOT,)</version>
</dependency>
  1. 添加配置
#sentry配置
raf.sentry:
  enabled: true #默認(rèn)false
  dns: https://f488ea8838b547c5a212c6d0faff312b@sentry.io/1783484?stacktrace.app.packages=xx-demo&environment=dev

nacos敏感信息加密使用

采用jasypt對敏感配置信息進(jìn)行統(tǒng)一的加解密

input:明文/密文;password:秘鑰

java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input='xxxx' password='xxxx' algorithm=PBEWITHHMACSHA512ANDAES_256 ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator

java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI input='xxxx' password='xxxx' algorithm=PBEWITHHMACSHA512ANDAES_256 ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator

在nacos配置使用

  1. 配置秘鑰
    jasypt.encryptor.password=xxxx

  2. 使用加密后的值
    xxx.pwd=ENC(xxxx)

其它配置使用

#日志配置
logging:
  level:
    root: info
    com.company.a.dao.cms: info
    jdbc:
      sqlonly: OFF
      sqltiming: INFO
      audit: OFF
      resultset: OFF
      resultsettable: OFF
      connection: OFF
  file:
    path: /data/logs

#日志記錄配置(輸入,輸出)
#BASIC,REQ_HEADERS, REQ_BODY, RSP_HEADERS(默認(rèn)), RSP_BODY
raf.log:
  enabled: true
  level: REQ_BODY

#優(yōu)雅停機(jī)
raf.tomcat:
  shutdown:
    enabled: true #默認(rèn)true
    waitTime: 30 #默認(rèn)30s的優(yōu)雅停機(jī)等待時間,超過時間強(qiáng)行關(guān)閉

#跨域配置
raf.cors:
  enabled: false #默認(rèn)false
  allowOrigins: #默認(rèn)*, 可以通過數(shù)組進(jìn)行添加
  allowHeaders: #默認(rèn)*, 可以通過數(shù)組進(jìn)行添加
  allowMethods: #默認(rèn)*, 可以通過數(shù)組進(jìn)行添加
  allowExposeHeaders: #默認(rèn)無,可以通過數(shù)組進(jìn)行添加

#異步線程池配置
raf.executor:
  enabled: true
  corePoolSize: 10
  maxPoolSize: 20
  queueCapacity: 100
  keepAliveSeconds: 5
  threadNamePrefix: raf-async-thread-pool-
  metricEnabled: false

#雪花算法
raf.snow-flake:
  enabled: false

統(tǒng)一http狀態(tài)碼,業(yè)務(wù)code碼

http狀態(tài)碼
200 成功
{
  "code": 200,
  "msg": "Success",
  "data": {
    "account": "xxx",
    "email": "xxx",
    "sex": 1,
    "status": 1
  }
}
401 認(rèn)證錯誤
{
  "code": 401,
  "msg": "Unauthorized"
}
403 認(rèn)證通過無權(quán)限
{
  "code": 403,
  "msg": "Forbidden"
}
404 資源不存在
{
  "code": 404,
  "msg": "Not Found"
}
405 Method Not Allowed
{
  "code": 405,
  "msg": "Method Not Allowed"
}
415 Unsupported Media Type
{
  "code": 415,
  "msg": "Unsupported Media Type"
}
426 簽名錯誤
{
  "code": 426,
  "msg": "Sign Error"
}
500 服務(wù)端錯誤
{
  "code": 500,
  "msg": "服務(wù)端錯誤,請稍后再試"
}
400 Bad Request
1. 參數(shù)校驗(yàn)錯誤 code:700
{
  "code": 700,
  "msg": "pageNum參數(shù)校驗(yàn)錯誤"
}
{
  "code": 700,
  "msg": "參數(shù)校驗(yàn)錯誤",
  "data": {
    "password": "長度需要在6和30之間",
    "email": "email不能為空"
  }
}
2. 業(yè)務(wù)異常-友好提示 code:10000以上
{
  "code": 10001,
  "msg": "Xxx失聯(lián)了,換一個試試吧"
}

啟動部署

<layers>
    <enabled>true</enabled>
</layers>

由于SpringBoot 2.3.x 已經(jīng)支持打包分層,所以maven插件已強(qiáng)制配置分層打包

推送公共包
mvn clean deploy -Dmaven.test.skip=true
服務(wù)打包
mvn clean package -Dmaven.test.skip=true

springboot,springcloud,spring-cloud-alibaba版本依賴關(guān)系

https://spring.io/projects/spring-cloud#overview
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

License

Raf Framework is Open Source software released under the MIT license.

底層框架開源地址
https://github.com/JerryRaf/raf-framework

示例項(xiàng)目開源地址
https://github.com/JerryRaf/co-demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容