还不会SpringBoot项目模块分层?来这手把手教你
创始人
2024-05-20 20:39:01
0

文章目录

    • 前言
      • 🍊缘由
      • ⏲️本文阅读时长
      • 🎯主要目标
      • 👨‍🎓试用人群
      • 🎁快速链接
      • 🍩水图
    • 正文
      • 🥫1.IDEA新建项目
      • 🌭2.创建子模块-dependencies(依赖层)
        • 🎯重点
      • 🍪3.创建子模块-main(主启动层)
        • 🎯重点
      • 🍇4.创建子模块-module(模块层)
      • 🍉5.创建chat-boot-module模块下对应功能分层
      • 🍧6.实际流程填充
      • 🦔7.示例DB更新
      • 🧩8.访问测试
    • 总结
    • 写在最后

前言

🍊缘由

经常看到网上很多优秀的开源项目中,代码简洁,模块分层完美。反观自己代码层级混乱,,却不知如何整理分层。此文手把手教你一步一步创建模块,左手右手一个慢动作。结合本人实际开发及个人项目中分层思路的分享,大神请勿喷

⏲️本文阅读时长

约25分钟

🎯主要目标

  1. 熟练掌握SpringBoot项目分层思路,丝滑拆分模块
  2. 熟悉代码层级依赖,规范化管理模块分布
  3. 手把手实战学习,理论实践相结合

👨‍🎓试用人群

  1. 对于Springboot熟悉但是不知道合理分层小白
  2. 有自己分层思路可以互相分享学习

🎁快速链接

公众号:JavaDog程序狗
在公众号,发送【分层】 ,无任何套路即可获得

在这里插入图片描述
或访问https://blog.javadog.net/archives/boot-module

🍩水图

下图反面教材,传统单体应用,结构臃肿

在这里插入图片描述

下图分层截选自本人的一个小项目,模块清晰,分工明确

在这里插入图片描述

我们要实现的小栗子的分层

在这里插入图片描述

正文

🥫1.IDEA新建项目

起名第一步,一个好名字,说不定是个好的开始

假如我们的项目是个聊天相关的项目,英文对应chat,所以定义项目名为chat-boot,其他的以此效仿

点击New->project

在这里插入图片描述

选择Maven项目,并选择合适JDK版本,点击Next

在这里插入图片描述

录入项目名称,并填写GAV坐标,点击Finish

在这里插入图片描述

删除无用文件及目录,如src目录和*.iml文件

在这里插入图片描述

删除后项目目录

在这里插入图片描述

修改pom.xml中依赖,增加spring-boot-starter-parent

 org.springframework.bootspring-boot-starter-parent2.3.1.RELEASE

在这里插入图片描述


