微服务项目->在线oj系统(Java版 - 1)
相信自己,终会成功
目录
C/S架构与B/S架构
C/S架构(Client/Server,客户端/服务器架构)
特点:
优点:
缺点:
典型应用:
B/S架构(Browser/Server,浏览器/服务器架构)
特点:
优点:
缺点:
典型应用:
核心对比
发展趋势
微服务划分
微服务划分的核心目标
微服务划分原则
前端运用技术
vue核心目录:
创建 Vue 实例:
常用指令
计算属性(Computed)和侦听器(Watch)
Mybatis-plus
1. 核心功能
2.常用注解
使用建议:
准备工作介绍
架构分层解析
(1) Controller 层
(2) Service 层
(3) MyBatis(DAO 层)
(4) 连接池
(5) 数据库(MySQL)
2. 完整请求流程
3. 关键设计思想
4. 常见问题与优化
5. 扩展:对比其他架构
接口文档
接口文档的核心作用
需求种类 | 需求内容 |
业务需求 | 题目列表 刷题 竞赛列表 竞赛用户排名 比赛 自动判题 题目管理 竞赛管理 |
用户需求 | 我的竞赛 我的消息 , 获取比赛结果 查看历史竞赛排名 |
系统需求 | 用户登录 , 注册 用户登录 安全防护(身份认证 , 身份认证 . 防sql注入 . 防xxs攻击) |
C/S架构与B/S架构
C/S架构(Client/Server,客户端/服务器架构)
特点:
-
客户端:需要安装专用的客户端软件(如QQ、微信、游戏客户端)。
-
服务器:负责数据处理和业务逻辑,客户端负责用户交互和部分计算。
-
通信:通过自定义协议(如TCP/UDP)直接与服务器交互。
优点:
-
性能高:客户端可以分担计算任务,响应速度快(适合图形渲染、实时交互等场景)。
-
离线能力:部分功能可离线使用,同步数据时再连接服务器。
-
安全性:通信协议可定制,数据加密更灵活。
缺点:
-
部署维护成本高:需为不同操作系统开发客户端,升级时需要用户手动更新。
-
跨平台性差:不同系统(Windows/macOS/Linux)可能需要单独开发。
-
用户门槛:用户需主动安装客户端,推广成本高。
典型应用:
-
大型游戏(如《英雄联盟》)、即时通讯工具(如微信)、企业ERP系统。
B/S架构(Browser/Server,浏览器/服务器架构)
特点:
-
浏览器:用户通过浏览器(Chrome/Firefox等)访问,无需安装额外软件。
-
服务器:承担主要业务逻辑和数据处理,浏览器仅负责展示和简单交互。
-
通信:基于HTTP/HTTPS协议,通常通过Web服务(如RESTful API)交互。
优点:
-
跨平台性:只需兼容浏览器,支持Windows/macOS/Linux甚至移动端。
-
无需安装:用户通过URL即可访问,使用门槛低。
-
维护方便:服务端更新后,所有用户自动获取最新版本。
缺点:
-
性能受限:依赖浏览器和网络,复杂计算或图形处理能力较弱。
-
离线能力差:通常需联网使用(可通过PWA等技术部分缓解)。
-
安全性挑战:易受Web攻击(如XSS、CSRF),需额外防护。
典型应用:
-
网页邮箱(如Gmail)、在线办公(如Google Docs)、电商平台(如淘宝)
核心对比
对比维度 | C/S架构 | B/S架构 |
---|---|---|
安装部署 | 需安装客户端 | 无需安装,浏览器即可访问 |
跨平台性 | 差(需多版本适配) | 强(浏览器通用) |
性能 | 高(本地计算) | 依赖网络和浏览器性能 |
维护成本 | 高(需更新客户端) | 低(服务端统一更新) |
离线支持 | 支持 | 有限支持(需特殊技术) |
典型场景 | 实时游戏、高频交互工具 | 信息查询、在线服务 |
发展趋势
混合架构:现代应用常结合两者优势,如客户端应用内嵌Web页面(Electron、Flutter),或PWA(渐进式Web应用)提供类原生体验。
云原生趋势:B/S架构因云计算的普及更受青睐,但C/S仍在对性能要求高的领域不可替代。
根据需求选择架构:
-
需要高性能、复杂交互 → C/S
-
追求便捷性、跨平台 → B/S
微服务划分
单体架构:
可跨展现差,技术栈受限,可靠性问题
集群架构:
资源利用率低,容错与隔离性不足,部署与升级复杂
分布式架构:
高耦合度,容错与隔离性不足
微服务架构的优势:
易于开发和维护:每个微服务负责的业务比较清晰,体量小,开发和维护成本降低
容错性高:一个服务发生故障,可以使故障隔离在单个服务中,不影响整体服务故障
扩展性好:每个服务都是独立运行的,我们可以结合项目实际情况进行扩展,按需伸缩
技术选型灵活:每个微服务都是单独的团队来运维,可以根据业务特点和团队特点,选择适合的技术栈
微服务带来的挑战
服务依赖:随着服务的数量增多,服务之间的关系也会变得复杂,一个服务的更改,需要考虑对其它服务的影响
运维成本: 一个业务流程会涉及多个微服务共同完成,有更多的服务需要编译,部署,运行,甚至可能是不同的编程语言,不同的运行环境,当然也需要集群来处理故障转移等
开发和测试:一个业务流程可能涉及多个微服务共同完成,服务调用引入网络延迟,不可靠的网络,如何进行容错处理等问题
服务监控:在一个单体结果中,很容易实现服务的监控,因为所有功能都在一个服务中,微服务架构下,不仅需要对整个链路进行监控,还需要对每一个服务进行监控
负载均衡:微服务架构中的服务实例数量肯能非常庞大,因此需要有效的服务发现和负载均衡机制来管理请求流量和保证高可用性
微服务划分的核心目标
-
高内聚低耦合:每个服务专注于单一业务能力,内部功能紧密相关,服务间依赖最小化。
-
独立部署与扩展:服务可单独部署、升级和扩缩容,不影响其他服务。
-
团队自治:每个服务由独立团队全权负责(开发、运维),减少跨团队协调成本。
-
技术异构性:不同服务可根据需求选择合适的技术栈(如数据库、编程语言)。
微服务划分原则
1. 业务能力优先
-
按领域驱动设计(DDD)划分:
-
识别业务领域的限界上下文(Bounded Context),每个上下文对应一个微服务。
-
例如:电商系统中的「订单服务」、「库存服务」、「支付服务」。
-
-
避免技术维度划分:
-
错误示例:按"数据库服务"、"缓存服务"划分(应属于技术组件而非业务服务)。
-
2. 单一职责原则(SRP)
-
每个服务只解决一个核心问题,例如:
-
用户服务:仅处理用户注册、登录、权限。
-
商品服务:仅管理商品信息、分类。
-
-
判断标准:如果修改一个功能的需求频繁影响多个服务,说明划分不合理。
3. 松耦合与高内聚
-
松耦合:服务间通过API通信,避免数据库直接共享。
-
高内聚:服务内部数据和行为紧密关联,例如「订单服务」应包含订单创建、查询、状态机逻辑。
4. 团队规模匹配
-
两个披萨原则:一个微服务应由一个小团队能完全维护。
-
避免服务粒度过细导致运维复杂度爆炸。
5. 演进式设计
在线oj系统:按照业务划分
服务名称 | 具体功能 |
后台数据管理 | 题库管理、竞赛管理、C端⽤⼾管理、定时任务管理 |
用户服务 | 登录、注册、退出登录、个⼈中⼼、我的竞赛、我的消息 |
题库竞赛服务 | 题库列表、竞赛列表、竞赛报名、查看排名、竞赛或者刷题时题⽬切换、提交代 码、运⾏代码、获取代码执⾏结果 |
按照技术划分:
服务名称 | 具体功能 | 拆分原因 |
网关服务 | 统⼀的权限控制,统⼀的请求入口动态路由 转发等 | 功能即原因 |
后台数据管理 服务 | 题库管理、竞赛管理、C端用户管理 | |
定时任务服务 | 定时任务增删改查、定时任务功能实现 | 从技术的⻆度分析定时任务的执行可能需要和 多个服务配合完成。 并且定时任务的执行可能 会周期性或⻓时间占用资源。 |
登录注册服务 | 登录、注册 | 可能需要与第三方的认证服务进行交互,存在 性能瓶颈 |
用户服务 | 退出登录、个⼈中心、我的竞 赛、我的消息 | |
消息服务 | 发送消息,接收消息 | 消息种类较多,短信、站内信、邮件等等。和 多个第三⽅组件交互 |
题库竞赛服务 | 题库列表、竞赛列表、竞赛报名、查看排 名 | |
答题服务 | 竞赛或者刷题时题⽬切换、提交代码、获取 代码执⾏结果 | 竞赛.刷题时高频使用功能 |
判题服务 | 判题 | 判题逻辑可能比较复杂,不同类型的题目判题 逻辑不⼀致,存在⼤量复杂计算 |
代码沙箱服务 | 运行代码 | 与第三方组件进行交互,可能是性能瓶颈 |
服务器架构:
前端运用技术
官方文档: Vue.js - 渐进式 JavaScript 框架 | Vue.js
实战教程: Vue Mastery | The best way to learn Vue.js
Vue Router:Vue Router | Vue.js 的官方路由
vue核心目录:
node_modules:支持项目运行的依赖文件
public:存放静态资源和公共资源,如如favicon.ico网站图标
src:项目开发主要文件夹
index.html:入口的html文件
package.json:项目的描述文件
创建 Vue 实例:
const app = Vue.createApp({data() {return {message: "Hello Vue!",count: 0,};},methods: {increment() {this.count++;},},
});app.mount("#app"); // 挂载到 DOM 元素
-
data()
:定义响应式数据(数据变化时 UI 自动更新)。 -
methods
:定义方法,可在模板或 JS 中调用
常用指令
指令 | 作用 | 示例 |
---|---|---|
v-bind | 动态绑定属性 | <a :href="url"> (缩写 : ) |
v-model | 双向数据绑定(表单) | <input v-model="name"> |
v-if / v-else | 条件渲染 | <p v-if="show">Visible</p> |
v-for | 列表渲染 | <li v-for="item in items">{{ item }}</li> |
v-on | 事件监听 | <button @click="submit"> (缩写 @ ) |
v-show | 显示/隐藏(CSS display ) | <div v-show="isVisible"> |
计算属性(Computed)和侦听器(Watch)
计算属性
computed: {reversedMessage() {return this.message.split('').reverse().join('');}
}
监听器
watch: {count(newVal, oldVal) {console.log(`Count changed from ${oldVal} to ${newVal}`);}
}
适合执行异步操作或复杂逻辑
功能 | 语法 | 说明 |
---|---|---|
数据绑定 | {{ }} 或 v-bind | 动态显示数据 |
事件绑定 | @click 或 v-on | 处理用户交互 |
条件渲染 | v-if / v-show | 控制元素显示 |
列表渲染 | v-for | 循环渲染数组 |
双向绑定 | v-model | 表单输入绑定 |
组件化 | app.component() | 复用 UI 逻辑 |
Mybatis-plus
MyBatis-Plus 🚀 为简化开发而生MyBatis-plus:MyBatis-Plus 🚀 为简化开发而生
MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。主要特性包括:
-
无侵入:只增强不修改 MyBatis 原有功能。
-
强大的 CRUD 操作:内置通用 Mapper 和 Service,减少 SQL 编写。
-
支持 Lambda 表达式:避免硬编码字段名。
-
多种主键策略:支持 UUID、雪花算法等。
-
分页插件:简化分页查询。
-
动态表名:支持运行时动态切换表名。
添加依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
创建实体类(示例)
@Data // Lombok 注解,自动生成 getter/setter
@TableName("user") // 指定表名(如果表名和类名一致可省略)
public class User {@TableId(type = IdType.AUTO) // 主键自增private Long id;private String name;private Integer age;private String email;
}
配置数据源
# application.yml
spring:datasource:url: jdbc:mysql://localhost:3306/mp_demo?useSSL=falseusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
创建 Mapper 接口
public interface UserMapper extends BaseMapper<User> {// 无需写 XML,继承 BaseMapper 即拥有 CRUD 方法
}
1. 核心功能
(1) 条件构造器(Wrapper)
用于构建动态 SQL 条件,支持链式调用。
// 查询 age > 18 且 name 包含 "张" 的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18).like("name", "张");
List<User> users = userMapper.selectList(wrapper);// Lambda 写法(避免硬编码字段名)
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.gt(User::getAge, 18).like(User::getName, "张");
List<User> users = userMapper.selectList(lambdaWrapper);
(2) 分页查询
// 配置分页插件
@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}
}// 使用分页
@Test
void testPage() {Page<User> page = new Page<>(1, 10); // 当前页,每页条数userMapper.selectPage(page, null);System.out.println("总记录数:" + page.getTotal());page.getRecords().forEach(System.out::println);
}
(3) 自定义 SQL
<!-- UserMapper.xml -->
<select id="selectUserByName" resultType="User">SELECT * FROM user WHERE name = #{name}
</select>
// Mapper 接口
public interface UserMapper extends BaseMapper<User> {User selectUserByName(@Param("name") String name);
}
2.常用注解
注解 | 作用 | 示例 |
---|---|---|
@TableName | 指定表名 | @TableName("sys_user") |
@TableId | 指定主键 | @TableId(type = IdType.AUTO) |
@TableField | 指定字段映射 | @TableField("user_name") |
@Version | 乐观锁字段 | @Version private Integer version; |
@EnumValue | 枚举字段存储值 | @EnumValue private StatusEnum status; |
使用建议:
-
避免全表扫描:使用
QueryWrapper
或LambdaQueryWrapper
添加条件。 -
逻辑删除:配置
@TableLogic
实现软删除。 -
性能优化:
-
使用
selectById
替代selectList
查询单条数据。 -
批量操作使用
insertBatch
或updateBatchById
。
-
准备工作介绍
架构分层解析
(1) Controller 层
-
作用:接收 HTTP 请求(如浏览器、API 调用),解析参数,调用 Service 层处理业务逻辑,并返回响应(JSON/页面)。
(2) Service 层
-
作用:处理核心业务逻辑(如订单创建、支付),调用 DAO(如 MyBatis Mapper)操作数据。
(3) MyBatis(DAO 层)
-
作用:负责与数据库交互,执行 SQL 查询/更新,将结果映射为 Java 对象。
-
关键组件:
-
Mapper 接口:定义数据库操作方法。
-
XML/注解 SQL:编写具体 SQL 语句。
-
(4) 连接池
-
作用:管理数据库连接,避免频繁创建/销毁连接带来的性能开销。
-
常见实现:
-
HikariCP(Spring Boot 默认)
-
Druid(阿里开源,带监控功能)
-
-
连接池工作流程:
-
应用启动时初始化多个连接(如图中的
连接1~4
)。 -
请求到达时从池中获取空闲连接。
-
使用完毕后归还连接,而非直接关闭。
-
(5) 数据库(MySQL)
-
作用:持久化存储数据,执行 SQL 语句并返回结果。
2. 完整请求流程
-
HTTP 请求 →
Controller
接收并解析参数。 -
业务逻辑 →
Service
处理业务(如校验、计算)。 -
数据操作 →
MyBatis
通过 Mapper 执行 SQL。 -
连接管理 → 从
连接池
获取连接,访问MySQL
。 -
返回结果 → 数据原路返回,最终由
Controller
响应给客户端。
3. 关键设计思想
-
分层解耦:各层职责单一,便于维护和扩展(如替换 MySQL 为 Oracle 只需修改 MyBatis 配置)。
-
连接池优化:复用连接,减少 TCP 握手和数据库认证开销。
-
ORM 映射:MyBatis 自动将数据库记录转为 Java 对象,避免手动解析 ResultSet。
4. 常见问题与优化
问题 | 解决方案 |
---|---|
Service 层事务失效 | 使用 @Transactional 注解。 |
连接池耗尽 | 调整连接数(如 spring.datasource.hikari.maximum-pool-size=20 )。 |
MyBatis 性能慢 | 开启二级缓存、优化 SQL。 |
5. 扩展:对比其他架构
-
无连接池:每次请求新建连接,高并发时数据库崩溃。
-
Service 和 Controller 合并:违反单一职责原则,难以维护。
-
直接 JDBC 替代 MyBatis:需手动处理结果集映射,代码冗余。
接口文档
接口文档(API Documentation)是开发人员编写的技术说明文件,用于描述系统提供的 API(应用程序编程接口) 的功能、参数、请求方式、返回数据格式等信息。它是前后端开发、测试、运维团队协作的重要依据。
接口文档的核心作用
-
明确接口规范
-
定义请求方法(GET/POST/PUT/DELETE)、URL、参数、返回值,避免前后端联调时出现歧义。
-
-
提高协作效率
-
前端开发无需等待后端完成,即可根据文档模拟数据;测试人员可直接根据文档编写用例。
-
-
降低维护成本
-
新成员通过文档快速理解系统接口设计,减少沟通成本。
-
-
支持自动化工具
-
Swagger、Postman 等工具可基于文档自动生成测试用例或 Mock 服务。
-
模块 | 说明 |
---|---|
接口基本信息 | 接口名称、版本、作者、更新时间等。 |
请求方式 | HTTP 方法(如 GET /api/users )。 |
请求参数 | Query 参数、Path 参数、Body 参数(类型、是否必填、示例值)。 |
响应数据 | 成功/失败的返回格式(字段说明、状态码、示例)。 |
错误码 | 定义全局或接口特定的错误码(如 401 Unauthorized )。 |
安全认证 | 描述鉴权方式(如 Token、OAuth2)。 |
调用限制 | 频率限制(如 100 次/分钟)、权限要求(如管理员角色)。 |