当前位置: 首页 > news >正文

企业网站需要哪些模块/怎样在网上推广

企业网站需要哪些模块,怎样在网上推广,在家可以加工的小工厂,下载手机app免费安装商业模式 常见商业模式 B2C模式: 两个角色: 管理员:增加,修改,删除普通用户:查询 商家到用户,自己制作大量自有版权的视频,放在自有平台上,让用户付费。 这是这个项目使…

商业模式

常见商业模式

  • B2C模式:

    两个角色:

    • 管理员:增加,修改,删除
    • 普通用户:查询

    商家到用户,自己制作大量自有版权的视频,放在自有平台上,让用户付费。

    这是这个项目使用的模式

    核心模块:课程模块

  • B2B2C模式:

    商家到商家到用户,平台连接第三方教育机构,平台一般不直接提供课程内容。

    比如京东,很多的电商平台都是这种模式。

项目模块

分成两个系统进行开发

  • 系统后台

    管理员使用

    1. 讲师管理模块
    2. 课程分类管理模块
    3. 课程管理模块
      • 视频
    4. 统计分析模块
    5. 订单管理
    6. banner管理
    7. 权限管理
  • 系统前台

    普通用户使用

    1. 首页数据的显示
    2. 讲师列表和详情
    3. 课程列表和详情
      • 视频在线播放
    4. 登录和注册
      • 微信扫码登录
    5. 微信扫码支付

项目技术点

采用前后端分离开发

  • 后端技术

    SpringBoot

    SpringCloud

    MybatisPlus

    Spring Security

  • 前端技术

    vue + element ui + axios + node.js …

  • 其他技术

    阿里云oss

    阿里云视频点播服务

    阿里云短信服务

    微信支付和登录

    docker

    git

    jenkins

Mybatis Plus

  1. 创建数据库,创建数据库表

    添加数据用于MP操作

    DROP TABLE IF EXISTS user;CREATE TABLE USER(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
    );
    
    DELETE FROM user;INSERT INTO user (id,name,age,email) VALUES
    (1, 'Jone', 18, 'test1@test.com'),
    (2, 'Jack', 20, 'test2@test.com'),
    (3, 'Tom', 28, 'test3@test.com'),
    (4, 'Sandy', 21, 'test4@test.com'),
    (5, 'Billie', 24, 'test5@test.com');
    
  2. 使用Idea 创建一个Spring Boot工程

  3. 引入相关依赖

    springboot和mp

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
    
  4. 在application.properties里面配置mysql配置

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=GMT%2B8
    spring.datasource.username=root
    spring.datasource.password=xxxxxxx
    
  5. 编写代码测试

配置日志

查看sql输出日志

# mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

测试Mybatis的添加操作

@Test
void addUser() {User user = new User();user.setName("lucy");user.setAge(30);user.setEmail("lucy@qq.com");int insert = userMapper.insert(user);System.out.println("insert: "+insert);
}

在这里没有手动设置id,但是MP会自动生成。

image-20230307213928150

主键生成策略

  1. 自动增长 AUTO INCREMENT

    分表时,会像下面这样分配每张表的id,所以创建新的表的时候需要知道上一张表最后一个项目的id

    image-20230307214429872

  2. UUID 一个生成的随机的值

    不好进行排序

  3. 用Redis实现

    image-20230307214752594

  4. MP自带策略,19位,使用雪花算法生成的

如何使用这些主键策略

image-20230307215742952

AUTO: 自动增长

ID_WORKER: MP自带的策略,生成19位的值,数字类型使用这种策略
ID_WORKER_STR:也是MP自带的策略,生成19位值,字符串类型使用这种策略

INPUT: 需要我们自己设置id

NONE: 没有策略,也需要自己设置

UUID: 每次生成一个UUID

@TableId(type=IdType.AUTO)
private Long id

增删改查其他操作

mp实现修改操作

@Test
void updateUser() {User user = new User();user.setId(2L);user.setAge(120);int i = userMapper.updateById(user);System.out.println(i);
}

自动填充

  1. 表中添加两个字段
    create_time update_time
  2. 添加实体类属性
    注意属性需要驼峰命名法
  3. 设置自动填充
    • 可以在addUser()的时候手动传值
      image-20230307221813207
    • 可以使用MP来做到

MP自动填充具体实现过程

  1. 在实体类里面需要自动填充的属性上添加注解

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    

    FieldFill.INSERT表示在执行插入的时候自动填充这个字段

  2. 自己创建类,实现METAObjectHandler接口,实现接口里面的方法

    @Component  // 一定注意交给Spring容器管理
    public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {  // 填充操作时会执行this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {  // 更新操作时会执行this.setFieldValByName("updateTime", new Date(), metaObject);}
    }
    

