# m-server 轻量级Web开发框架
**Repository Path**: huhuanan/m-server
## Basic Information
- **Project Name**: m-server 轻量级Web开发框架
- **Description**: 一个轻量级、高性能的 Java Web 全栈框架。从零构建,不依赖 Spring 等第三方 Web 框架,仅使用 JDK 8 + MySQL 驱动 + FastJSON2 三个依赖,即可提供完整的 Web 服务器、ORM、缓存、任务调度能力。
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-02-24
- **Last Updated**: 2026-05-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# m-server
一个轻量级、高性能的 Java Web 全栈框架。从零构建,不依赖 Spring 等第三方 Web 框架,仅使用 **JDK 8 + MySQL 驱动 + FastJSON2** 三个依赖,即可提供完整的 Web 服务器、ORM、缓存、任务调度能力。
## 特性
- **自研 Web 服务器** — 基于 Socket 的 HTTP/HTTPS 服务器,内置线程池与 SSL/TLS 支持
- **注解驱动 ORM** — 通过 `@TableMeta`、`@FieldMeta` 等注解定义模型,自动建表,支持联表查询与多数据源
- **Action 路由体系** — `@ActionRequest` + `@RequestMethod` 注解映射 URL 到 Java 方法,支持参数绑定、声明式事务
- **三级缓存架构** — 单键、双键、列表三种缓存类型,支持分布式节点分区与自动过期清理
- **灵活任务调度** — `@TaskStartRunMeta`(间隔执行)和 `@TaskTimerRunMeta`(Cron 定时)两种调度模式
- **安全防护** — URL 白名单、Referer 校验、授权头匹配、敏感字段自动过滤
- **极简部署** — 单 JAR + lib 目录,`java -jar` 一行命令启动
## 目录
- [技术栈](#技术栈)
- [功能概览](#功能概览)
- [项目架构](#项目架构)
- [整体分层](#整体分层)
- [请求处理流程](#请求处理流程)
- [核心模块详解](#核心模块详解)
- [快速开始](#快速开始)
- [环境与配置](#环境与配置)
- [定义 Model](#定义-model)
- [定义 Action](#定义-action)
- [定义 Service](#定义-service)
- [定义定时任务](#定义定时任务)
- [配置路由与访问控制](#配置路由与访问控制)
- [使用缓存](#使用缓存)
- [引用框架](#引用框架)
- [框架优势](#框架优势)
## 技术栈
| 组件 | 选型 | 说明 |
|------|------|------|
| JDK | 1.8+ | 最低版本要求 |
| Web 服务器 | 自研 Socket 服务器 | 固定线程池,支持 HTTP / HTTPS |
| JSON | FastJSON2 2.0.61 | 请求解析与序列化 |
| 数据库 | MySQL 8.0 | 自研连接池与 ORM 映射 |
| 构建工具 | Maven | 打包与依赖管理 |
Maven 依赖仅两项:
```xml
mysql
mysql-connector-java
8.0.33
com.alibaba.fastjson2
fastjson2
2.0.61
```
## 功能概览
### Web 服务器
| 功能 | 说明 |
|------|------|
| HTTP/HTTPS | 基于 ServerSocket,配置 JKS 证书即启用 HTTPS |
| 线程池 | 固定大小线程池处理并发连接,池大小根据数据库连接数自动计算 |
| 请求解析 | 支持 GET/POST/PUT/DELETE,解析 JSON、URL 编码、Multipart/FormData |
| 响应输出 | 支持 JSON 响应、文件下载、字节流输出、页面重定向 |
| 会话管理 | ThreadLocal 隔离的 Session,同时支持 Cookie 和 Authorization Header |
### ORM 模型层
| 功能 | 说明 |
|------|------|
| 注解建模 | `@TableMeta` 定义表,`@FieldMeta` 定义列,`@LinkTableMeta` 定义外键关联 |
| 自动建表 | 启动时扫描 Model 注解,自动创建/更新数据库表结构 |
| CRUD 操作 | `saveModel`(自动判断新增/修改)、`insertModel`、`updateModel`、`deleteModel`,均支持批量 |
| 条件查询 | `QueryCondition` 构建器支持 `eq`、`like`、`in`、`between`、`isNotNull` 等条件 |
| 分页查询 | `QueryPage` 支持自动分页,返回数据列表与总数 |
| 联表查询 | `@LinkTableMeta` 自动 JOIN 关联表,支持多级关联 |
| 自定义 SQL | `ModelQuery` 流式 API 支持自定义字段表达式与原生 SQL 片段 |
| 多数据源 | 每个 Model 通过 `@TableMeta(db="xxx")` 指定不同数据库 |
### 数据库层
| 功能 | 说明 |
|------|------|
| 连接池 | 固定大小数组连接池,线程安全获取/释放,自动验证连接有效性 |
| 事务管理 | ThreadLocal 事务管理,支持声明式(`transaction=true`)和编程式事务 |
| 嵌套事务 | 最外层事务生效,内层事务自动加入 |
| 事务回调 | `pushCommitBackCall()` 注册事务提交后执行的回调 |
| SQL 日志 | Debug 模式下打印完整 SQL 语句、参数值与执行耗时 |
### 缓存系统
| 类型 | 接口 | 说明 |
|------|------|------|
| 单键缓存 | `FlushCache` | 一个 Key 对应一个对象,自动加载 |
| 双键缓存 | `FlushCache2` | 两个 Key 联合定位,适用于复合条件 |
| 列表缓存 | `FlushCacheList` | 一个 Key 对应一个列表 |
| 通用缓存 | `CacheHost` | Key-Value 缓存,默认 TTL 30 分钟,自动过期清理 |
所有缓存内置容量上限保护,超过阈值自动淘汰。
### 任务调度
| 注解 | 说明 |
|------|------|
| `@TaskStartRunMeta(init=true, interval=60)` | 启动时立即执行,之后每 N 秒执行一次 |
| `@TaskTimerRunMeta(hour={9}, minute={0,30})` | Cron 风格定时,支持年/月/日/时/分/秒/周匹配 |
任务在线程池中执行,防止线程数爆炸;同一任务串行执行,防止并发重叠。
### 安全机制
| 功能 | 配置方式 | 说明 |
|------|----------|------|
| URL 白名单 | `urlmarker.xml` `` | 仅允许配置的路径访问 |
| URL 重定向 | `` | 访问指定路径时自动重定向 |
| Referer 校验 | `` | 验证请求来源域名 |
| 授权头匹配 | `` | 支持 Authorization Header 前缀匹配 |
| 浏览器缓存 | `` | 配置 Cache-Control 响应头 |
| 自定义 Header | `` | 添加自定义安全响应头 |
| 敏感字段过滤 | `mconfig.properties` `secret_field` | 查询结果自动移除指定字段 |
| 扩展名拦截 | 内置 | 自动拦截 `.php`、`.jsp`、`.do`、`.action` 等请求 |
## 项目架构
### 整体分层
```
m-server
├── m.server # Web 服务器层
│ ├── TcpServer # TCP 服务器(线程池 + SSL)
│ ├── ServerHandler # Socket 处理抽象类
│ └── web/
│ ├── WebHandler # HTTP 请求处理器
│ ├── Request # HTTP 请求解析
│ ├── Response # HTTP 响应构建
│ ├── ActionRedirect # Action 执行器(事务 + 反射)
│ ├── AuthInfoUtil # 会话管理(ThreadLocal)
│ └── req/res # 请求/响应相关类型定义
│
├── m.common # 通用业务框架层
│ ├── action/
│ │ ├── Action # 控制器基类
│ │ ├── ActionRequest # 类级路由注解
│ │ ├── RequestMethod # 方法级路由注解
│ │ └── Param # 参数绑定注解
│ ├── model/
│ │ ├── Model # 模型基类(oid 主键)
│ │ ├── TableMeta # 表注解
│ │ ├── FieldMeta # 字段注解
│ │ ├── LinkTableMeta # 外键关联注解
│ │ ├── config/ModelConfig # 模型元数据注册中心
│ │ └── util/ # ORM 工具(查询/更新/条件/分页)
│ └── service/
│ └── Service # 业务逻辑基类(CRUD 封装)
│
└── m.system # 系统基础设施层
├── db/ # 数据库(连接池、SQL 执行、事务管理)
├── cache/ # 缓存(内存缓存、分布式节点分区)
├── task/ # 任务调度(线程池、间隔任务、Cron 定时任务)
├── url/UrlMarker # XML 路由与访问控制
├── listener/ # 系统初始化与组件扫描
└── util/ # 工具类(字符串、日期、反射、ID 生成等)
```
### 请求处理流程
```
TcpServer.start(port)
│
Socket accept (线程池)
│
WebHandler
│
┌─────────┴─────────┐
│ Request 解析 │ HTTP 方法、URI、Header、Body
└─────────┬─────────┘
│
┌─────────┴─────────┐
│ AuthInfoUtil.init │ ThreadLocal 绑定 Session
└─────────┬─────────┘
│
┌─────────┴─────────┐
│ UrlMarker 过滤 │ 重定向、白名单、Referer、授权
└─────────┬─────────┘
│
┌─────────┴─────────┐
│ ActionUtil 路由 │ URL → Action 类 + 方法
└─────────┬─────────┘
│
┌─────────┴─────────┐
│ ActionRedirect │ 反射调用,可选事务包装
│ ├─ beforeExecute │
│ ├─ Action.method │ ← 业务逻辑在这里
│ ├─ afterExecute │
│ └─ exceptionExe │
└─────────┬─────────┘
│
┌─────────┴─────────┐
│ Response 输出 │ JSON / 文件 / 重定向
└─────────┬─────────┘
│
资源清理关闭
```
### 核心模块详解
#### 1. Web 服务器(m.server)
- **TcpServer**:基于 `ServerSocket` 的 TCP 服务器,使用固定大小线程池处理并发请求
- **SSL 支持**:配置 JKS 证书后自动启用 HTTPS
- **WebHandler**:继承 `ServerHandler`,负责完整的 HTTP 请求生命周期
#### 2. Action 控制器(m.common.action)
通过注解将 URL 映射到 Java 方法:
- `@ActionRequest(name="路径")` — 标注 Action 类,定义 URL 前缀
- `@RequestMethod(name="路径")` — 标注方法,定义完整 URL
- `@Param("参数名")` — 标注方法参数,从请求中取值
Action 基类提供三个生命周期钩子:
- `beforeExecute()` — 方法执行前
- `afterExecute()` — 方法执行后
- `exceptionExecute()` — 方法异常时
#### 3. ORM 模型层(m.common.model)
基于注解的元数据驱动 ORM:
| 注解 | 作用 | 示例 |
|------|------|------|
| `@TableMeta` | 定义表名、数据源 | `@TableMeta(name="t_user", db="default")` |
| `@FieldMeta` | 定义列名、类型、长度 | `@FieldMeta(name="username", type=FieldType.STRING, length=50)` |
| `@LinkTableMeta` | 定义外键关联 | `@LinkTableMeta(name="role_id")` |
| `@KeyFieldMeta` | 定义主键 | `@KeyFieldMeta(name="oid")` |
支持操作:
- **查询**:主键查询、条件查询、分页查询、联表查询、自定义 SQL
- **更新**:新增、修改、保存(自动判断 insert/update)、批量操作、删除
- **自动建表**:启动时根据 Model 注解自动创建/更新表结构
#### 4. 数据库层(m.system.db)
- **DBConnection**:固定大小连接池,线程安全获取/释放连接
- **DBManager**:SQL 执行器,支持增删改查和批量操作
- **TransactionManager**:ThreadLocal 事务管理,支持声明式事务和嵌套事务
- **多数据源**:每个 Model 可指定不同的数据库
#### 5. 缓存系统(m.system.cache)
提供三种缓存接口:
| 类型 | 接口 | 适用场景 |
|------|------|----------|
| 单键缓存 | `FlushCache` | 一个 Key 对应一个对象 |
| 双键缓存 | `FlushCache2` | 两个 Key 联合定位一个对象 |
| 列表缓存 | `FlushCacheList` | 一个 Key 对应一个列表 |
默认 TTL 30 分钟,内置容量上限保护,支持分布式节点分区存储。
#### 6. 任务调度(m.system.task)
两种任务注解:
- **`@TaskStartRunMeta`** — 间隔执行任务
```java
@TaskStartRunMeta(init=true, interval=60) // 启动时立即执行,之后每60秒执行一次
public void refreshCache() { ... }
```
- **`@TaskTimerRunMeta`** — Cron 定时任务
```java
@TaskTimerRunMeta(hour={9}, minute={0,30}) // 每天 9:00 和 9:30 执行
public void dailyReport() { ... }
```
#### 7. 路由与安全(m.system.url.UrlMarker)
通过 `urlmarker.xml` 配置:
- **redirect** — URL 重定向
- **enable** — 访问白名单
- **cache** — 浏览器缓存策略
- **referer** — 来路域名校验
- **authorization** — 授权头前缀匹配
- **header** — 自定义响应头
## 快速开始
### 环境与配置
**1. 前置条件**
- JDK 1.8+
- MySQL 8.0+
- Maven 3.x
**2. 创建数据库**
```sql
CREATE SCHEMA mserver CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
```
**3. 配置数据库**(`src/main/resources/dbconfig.properties`)
```properties
db_driver=com.mysql.cj.jdbc.Driver
db_url=jdbc:mysql://127.0.0.1:3306/mserver?useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
db_username=root
db_password=your_password
db_init_connect=SET NAMES utf8mb4 COLLATE utf8mb4_general_ci
db_max_connect=100
db_query_timeout=600
# 节点编号 (0-35),多节点部署时各节点设置不同值
node_index=1
# 调试模式,打印 SQL 日志
debug=true
# 输出日志到文件
out_log=false
# JKS 证书路径(不配置则启动 HTTP,配置则启动 HTTPS)
jks_cert=
jks_pass=
```
**4. 配置包扫描路径**(`src/main/resources/config/mconfig.properties`)
```properties
# Model 所在包,多个用逗号分隔
model_pack=com.example.model
# Action 所在包,多个用逗号分隔
action_pack=com.example.action
# Task 所在包,多个用逗号分隔
task_pack=com.example.task
# 敏感字段(查询时自动过滤)
secret_field=password,secret
```
**5. 启动服务**
```bash
# Maven 打包
mvn clean package
# 运行(默认端口 9999)
java -jar m-server-1.0-SNAPSHOT.jar
# 指定端口
java -jar m-server-1.0-SNAPSHOT.jar 8080
```
启动成功后输出:`服务启动成功,端口:9999`
### 定义 Model
```java
@TableMeta(name="t_user")
public class UserModel extends Model {
@FieldMeta(name="username", type=FieldType.STRING, length=50)
private String username;
@FieldMeta(name="age", type=FieldType.INT)
private Integer age;
@FieldMeta(name="email", type=FieldType.STRING, length=100)
private String email;
@LinkTableMeta(name="dept_id")
private DeptModel dept;
// getter/setter ...
}
```
启动时自动在数据库中创建 `t_user` 表(如果不存在)。
### 定义 Action
```java
@ActionRequest(name="user")
public class UserAction extends Action {
@RequestMethod(name="list")
public JSONMessage list(@Param("page") int page, @Param("size") int size) throws Exception {
Service service = getService();
// 使用 ModelQueryList 进行分页查询
QueryPage queryPage = new QueryPage(page, size);
// ... 查询逻辑
return new JSONMessage().push("list", resultList).push("total", total);
}
@RequestMethod(name="save", transaction=true)
public JSONMessage save() throws Exception {
Service service = getService();
UserModel user = getRequest().getRequestJson().toJavaObject(UserModel.class);
service.saveModel(user);
return new JSONMessage().push("oid", user.getOid());
}
@RequestMethod(name="delete", transaction=true)
public JSONMessage delete(@Param("oid") String oid) throws Exception {
Service service = getService();
UserModel user = new UserModel();
user.setOid(oid);
service.deleteModel(user);
return new JSONMessage();
}
}
```
以上 Action 对应的访问 URL 为:
- `POST /user/list` — 用户列表
- `POST /user/save` — 保存用户
- `POST /user/delete` — 删除用户
### 定义 Service
```java
public class UserService extends Service {
public UserModel findByUsername(String username) throws Exception {
return getModel(UserModel.class,
new String[]{"oid", "username", "email"},
QueryCondition.eq("username", username)
);
}
public List listByDept(String deptOid) throws Exception {
// 使用 ModelQueryList 构建复杂查询
// ...
}
}
```
### 定义定时任务
```java
public class DataTask {
@TaskStartRunMeta(init=true, interval=300)
public void refreshCache() {
// 启动时立即执行,之后每 300 秒执行一次
}
@TaskTimerRunMeta(hour={2}, minute={0})
public void dailyCleanup() {
// 每天凌晨 2:00 执行
}
}
```
### 配置路由与访问控制
编辑 `src/main/resources/config/urlmarker.xml`:
```xml
```
### 使用缓存
```java
// 实现 FlushCache 接口
public class UserCache implements FlushCache {
@Override
public UserModel getCacheModel(String key) {
// 从数据库加载
return ...
}
}
// 使用
UserModel user = CacheUtil.get(UserCache.class, "user_001");
```
## 引用框架
> 示例项目:[m.member 会员管理系统H5版](https://gitee.com/huhuanan/m.member)
>
> 管理端开发平台:[m-server.manage 轻量级权限管理开发框架(含工作流)](https://gitee.com/huhuanan/m-server.manage)
### 方式一:Maven 本地仓库引用(推荐)
配置简单,框架更新时重新 `mvn install` 即可同步。
**1. 安装框架到本地仓库**
```bash
git clone https://gitee.com/huhuanan/m-server.git
cd m-server
mvn install
```
**2. 在新项目 pom.xml 中添加依赖**
```xml
m
m-server
1.0-SNAPSHOT
```
**3. 拷贝配置文件**
将框架 `src/main/resources/` 下的配置文件拷贝到新项目对应目录,根据实际情况修改数据库连接等配置:
- `dbconfig.properties` — 数据库连接配置
- `config/mconfig.properties` — 包扫描路径配置
- `config/urlmarker.xml` — 路由与访问控制配置
**4. 添加启动入口**
拷贝 `Start.java` 到新项目的 Java 源码目录,作为启动类。
### 方式二:本地 JAR 引用
框架更新时将新打包的 JAR 替换到 `lib` 目录即可,无需重新 install。
**1. 打包并拷贝 JAR**
```bash
cd m-server
mvn clean package
cp target/m-server-1.0-SNAPSHOT.jar your-project/lib/
```
**2. 在新项目 pom.xml 中添加依赖和打包配置**
```xml
m
m-server
1.0-SNAPSHOT
system
${pom.basedir}/lib/m-server-1.0-SNAPSHOT.jar
mysql
mysql-connector-java
8.0.33
com.alibaba.fastjson2
fastjson2
2.0.61
org.apache.maven.plugins
maven-jar-plugin
2.6
true
lib/
Start
lib/m-server-1.0-SNAPSHOT.jar
```
**3. 拷贝配置文件和启动入口**(同方式一的步骤 3-4)
### 方式三:源码集成
直接基于框架源码开发,可自由修改框架内部代码。适合需要深度定制框架的场景。
**方式 A — 克隆后直接开发**
```bash
git clone https://gitee.com/huhuanan/m-server.git your-project
cd your-project
# 修改目录名和 pom.xml 中的 groupId/artifactId
```
**方式 B — 拷贝源码到已有项目**
将框架 `src/main/java/` 和 `src/main/resources/` 下的全部文件拷贝到新项目对应目录,然后在 `pom.xml` 中添加 MySQL 和 FastJSON2 依赖即可。
## 框架优势
| 优势 | 说明 |
|------|------|
| **极简依赖** | 仅 MySQL 驱动 + FastJSON2,无 Spring 体系庞大依赖链,JAR 包体积极小 |
| **启动快速** | 无 IoC 容器初始化和组件扫描开销,毫秒级启动 |
| **资源占用低** | 无反射代理、无字节码增强,内存占用远低于 Spring Boot |
| **全栈自研** | Web 服务器、ORM、缓存、任务调度一体化,无整合适配问题 |
| **注解驱动** | Model、Action、Task 均通过注解声明,约定优于配置 |
| **自动建表** | 根据 Model 注解自动创建和更新数据库表结构,减少手动维护 |
| **声明式事务** | `@RequestMethod(transaction=true)` 一行注解开启事务,也可编程式管理 |
| **灵活查询** | 支持主键查询、条件构造器、分页、联表、自定义 SQL 等多种查询方式 |
| **多数据源** | 每个 Model 可指定不同的数据库,天然支持分库 |
| **分布式友好** | 节点索引分区(0-35)、分布式 ID 生成器,可横向扩展 |
| **安全可控** | URL 白名单、Referer 校验、授权头匹配、敏感字段过滤等多层安全机制 |
| **SSL 内置** | 配置 JKS 证书即启用 HTTPS,无需外部代理 |
| **易于部署** | 单 JAR + lib 目录,`java -jar` 即可运行,不依赖容器 |
---
> 适用场景:中小型后端服务、API 服务、微服务轻量节点、对启动速度和资源占用有要求的场景。