解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# HttpServer 使用手册
本文档基于æºç `NewLife.Core/Http/HttpServer.cs`,用于说明 `HttpServer`(轻é‡çº§ HTTP æœåŠ¡å™¨ï¼‰çš„èŒè´£ã€è·¯ç”±æ³¨å†Œæ–¹å¼ã€åŒ¹é…规则与使用注æ„事项。
> 关键è¯ï¼šè·¯ç”±æ˜ å°„ã€é€šé…符 `*`ã€å§”托处ç†å™¨ã€æŽ§åˆ¶å™¨æ˜ å°„ã€é™æ€æ–‡ä»¶ã€åŒ¹é…缓å˜ã€çº¿ç¨‹å®‰å…¨ã€‚
---
## 1. 概述
`HttpServer` 继承自 `NetServer` 并实现 `IHttpHost`,用于在 TCP 连接之上æä¾› HTTP å议处ç†èƒ½åŠ›ã€‚
主è¦èŒè´£ï¼š
1. ä¿å˜è·¯ç”±æ˜ å°„ `Routes`ï¼Œå¹¶åœ¨æ”¶åˆ°è¯·æ±‚æ—¶æ ¹æ®è·¯å¾„åŒ¹é… `IHttpHandler`ï¼›
2. 为æ¯ä¸ªç½‘络会è¯åˆ›å»ºå¯¹åº”çš„ `HttpSession` å议处ç†å™¨ï¼ˆ`CreateHandler`);
3. æä¾›å¤šç§ `Map` é‡è½½ï¼ˆå§”托/控制器/陿€æ–‡ä»¶ï¼‰ä»¥ç®€åŒ–注册。
---
## 2. 默认行为与关键属性
### 2.1 基础é…ç½®
æž„é€ å‡½æ•°ä¸ï¼Œ`HttpServer` 的默认é…置为:
- `Name = "Http"`
- `Port = 80`
- `ProtocolType = NetType.Http`
- `ServerName = "NewLife-HttpServer/{Major}.{Minor}"`(从程åºé›†ç‰ˆæœ¬ç”Ÿæˆï¼‰
### 2.2 `ServerName`
- 类型:`String`
- è¯ä¹‰ï¼šç”¨äºŽ HTTP å“应头ä¸çš„ `Server` å称(具体写入由åè®®æ ˆå…¶å®ƒéƒ¨åˆ†å®Œæˆï¼‰ã€‚
### 2.3 `Routes`
- 类型:`IDictionary<String, IHttpHandler>`
- Key:路径(区分大å°å†™è§„则:ä¸åŒºåˆ†ï¼Œ`StringComparer.OrdinalIgnoreCase`)
- Value:处ç†å™¨ï¼ˆ`IHttpHandler`)
说明:
- 路由 Key 会在注册时统一确ä¿ä»¥ `/` 开头。
- åŽæ³¨å†Œä¼šè¦†ç›–先注册(`Routes[path] = handler`)。
---
## 3. 会è¯ä¸Žå议处ç†
### 3.1 `CreateHandler(INetSession session)`
`HttpServer` 会为æ¯ä¸€ä¸ªåº•层网络会è¯åˆ›å»ºä¸€ä¸ªæ–°çš„ `HttpSession`:
- 返回:`new HttpSession()`
è¿™æ„味ç€ï¼š
- HTTP è§£æžã€è¯·æ±‚/å“应生命周期逻辑主è¦ç”± `HttpSession` 承担;
- `HttpServer` æ›´èšç„¦åœ¨â€œè·¯ç”±è¡¨ç»´æŠ¤â€å’Œâ€œåŒ¹é…处ç†å™¨â€ã€‚
---
## 4. 路由注册 API
`HttpServer` æä¾›å¤šç§è·¯ç”±æ³¨å†Œæ–¹å¼ï¼Œæœ€ç»ˆç»Ÿä¸€èµ°ç§æœ‰æ–¹æ³• `SetRoute(String path, IHttpHandler handler)`。
### 4.1 æ˜ å°„å¤„ç†å™¨å®žä¾‹
```csharp
var server = new HttpServer();
server.Map("/api/test", new MyHandler());
```
- `Map(String path, IHttpHandler handler)`
### 4.2 æ˜ å°„å§”æ‰˜ï¼ˆDelegate)
é€‚ç”¨äºŽå¿«é€Ÿæ³¨å†Œè½»é‡æŽ¥å£ã€‚
- `Map(String path, HttpProcessDelegate handler)`
- `Map<TResult>(String path, Func<TResult> handler)`
- `Map<TModel, TResult>(String path, Func<TModel, TResult> handler)`
- `Map<T1, T2, TResult>(String path, Func<T1, T2, TResult> handler)`
- `Map<T1, T2, T3, TResult>(String path, Func<T1, T2, T3, TResult> handler)`
- `Map<T1, T2, T3, T4, TResult>(String path, Func<T1, T2, T3, T4, TResult> handler)`
说明:
- 这些é‡è½½ä¼šåˆ›å»º `DelegateHandler` 并把委托赋值到 `Callback`。
示例:
```csharp
server.Map("/health", () => "OK");
```
### 4.3 æ˜ å°„æŽ§åˆ¶å™¨
```csharp
server.MapController<MyController>();
```
- `MapController<TController>(String? path = null)`
- `MapController(Type controllerType, String? path = null)`
规则:
- `path` 为空时:默认为 `/{ControllerName}`ï¼Œå…¶ä¸ ControllerName æ¥è‡ª `controllerType.Name.TrimEnd("Controller")`。
- 控制器路由最终会被规范化为:`/{xxx}/*`。
- 注册的处ç†å™¨ç±»åž‹ä¸º `ControllerHandler`,其 `ControllerType` 指å‘ç›®æ ‡æŽ§åˆ¶å™¨ç±»åž‹ã€‚
示例:
```csharp
server.MapController<MyController>("/api");
// 实际注册路由为 /api/*
```
### 4.4 æ˜ å°„é™æ€æ–‡ä»¶ç›®å½•
```csharp
server.MapStaticFiles("/js", "./wwwroot/js");
```
- `MapStaticFiles(String path, String contentPath)`
规则:
- `path` 会确ä¿ä»¥ `/` 开头;
- 实际用于匹é…的路由 Key 为 `path.EnsureEnd("/").EnsureEnd("*")`,例如 `/js/*`ï¼›
- `StaticFilesHandler.Path` 为 `path.EnsureEnd("/")`(例如 `/js/`);
- `StaticFilesHandler.ContentPath` ä¸ºä¼ å…¥çš„ `contentPath`。
---
## 5. 路由设置规范化(`SetRoute`)
所有路由注册最终统一到:
- 傿•°æ ¡éªŒï¼š
- `path` ä¸èƒ½ä¸ºç©º
- `handler` ä¸èƒ½ä¸ºç©º
- 路径规范化:
- `path = path.EnsureStart("/")`
- 覆盖è¯ä¹‰ï¼š
- `Routes[path] = handler`
注æ„:
- `SetRoute` ä¸ä¼šè‡ªåŠ¨è¡¥é½å°¾éƒ¨ `/` 或 `*`,这由 `MapController` / `MapStaticFiles` 负责。
---
## 6. 路由匹é…规则(`MatchHandler`)
`MatchHandler(String path, HttpRequest? request)` ç”¨äºŽæ ¹æ®â€œå·²è§„范化åŽçš„请求路径(ä¸å«æŸ¥è¯¢å—符串)â€åŒ¹é…处ç†å™¨ã€‚
匹é…顺åºï¼š
1. **精确匹é…**:`Routes.TryGetValue(path, out handler)`
2. **缓å˜å‘½ä¸**:
- `_pathCache.TryGetValue(path, out p)`
- ç„¶åŽ `Routes.TryGetValue(p, out handler)`
3. **通é…符匹é…**:枚举 `Routes`ï¼Œå¯¹åŒ…å« `*` çš„ key 执行:
- `key.IsMatch(path)`
### 6.1 通é…符约定
- 仅当路由 key åŒ…å« `*` 时,æ‰è¿›å…¥æ¨¡ç³ŠåŒ¹é…。
- 匹é…逻辑ä¾èµ– `IsMatch` 扩展方法(æ¥è‡ªåŸºç¡€åº“å—符串匹é…能力)。
### 6.2 匹é…ç¼“å˜ `_pathCache`
- 类型:`IDictionary<String, String>`
- Key:请求路径 `path`
- Value:命ä¸çš„路由 key(例如 `/api/*`)
缓å˜ç–略:
- å‘½ä¸ `StaticFilesHandler`:缓å˜è¯¥ `path -> routeKey`。
- éžé™æ€æ–‡ä»¶ï¼šä»…当 `path.Split('/')` 段数 `<= 3` æ‰ç¼“å˜ã€‚
目的:
- é¿å…åŠ¨æ€ URL(例如带多段 id çš„è·¯å¾„ï¼‰é€ æˆç¼“å˜æ— é™è†¨èƒ€ï¼›
- 对常è§çŸè·¯å¾„åŠ é€Ÿæ¨¡ç³ŠåŒ¹é…。
---
## 7. çº¿ç¨‹å®‰å…¨ä¸Žå¹¶å‘æ³¨æ„事项
当å‰å®žçŽ°çš„å¹¶å‘è¯ä¹‰ï¼š
- `Routes` 默认是 `Dictionary`,并éžå¹¶å‘容器;
- 典型场景:å¯åŠ¨é˜¶æ®µé›†ä¸æ³¨å†Œè·¯ç”±ï¼Œè¿è¡ŒæœŸåªè¯»è®¿é—®ï¼›
- è‹¥è¿è¡ŒæœŸåЍæ€å¢žåˆ 路由:需è¦è°ƒç”¨æ–¹è‡ªè¡ŒåŠ é”åºåˆ—化访问。
风险点:
- 在è¿è¡ŒæœŸä¿®æ”¹ `Routes` å¹¶åŒæ—¶è°ƒç”¨ `MatchHandler`,å¯èƒ½è§¦å‘ `Dictionary` 枚举异常或产生ä¸ä¸€è‡´ç»“果。
- `_pathCache` åŒæ ·ä¸º `Dictionary`,并å‘读写也ä¸ä¿è¯å®‰å…¨ã€‚
建议:
- å¯åŠ¨å®ŒæˆåŽä¸è¦å†å˜æ›´è·¯ç”±ï¼›
- æˆ–è€…åœ¨å¤–éƒ¨åŠ é”ï¼Œç¡®ä¿ `Map/SetRoute` 与 `MatchHandler` ä¸å¹¶å‘执行。
---
## 8. 最å°ç¤ºä¾‹
> è¯´æ˜Žï¼šç¤ºä¾‹åªæ¼”示 `HttpServer` 的路由注册与组åˆã€‚实际å¯åŠ¨ç›‘å¬ã€ä¼šè¯æ”¶å‘ç‰èƒ½åŠ›ç”± `NetServer` æä¾›ï¼Œè¯·ä»¥é¡¹ç›®å†…现有示例或 `NetServer` 文档为准。
```csharp
using NewLife.Http;
var server = new HttpServer
{
Port = 8080,
ServerName = "MyServer/1.0",
};
server.Map("/health", () => "OK");
server.MapStaticFiles("/static", "./wwwroot");
server.MapController<MyController>("/api");
server.Start();
```
---
## 9. 常è§é—®é¢˜
### 9.1 为什么 `MapController` ä¼šè‡ªåŠ¨åŠ ä¸Š `/*`?
控制器通常需è¦åŒ¹é…其“å路径â€ï¼Œä¾‹å¦‚ `/api/user/list`ã€`/api/user/detail/123` ç‰ã€‚通过 `/*` 让åŒä¸€ä¸ªæŽ§åˆ¶å™¨å¤„ç†å™¨æŽ¥ç®¡è¯¥å‰ç¼€ä¸‹çš„æ‰€æœ‰è¯·æ±‚。
### 9.2 为什么部分路径ä¸åšç¼“å˜ï¼Ÿ
å¯¹å¤šæ®µåŠ¨æ€ URL å…¨é‡ç¼“å˜å¯èƒ½å¯¼è‡´ `_pathCache` æŒç»å¢žé•¿ï¼ˆç¼“å˜è†¨èƒ€ï¼‰ã€‚当å‰ç–略仅缓å˜çŸè·¯å¾„æˆ–é™æ€æ–‡ä»¶å‘½ä¸ï¼Œä»¥å®žçŽ°åŠ é€Ÿä¸Žç©ºé—´ä¹‹é—´çš„æŠ˜ä¸ã€‚
---
## 10. 相关æºç
- `NewLife.Core/Http/HttpServer.cs`
- `NewLife.Core/Http/HttpSession.cs`
- `NewLife.Core/Http/Handlers/DelegateHandler.cs`(按项目实际路径为准)
- `NewLife.Core/Http/Handlers/ControllerHandler.cs`
- `NewLife.Core/Http/Handlers/StaticFilesHandler.cs`
|