乐观锁

主要解决:丢失更新问题

如果不考虑事务隔离性,会产生读问题?

  • 脏读
  • 不可重复读
  • 幻读/虚读

不考虑隔离性,产生写问题:丢失更新问题。

丢失更新问题image-20230308090108615

上面的过程中,mary原本是想修改数据500,可最后修改了数据8000,这就导致了lucy的数据更新被覆盖了。

多人同时修改一条记录,最后一个提交的人会把前面提交的更新覆盖。

解决方案:

  1. 悲观锁
    把所有的操作变成串行操作。lucy开启事务之后,mary无法开启事务。有可能影响性能。
  2. 乐观锁
    在表中加上一个字段 version ,开始事务时获取这条记录的 version ,提交修改的时候比较刚开始获取的 version 和当前数据库中这条记录的 version,如果一样的话,提交修改,并将版本号加一;如果不一样的话就取消当前的修改。

在代码中使用乐观锁

  1. 在数据库表中添加version字段

  2. 对应的实体类添加版本号属性

  3. 在实体类的属性上添加注解

    @Version
    private Integer version; // 版本号
    
  4. 配置乐观锁插件 (建议写到配置类里面)

    @Configuration // 注解表示这是一个配置类
    public class MPConfig {/** 乐观锁插件,这个插件是固定的,直接复制就可以了* */@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}
    }
    
  5. 编写代码测试

    @Test
    void testLock() {  // 因为乐观锁的存在,所以一定要先查再改// 通过id查询数据User user = userMapper.selectById(1633278798692634625L);// 1633278798692634625user.setAge(200);userMapper.updateById(user);
    }
    

MP简单查询

  1. 根据id查询

    // 根据id查询数据
    User user = userMapper.selectById();
    
  2. 多个id的批量查询

    @Test
    void testSelectBench() {List<Integer> integers = Arrays.asList(1, 2, 3);List<User> users = userMapper.selectBatchIds(integers);users.forEach(System.out::println);
    }
    
  3. 简单的条件查询

    @Test
    void testSelectByMap() {  // 这种不经常使用HashMap<String, Object> map = new HashMap<>();map.put("name", "mary");map.put("age", 30);List<User> users = userMapper.selectByMap(map);for (User user : users) {System.out.println(user);}
    }
    
  4. 分页查询 (和PageHelper差不多)

    1. 配置分页插件

      @Bean  // 也是在配置类里面进行的
      public PaginationInterceptor paginationInterceptor() {return  new PaginationInterceptor();
      }
      
    2. 编写分页代码
      直接new page对象,传入两个参数,当前页和每页显示的记录数

      @Test
      void testPage() {// 创建page对象,传入参数: 当前页 和 每页小时的记录数Page<User> userPage = new Page<>(1, 3);// 调用MP中分页查询的方法// 调用MP分页查询过程中,会把查出来的数据封装到page对象里面userMapper.selectPage(userPage, null);System.out.println(userPage.getCurrent()); // 获取当前页System.out.println(userPage.getRecords()); // 每页数据list集合System.out.println(userPage.getSize());  // 每页的记录数System.out.println(userPage.getTotal()); // 表中总记录数System.out.println(userPage.getPages()); // 得到总页数System.out.println(userPage.hasNext());  // 是否有下一页System.out.println(userPage.hasPrevious()); // 是否有上一页
      }
      

删除

  • 逻辑删除:假删除,在表中还存在,但是查询查不出来了,设置是否被删除字段来实现。
  • 物理删除:真删除,将对应数据从数据库中删除。

物理删除

  1. 通过id删除

    @Test
    void testDeleteByID() {int row = userMapper.deleteById(1L);System.out.println(row);
    }
    
  2. 批量删除

    @Test
    void testDeleteBatchIds() {int row = userMapper.deleteBatchIds(Arrays.asList(2, 3));System.out.println(row);
    }
    
  3. 简单条件删除

    @Test
    void testDeleteByMap() {HashMap<String, Object> map = new HashMap<>();map.put("age", 18);int i = userMapper.deleteByMap(map);System.out.println(i);
    }
    