🌭2.创建子模块-dependencies(依赖层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-dependencies

在这里插入图片描述

选择对应Module SDK版本,本人选择jdk1.8

在这里插入图片描述

填写子模块名 chat-boot-dependencies,然后检查对应GAV,点击Finish

在这里插入图片描述

生成子模块chat-boot-dependencies如下图

在这里插入图片描述

删除chat-boot-dependencies下无用文件及目录,如src目录,删除无用目录如下

在这里插入图片描述

完善chat-boot-dependencies下pom.xml依赖, 常用依赖放入,作为依赖主体,以下是本狗常用依赖,可酌情选择;记得把packaging改为pom


chat-bootnet.javadog.chat1.0-SNAPSHOT4.0.0chat-dependenciespom88UTF-8UTF-88.0.171.1.213.4.11.2.755.5.81.18.124.2.02.9.22.9.22.0.44.4.5.B1.3.23.2.0com.baomidoumybatis-plus-boot-starter${mybatis-plus.version}mysqlmysql-connector-java${mysql-connector-java.version}com.alibabadruid${druid.version}com.alibabafastjson${fastjson.version}cn.hutoolhutool-all${hutool.version}org.projectlomboklombok${lombok.versin}io.springfoxspringfox-swagger2${springfox-swagger2.version}io.springfoxspringfox-swagger-ui${springfox-swagger-ui.version}com.github.xiaoyminknife4j-spring-boot-starter${knife4j.version}cn.afterturneasypoi-base${easypoi.version}com.github.binarywangweixin-java-miniapp${weixin.version}org.apache.shiroshiro-spring${shiro.version}com.auth0java-jwt${jwt.version}

🎯重点

此处用的标签是 dependencyManagement

dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。


🍪3.创建子模块-main(主启动层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-main

在这里插入图片描述

选择对应Module SDK版本,本狗选择jdk1.8,点击Next

在这里插入图片描述

填写子模块名 chat-boot-main,然后检查对应GAV,点击Finish

在这里插入图片描述

生成子模块chat-boot-main如下图

在这里插入图片描述

完善chat-boot-main模块下pom.xml中依赖

  1. 引入必要依赖
  2. 完善profiles标签中环境相关
  3. 配置build标签中插件

chat-bootnet.javadog.chat1.0-SNAPSHOT4.0.0chat-boot-main88net.javadog.chatchat-boot-dependencies1.0-SNAPSHOTpomimportorg.springframework.bootspring-boot-starter-weborg.projectlomboklombokio.springfoxspringfox-swagger2io.springfoxspringfox-swagger-uicom.github.xiaoyminknife4j-spring-boot-starterchatorg.springframework.bootspring-boot-maven-pluginrepackagetruesrc/main/webappfalsesrc/main/resourcestruesrc/main/java**/*.xmllocallocaltruedevdevprodprod

🎯重点

  • 配置引入依赖chat-boot-dependencies,用作此模块依赖引入
net.javadog.chatchat-boot-dependencies1.0-SNAPSHOTpomimport

  • 配置build标签用于完善插件plugins,其中包含maven-compiler-plugin和maven-resources-plugin
org.apache.maven.pluginsmaven-compiler-plugin3.1${java.version}${java.version}org.apache.maven.pluginsmaven-resources-plugin2.6@falsesrc/main/webappfalsesrc/main/resourcestruesrc/main/java**/*.xml
  • 配置profiles环境变量标签,用于方便打包切换,本狗设置了 local、dev、prod三种环境
 locallocaltruedevdevprodprod

操作可在IDEA右上角方便切换环境
在这里插入图片描述
💥切记一定主动Reload一下Maven依赖
💥切记一定主动Reload一下Maven依赖
💥切记一定主动Reload一下Maven依赖
在这里插入图片描述

在chat-boot-main模块中加入启动类,在src/main/java下右键New=>Java Class

在这里插入图片描述

录入启动类名ChatApplication

在这里插入图片描述

完善ChatApplication启动类代码

package net.javadog.chat;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.net.InetAddress;
import java.net.UnknownHostException;/*** @author: hdx* @Date: 2023-01-28 11:24* @version: 1.0**/
@SpringBootApplication
@ServletComponentScan
@Slf4j
@EnableSwagger2
@EnableKnife4j
public class ChatApplication {public static void main(String[] args) throws UnknownHostException {// 启动类ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args);// 打印基础信息info(application);}static void info(ConfigurableApplicationContext application) throws UnknownHostException {Environment env = application.getEnvironment();String ip = InetAddress.getLocalHost().getHostAddress();String port = env.getProperty("server.port");String active = env.getProperty("spring.profiles.active");String contextPath = env.getProperty("server.servlet.context-path");if (contextPath == null) {contextPath = "";}log.info("\n----------------------------------------------------------\n\t" +"欢迎访问  \thttps://blog.javadog.net\n\t" +"示例程序【" + active + "】环境已启动! 地址如下:\n\t" +"Local: \t\thttp://localhost:" + port + contextPath + "\n\t" +"External: \thttp://" + ip + ':' + port + contextPath + '\n' +"Swagger文档: \thttp://" + ip + ":" + port + contextPath + "/doc.html\n" +"----------------------------------------------------------");}
}

配置application.yml文件

在这里插入图片描述
application.yml

#============================#
# server 配置
#============================#
server:port: 82max-http-header-size: 10240servlet:context-path: /chat/v1#============================#
# spring 配置
#============================#
spring:application:# 应用名name: chatprofiles:active: @spring.active@servlet:multipart:max-request-size: 100MBmax-file-size: 100MBjackson:time-zone: GMT+8date-format: yyyy-MM-dd HH:mm:ss.SSSlocale: zh_CNserialization:# 格式化输出indent_output: falsemain:allow-circular-references: true#解决swagger版本路径不兼容问题mvc:pathmatch:matching-strategy: ant_path_matcher#============================#
# mybatisplus 配置
#============================#
mybatis-plus:mapper-locations: classpath:mapper/*.xmlconfiguration:map-underscore-to-camel-case: truecache-enabled: truelazy-loading-enabled: truemultiple-result-sets-enabled: truelog-impl: org.apache.ibatis.logging.nologging.NoLoggingImplglobal-config:banner: falsedb-config:id-type: assign_idtable-underline: trueenable-sql-runner: true#数据库类型db-type: MYSQLconfiguration-properties:prefix:#如果数据库为postgresql,则需要配置为blobType: BINARYblobType: BLOB#如果数据库为oracle或mssql,则需要配置为boolValue: 1boolValue: true#============================#
# logging 配置
#============================#
logging:level:root: infofile:path: /root/javadog/chat/logs/${spring.application.name}/name: ${spring.application.name}logback:rollingpolicy:max-history: 7max-file-size: 10MB#============================#
# file 配置
#============================#
file:# 静态附件前缀static-prefix: attach# 上传的文件对外暴露的访问路径access-path-pattern: /${file.static-prefix}/**# 文件上传目录upload-folder: /root/javadog/chat/# 文件上传最大max-post-size: 10

application-local.yml

#服务配置
server:port: 8001max-http-header-size: 10240# Mysql数据库
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/chat-boot?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=trueusername: rootpassword: rootredis:host: localhostport: 6379password:

application-dev.yml

#服务配置
server:port: 7001max-http-header-size: 10240# mybatisplus 配置
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

application-prod.yml

#服务配置
server:port: 8005

🌊顺便加一下logback-spring.xml 日志文件


${application.name}${CONSOLE_LOG_PATTERN}${logging.path}/info/${application.name}-info.log${logging.path}/info/${application.name}-info.%d{yyyy-MM-dd}.%i.log${logging.file.max-size}${logging.file.max-history}true${FILE_LOG_PATTERN}warnACCEPTDENY${logging.path}/warn/${application.name}-warn.log${logging.path}$/warn/${application.name}-warn.%d{yyyy-MM-dd}.%i.log${logging.file.max-size}${logging.file.max-history}${FILE_LOG_PATTERN}errorACCEPTDENY${logging.path}/error/${application.name}-error.log${logging.path}/error/${application.name}-error.%d{yyyy-MM-dd}.%i.log${logging.file.max-size}${logging.file.max-history}${FILE_LOG_PATTERN}

启动一下项目试试,启动如下证明成功。如果报错少依赖请再拉一下Maven依赖!!!

在这里插入图片描述
在这里插入图片描述


🍇4.创建子模块-module(模块层)

右击项目chat-boot,new ->Moudle新建模块chat-boot-module

在这里插入图片描述

填写子模块名 chat-boot-module,然后检查对应GAV,点击Finish

在这里插入图片描述

生成子模块chat-boot-module如下图

在这里插入图片描述

删除chat-boot-module下无用文件及目录,如src目录,删除无用目录如下

在这里插入图片描述

自此外部大框架初步搭建成功

在这里插入图片描述

完善chat-boot-module下pom.xml依赖,如lombok,web等必要依赖


chat-bootnet.javadog.chat1.0-SNAPSHOT4.0.0chat-boot-modulepomchat-boot-commonchat-boot-controllerchat-boot-daochat-boot-dtochat-boot-entitychat-boot-service88net.javadog.chatchat-boot-dependencies${project.parent.version}pomimportnet.javadog.bkbbkb-boot-dependencies${project.parent.version}org.springframework.bootspring-boot-starter-webcom.github.binarywangweixin-java-miniapporg.projectlomboklombokcn.hutoolhutool-allio.springfoxspringfox-swagger2io.springfoxspringfox-swagger-uicom.github.xiaoyminknife4j-spring-boot-starterorg.apache.shiroshiro-springcom.auth0java-jwtcom.baomidoumybatis-plus-boot-startermysqlmysql-connector-java

一定要重新拉取依赖!
一定要重新拉取依赖!
一定要重新拉取依赖!

在这里插入图片描述


🍉5.创建chat-boot-module模块下对应功能分层

目前本狗分为如下6层

  • common-共通层
  • controller-控制器层
  • dao-数据持久层
  • dto-数据传输对象层
  • entity-实体层
  • service-业务逻辑层

依次按照上述添加模块方式进行新增子模块,本狗如下示例一个,其余都如法炮制

右击项目chat-boot-module,new ->Moudle新建模块chat-boot-common

一定看清楚父模块是否正确
一定看清楚父模块是否正确
一定看清楚父模块是否正确

在这里插入图片描述

确认父级模块后,点击Finish,生成chat-boot-common模块

在这里插入图片描述

依次按照上述方法,新建其他模块

chat-boot-controller模块

在这里插入图片描述

chat-boot-dao模块
在这里插入图片描述

chat-boot-dto模块
在这里插入图片描述

chat-boot-entity模块
在这里插入图片描述

chat-boot-service模块
在这里插入图片描述

总体模块雏形基本完成

在这里插入图片描述

🍧6.实际流程填充

  • 模拟正常前端请求后台服务调用过程,进行实际代码补充

在chat-boot-entity下新建实体类User,在src/main/java下右键New=>Java Class,录入包名及类名

在这里插入图片描述

package net.javadog.chat.entity;import lombok.Data;/*** @author: hdx* @Date: 2023-01-28 14:26* @version: 1.0**/
@Data
public class User {private Long id;private String username;private String idCard;
}

在chat-boot-dto下新建目request和response,分别代表请求传输对象和返回传输对象,并分别在目录下创建UserRequest.java和UserResponse.java

在这里插入图片描述

package net.javadog.chat.request;import lombok.Data;/*** @author: hdx* @Date: 2023-01-28 14:59* @version: 1.0**/
@Data
public class UserRequest {private Long id;private String username;
}
package net.javadog.chat.response;import lombok.Data;/*** @author: hdx* @Date: 2023-01-28 14:59* @version: 1.0**/
@Data
public class UserResponse {private Long id;private String username;
}

在chat-boot-dao下修改chat-boot-dao模块下修改pom.xml文件依赖,引入chat-boot-entity;并增对应UserMapper.java
在这里插入图片描述

package net.javadog.chat.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.javadog.chat.entity.User;/*** 用户mapper** @author: hdx* @Date: 2023-01-10 11:43* @version: 1.0**/
public interface UserMapper extends BaseMapper {
}

chat-boot-modulenet.javadog.chat1.0-SNAPSHOT4.0.0chat-boot-dao88net.javadog.chatchat-boot-entity${project.parent.version}

在chat-boot-service下新建目录service和impl,并在对应目录下新建UserService.java和UserServiceImpl.java,并修改chat-boot-service模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-dao

在这里插入图片描述

package net.javadog.chat.service;import com.baomidou.mybatisplus.extension.service.IService;
import net.javadog.chat.entity.User;/*** 用户接口** @author: hdx* @Date: 2023-01-10 11:53* @version: 1.0**/
public interface UserService extends IService {}
package net.javadog.chat.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.javadog.chat.entity.User;
import net.javadog.chat.mapper.UserMapper;
import net.javadog.chat.service.UserService;
import org.springframework.stereotype.Service;/*** 用户接口实现类** @author: hdx* @Date: 2023-01-10 11:55* @version: 1.0**/
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {}

chat-boot-modulenet.javadog.chat1.0-SNAPSHOT4.0.0chat-boot-service88net.javadog.chatchat-boot-dao${project.parent.version}net.javadog.chatchat-boot-dto${project.parent.version}

在chat-boot-controller创建UserController.java,并修改chat-boot-controller模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-service

在这里插入图片描述

package net.javadog.chat.controller;import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.javadog.chat.entity.User;
import net.javadog.chat.request.UserRequest;
import net.javadog.chat.response.UserResponse;
import net.javadog.chat.service.UserService;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** 用户控制器** @author: hdx* @Date: 2022-12-07 15:48* @version: 1.0**/
@Api(tags = "用户控制器")
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@ApiOperation(value = "用户详情", notes = "用户详情")@GetMappingpublic UserResponse detail(UserRequest userRequest){UserResponse userResponse = new UserResponse();User user = userService.getById(userRequest.getId());BeanUtil.copyProperties(user, userResponse);return userResponse;}}

🎯重要补充
1.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-controller模块加入
2.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-dao模块加入
3.切记修改启动类ChatApplication中加入@MapperScan注解

在这里插入图片描述


chat-bootnet.javadog.chat1.0-SNAPSHOT4.0.0chat-boot-main88net.javadog.chatchat-boot-dependencies1.0-SNAPSHOTpomimportorg.springframework.bootspring-boot-starter-weborg.projectlomboklombokio.springfoxspringfox-swagger2io.springfoxspringfox-swagger-uicom.github.xiaoyminknife4j-spring-boot-starternet.javadog.chatchat-boot-controller${project.parent.version}net.javadog.chatchat-boot-dao${project.parent.version}org.apache.maven.pluginsmaven-compiler-plugin3.1${java.version}${java.version}org.apache.maven.pluginsmaven-resources-plugin2.6@falsesrc/main/webappfalsesrc/main/resourcestruesrc/main/java**/*.xmllocallocaltruedevdevprodprod

在这里插入图片描述

package net.javadog.chat;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.net.InetAddress;
import java.net.UnknownHostException;/*** @author: hdx* @Date: 2023-01-28 11:24* @version: 1.0**/
@SpringBootApplication
@ServletComponentScan
@Slf4j
@EnableSwagger2
@EnableKnife4j
@MapperScan(basePackages = {"net.javadog.chat.mapper"})
public class ChatApplication {public static void main(String[] args) throws UnknownHostException {// 启动类ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args);// 打印基础信息info(application);}static void info(ConfigurableApplicationContext application) throws UnknownHostException {Environment env = application.getEnvironment();String ip = InetAddress.getLocalHost().getHostAddress();String port = env.getProperty("server.port");String active = env.getProperty("spring.profiles.active");String contextPath = env.getProperty("server.servlet.context-path");if (contextPath == null) {contextPath = "";}log.info("\n----------------------------------------------------------\n\t" +"欢迎访问  \thttps://blog.javadog.net\n\t" +"示例程序【" + active + "】环境已启动! 地址如下:\n\t" +"Local: \t\thttp://localhost:" + port + contextPath + "\n\t" +"External: \thttp://" + ip + ':' + port + contextPath + '\n' +"Swagger文档: \thttp://" + ip + ":" + port + contextPath + "/doc.html\n" +"----------------------------------------------------------");}
}

🦔7.示例DB更新

  • 模拟正常前端请求后台服务调用过程,进行实际代码补充

在这里插入图片描述

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` bigint(20) NOT NULL COMMENT 'id',`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',`id_card` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'JavaDog', '123123');

🧩8.访问测试

浏览器访问http://localhost:8001/chat/v1/user?id=1

测试成功如下图所示

在这里插入图片描述

总结

以上示例只是简单示范分层思路,其中代码逻辑实现方式有很多种,大家选取适用自己就好,希望自己的思路能对大家有帮助

如遇缺少依赖情况,一定要重新拉取依赖!
在这里插入图片描述

写在最后

此生两悔,悔遇见你,更悔未早遇见你,珍惜当下拥有,勿念昔日美好。

JavaDog狗屋地址
个人博客https://blog.javadog.net
公众号https://mp.weixin.qq.com/s/_vgnXoQ8FSobD3OfRAf5gw
CSDNhttps://blog.csdn.net/baidu_25986059
掘金https://juejin.cn/user/2172290706716775
知乎https://www.zhihu.com/people/JavaDog
简书https://www.jianshu.com/u/1ff9c6bdb916
giteehttps://gitee.com/javadog-net
GitHubhttps://github.com/javadog-net

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...