逻辑删除

  1. 在数据库中添加 deleted 字段

  2. 实体类添加 deleted 字段
    加上注解 @TableLogicTableField(fill = FieldFill.INSERT)

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;
    
  3. 配置类中配置逻辑删除插件

    @Bean
    public ISqlInjector sqlInjector() {return new LogicSqlInjector();
    }
    
    mybatis-plus.global-config.db-config.logic-delete-value=1 # 也可以在这里配置删除后是什么1,不删除是什么值
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
  4. 要删除的时候还是执行之前的删除方法,但是效果就变成了把 deleted 字段变成1,使用MP查询的时候我们也不需要加额外的条件,MP会自动加上 deleted 不为1这个条件。

  5. 如果想要查询被删除的记录的话,MP没有办法做到,只能通过新建 xml 文件,手写slq来实现。

性能分析

  1. 在配置类中配置性能分析插件

    /*
    * SQL执行性能分析插件
    * 开发环境使用,线上不推荐。MaxTime是指sql最大运行时长
    *
    * 环境一般有三种:
    * dev: 开发环境
    * test: 测试环境
    * prod: 生产环境, 用户真正去使用的
    * */
    @Bean
    @Profile({"dev", "test"})
    public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100);  // ms, 超过这个时间的sql不执行performanceInterceptor.setFormat(true);return performanceInterceptor;
    }
    
  2. 在配置文件中设置 SpringBoot当前环境

    
    

测试

运行代码的时候会在输出窗口看到sql的运行时长。

image-20230309084220992

如果sql运行时间超过MaxTime的话,就会抛出一个异常。

image-20230309084433976

复杂条件查询

条件查询器

image-20230309085703936

一般使用 QueryWrapper 来构件条件

  1. 创建QueryWrapper对象
  2. 添加条件
@Test
void testSelectQuery() {// 创建QueryWrapper对象QueryWrapper<User> wrapper = new QueryWrapper<>();// 通过QueryWrapper设置条件// ge, gt, le, lt// 查询age >= 30 的记录// 第一个参数是列名, 第二个参数是值
//        wrapper.ge("age", 30);// eq, ne
//        wrapper.eq("name", "东方不败");
//        wrapper.ne("name", "东方不败");// between
//        wrapper.between("age", 20, 30);// like 模糊查询
//        wrapper.like("name", "东");// orderByDesc, 排序
//        wrapper.orderByDesc("id");// last, 拼接sql语句
//        wrapper.last("limit 1");// 指定要查询的列wrapper.select("id", "name");List<User> users = userMapper.selectList(wrapper);System.out.println(users);}

相关文章:

谷粒学院开发(一):基础准备

商业模式 常见商业模式 B2C模式&#xff1a; 两个角色&#xff1a; 管理员&#xff1a;增加&#xff0c;修改&#xff0c;删除普通用户&#xff1a;查询 商家到用户&#xff0c;自己制作大量自有版权的视频&#xff0c;放在自有平台上&#xff0c;让用户付费。 这是这个项目使…...

Photoshop如何安装ZXP扩展插件?

Photoshop如何安装ZXP扩展插件呢&#xff1f;有一些小伙伴不会安装&#xff0c;今天介绍两种安装ZXP扩展的方法&#xff0c;希望对能帮助到大家。方法一&#xff1a;手动安装方式1&#xff09;把下载好的.zxp扩展名改为.zip&#xff0c;然后解压。Windows系统&#xff1a;C:\Us…...

c++面试技巧-基础篇4

1.面试官&#xff1a;在使用继承时需要注意哪些问题&#xff1f; 应聘者&#xff1a;在使用继承时需要注意以下内容。 &#xff08;1&#xff09;父类的构造函数和析构函数是不会被继承的&#xff0c;需要重写派生类的构造函数和析构函数。 &#xff08;2&#xff09;派生类…...

openEuler用户软件仓(EUR)介绍

什么是 EUR EUR(openEuler User Repo)是openEuler社区针对开发者推出的个人软件包托管平台&#xff0c;目的在于为开发者提供一个易用的软件包分发平台。 链接&#xff1a;https://eur.openeuler.openatom.cn/ 为什么我们需要 EUR 在操作系统的世界&#xff0c;软件包是一等…...

MySQL的图形化界面开发工具DataGrip的下载安装

在日常的开发中&#xff0c;会借助于MySQL的图形化界面&#xff0c;来简化开发&#xff0c;提高开发效率。目前mysql主流的图形化界面工具&#xff0c;有Navicat、SQLyog、DataGrip等&#xff0c;最后一种DataGrip&#xff0c;这种图形化界面工具&#xff0c;功能更加强大&…...

Azure Portal 访问安全性增强

Azure Portal 访问安全性增强客户需求如何设置账号&#xff08;包括Admin&#xff09;定期修改密码&#xff0c;例如强制每90天必须修改密码如何设定账号密码的复杂性要求如何设定限制访问Azure Portal的源IP Address客户需求 为了增强访问Azure Portal的安全性&#xff0c;希…...

mysql安全值守数据库常用语句

目录1.用户权限设置mysql中用户如何定义2.元数据查询3.union查询详解4.分组查询展示5.字符串函数6.mysql数据库导入导出1.用户权限设置 mysql中用户如何定义 用户名主机域有以下几种表示方式&#xff1a; 1. 10.0.0.51 2. 10.0.0.% 3. % 4. 10.0.0.0/255.255.255.0 5. Db01 6…...

CSS快速入门

文章目录一、CSS是什么&#xff1f;语法规范引入方式二、CSS选择器标签选择器类选择器ID选择器通配符选择器后代选择器子选择器并集选择器伪类选择器三、常见元素属性字体属性文本属性背景属性圆角矩形元素的显示默认块级与行级元素盒子模式去除浏览器默认样式弹性布局一、CSS是…...

emq-docker安装配置

目录 1 docker配置 2 mysql 认证 2.1 添加认证表 2.2 认证文件配置 3 系统topic docker安装&#xff1b;mysql客户端认证&#xff1b;配置系统topic 获取客户端上下线消息。文件提到配置文件见附件。 1 docker配置 docker镜像地址&#xff1a;emqx/emqx emqx_auth_mysql.…...

Bean三种实例化方式的底层原理

Bean实例化的三种方式 1&#xff0c;使用类构造器实例化&#xff08;无参构造函数&#xff09;2&#xff0c;使用静态工厂方法实例化&#xff08;简单工厂模式&#xff09;3&#xff0c;使用实例工厂方法实例化&#xff08;工厂方法模式&#xff09; 基于以上的三种方式&…...

java25种设计模式之适配器模式

1、定义 适配器模式在java中是一中结构型设计模式。 在实际的java来发中&#xff0c;有时候我们会遇到一些不能直接调用&#xff0c;或者不是客户需要的接口&#xff0c;但是却需要使用时&#xff0c;我们就可以使用适配器设计模式。 适配器设计模式就是将一个原本不兼容的接口…...

【微服务】—— 初识微服务

文章目录1. 什么是微服务1.1 微服务的特性自主专用性1.2 微服务的优势敏捷性灵活扩展轻松部署技术自由可重复使用的代码弹性2. 微服务技术栈3. 微服务架构演进3.1 单体架构3.2 分布式架构服务治理3.3 微服务微服务结构微服务技术对比企业需求1. 什么是微服务 微服务是一种开发软…...

Unity使用webSocket与服务器通信(二)——C#服务器端使用Fleck时的简单服用方法

C#服务端用到Fleck包&#xff0c;它包含哪些可用的回调函数&#xff0c;有哪些常用的api方法&#xff1f; 演示&#xff1a;服务端收到Unity用户发来的信息 1、Fleck服务器提供哪些回调函数 Fleck提供的回调函数有下面几种&#xff1a; //用户连入服务器时... Action OnOp…...

【Linux】线程概念 | 线程控制

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;知识补充&…...

pocsuite3安装及使用

pocsuite3安装及使用简介项目地址环境配置及安装环境要求安装&#xff08;详情可以参考[https://pocsuite.org/](https://pocsuite.org/)&#xff09;使用方法运行模块加载目标参数&#xff1a;Console模式查看有哪些模块使用Telnet 弱密码模块这里以flask模板注入漏洞为例pocs…...

docker从安装到部署一个项目

一.centos安装docker 参考博客&#xff1a;https://blog.csdn.net/m0_47010003/article/details/127775185 1.设置一下下载Docker的镜像源 设置下载的镜像源为国内的阿里云&#xff0c;如果不设置&#xff0c;会默认去Docker的官方下载 yum-config-manager --add-repo http…...

QT编程从入门到精通之十二:“第四章:Qt程序创建基础”之“4.1 创建基础程序”

目录 第四章:Qt程序创建基础 4.1 创建基础程序 4.1.1 新建一个项目...

黑客入门教程【非常详细】从零基础入门到精通,看这一篇就够了!

首先要明白啊&#xff0c;我们现在说的黑客不是那种窃取别人信息、攻击别人系统的黑客&#xff0c;说的是调试和分析计算机安全系统的网络安全工程师。 黑客技术的核心就是渗透攻防技术&#xff0c;是为了证明网络防御按照预期计划正常运行而提供的一种机制。就是通过模拟恶意…...

手机怎么远程控制腾讯云云服务器?

手机怎么远程控制腾讯云云服务器&#xff1f;腾讯云提供的连接&#xff1a;Windows系统。可以用远程桌面连接&#xff0c;你本地电脑点击&#xff0c;开始-运行-输入mstsc&#xff0c;弹出的框里&#xff0c;填IP和账号密码信息。 管理服务器上还会运行一个数据采集程序&#…...

dorcker与vlu靶场搭建

dorcker与vlu靶场搭建 dorcker安装 以kali linux 为例 安装必要的一些系统工具 apt update apt -y install apt-transport-https ca-certificates curl software-properties-common 添加Docker PGP key curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg …...

Unity性能优化 - Overdraw篇

一、什么是Overdraw Unity Overdraw&#xff08;超绘&#xff09;是指在渲染过程中绘制了超过一次相同像素的现象。当多个UI元素重叠时&#xff0c;每个像素都需要被多次绘制。这种绘制超出了渲染所需的最小像素数&#xff0c;因此被称为Overdraw。 二、都有哪些元素会导致Ov…...

Tp5操作mysql json函数

Tp5操作mysql json函数 官方文档介绍正常单个json数据更新没什么问题,但是某些情况可能一次修改多个,但是也不想全部替换 怎么处理?注意 :在源码中 项目\thinkphp\library\think\db\builder.php@parseData方法中 修改控制器调用:官方文档介绍 JSON字段 从V5.1.4+版本开始…...

【蓝桥杯嵌入式】PWM的设置,原理图解析与代码实现(第十一届省赛为例)——STM32

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都在这儿哦&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列专栏 - 蓝…...

Learning C++ No.13【STL No.3】

引言&#xff1a; 北京时间&#xff1a;2023/3/7/15:33&#xff0c;还有27分钟就要去上课啦&#xff01;刚刚把最近因为考试原因欠的课给还干净了&#xff0c;已经准备好今天晚上接受航哥的毒打了&#xff0c;毒打就毒打&#xff0c;咱不怕&#xff0c;只要不欠钱&#xff0c;…...

推荐收藏!10大程序员必备生产力工具

作为程序员&#xff0c;提高生产力是我们一直追求的目标。随着技术的发展&#xff0c;越来越多的工具和应用程序被开发出来&#xff0c;帮助程序员们更好地完成工作。在本文中&#xff0c;我将介绍一些程序员必备的生产力工具。 一、IDE&#xff08;集成开发环境&#xff09; …...

【项目总结】基于SSM+SpringBoot+Redis的个人博客系统项目总结

文章目录项目介绍&#xff08;开发背景&#xff09;数据库设计主要使用到的技术点前端后端自定义统一返回对象自定义拦截器加盐加密操作分页功能session持久化自定义头像的存储和获取项目编写过程中遇到的困难点困难点一&#xff08;小&#xff09;困难点二&#xff08;小&…...

从入门到精通MongoDB数据库系列之一:MongoDB简介

从入门到精通MongoDB数据库系列之一:MongoDB简介 一、易于使用二、易于扩展三、功能丰富四、性能卓越五、设计理念MongoDB是功能强大、灵活且易于扩展的通用型数据库。融合了二级索引、范围查询、排序、聚合以及地理空间索引等诸多特性。 一、易于使用 MongoDB是面向文档的数…...

大数据系列——什么是hdfs?hdfs用来干什么的?

一、什么是HDFSHDFS全称是Hadoop Distributed File System是一种分布式文件系统(HDFS使用多台计算机存储文件&#xff0c;对外提供统一操作文件的接口)Hodoop使用HDFS(Hadoop Distributed File System)作为存储系统。二、hdfs用来干什么的用于大规模数据的分布式读写&#xff0…...

云端地球2月更新了这些功能,你都用过了吗?

时光飞逝、转眼已到2023年的第三个月&#xff0c;武汉的天气也逐渐转好&#xff0c;温度步步高升。云端地球产研团队的脚步也越走越快&#xff0c;虽然春节仿佛还是昨天的事&#xff0c;但云端地球已经完成了四次迭代&#xff0c;为广大建模爱好者带来了更多实用功能&#xff0…...

基于gin-vue-admin[gin+gorm]手动实现crud(全)

使用Gin-Vue- Admin框架手动实现crud 在gva框架下自己手动实现一个CRUD的操作&#xff0c;该操作将会结合gen进行探讨学习&#xff0c;具体实现可以看下面代码的实现&#xff0c;项目目录层级分为api层&#xff0c;service层&#xff0c;model层&#xff0c;common层&#xff…...