解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# ApiHttpClient ʹÓÃÊÖ²á
## ¸ÅÊö
`ApiHttpClient` ÊÇ NewLife.Core ÌṩµÄ Http Ó¦Óýӿڿͻ§¶Ë£¬ÊǶԶà¸ö·þÎñµØÖ·µÄ°ü×°¡£ËüÔڵײã¹ÜÀí¶à¸ö `HttpClient`£¬ÌṩͳһµÄ¸ºÔؾùºâºÍ¹ÊÕÏ×ªÒÆÄÜÁ¦¡£
### ºËÐÄÌØÐÔ
- **¶àµØÖ·¹ÜÀí**£ºÖ§³ÖÅäÖöà¸ö·þÎñµØÖ·£¬×Ô¶¯½øÐиºÔؾùºâ
- **¹ÊÕÏ×ªÒÆ**£º½Úµã²»¿ÉÓÃʱ×Ô¶¯Çл»µ½±¸Óýڵã
- **¸ºÔؾùºâ**£ºÖ§³Ö¹ÊÕÏ×ªÒÆ¡¢¼ÓȨÂÖѯ¡¢¾ºËÙµ÷ÓÃÈýÖÖģʽ
- **ÁîÅÆ¼øÈ¨**£ºÖ§³Ö Token ºÍ Authentication Á½ÖÖ¼øÈ¨·½Ê½
- **ÏìÓ¦½âÎö**£ºÖ§³Ö×Ô¶¨Òå״̬ÂëºÍÊý¾Ý×Ö¶ÎÃû³Æ£¬ÊÊÅ䲻ͬƽ̨
- **¿ÉÀ©Õ¹ÐÔ**£ºÖ§³Ö×Ô¶¨Òå JsonHost¡¢Filter¡¢Ê¼þµÈ
## ¿ìËÙ¿ªÊ¼
### »ù´¡Ó÷¨
```csharp
// ´´½¨¿Í»§¶Ë
var client = new ApiHttpClient("http://api.example.com");
// GET ÇëÇó
var result = await client.GetAsync<UserInfo>("user/info", new { id = 123 });
// POST ÇëÇó
var response = await client.PostAsync<ResultModel>("user/create", new { name = "test", age = 18 });
// ͬ²½µ÷ÓÃ
var data = client.Get<String>("api/data");
```
### ¶àµØÖ·ÅäÖÃ
```csharp
// ¶ººÅ·Ö¸ô¶à¸öµØÖ·
var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com,http://api3.example.com");
// »òÕßÊÖ¶¯Ìí¼Ó
var client = new ApiHttpClient();
client.Add("primary", "http://api1.example.com");
client.Add("backup", "http://api2.example.com");
```
## ¸ºÔؾùºâ
### ÈýÖÖ¸ºÔؾùºâģʽ
| ģʽ | ö¾ÙÖµ | ˵Ã÷ |
|------|--------|------|
| ¹ÊÕÏ×ªÒÆ | `LoadBalanceMode.Failover` | ÓÅÏÈʹÓÃÖ÷½Úµã£¬Ê§°Üʱ×Ô¶¯Çл»µ½±¸Óýڵ㣬¹ýÒ»¶Îʱ¼ä×Ô¶¯ÇÐ»Ø |
| ¼ÓȨÂÖѯ | `LoadBalanceMode.RoundRobin` | °´È¨ÖØ·ÖÅäÇëÇóµ½¶à¸ö½Úµã£¬×Ô¶¯ÆÁ±Î²»¿ÉÓýڵã |
| ¾ºËÙµ÷Óà | `LoadBalanceMode.Race` | ²¢ÐÐÇëÇó¶à¸ö½Úµã£¬È¡×î¿ìÏìÓ¦£¬È¡ÏûÆäËüÇëÇó |
### ¹ÊÕÏ×ªÒÆÄ£Ê½£¨Ä¬ÈÏ£©
```csharp
var client = new ApiHttpClient("http://primary.example.com,http://backup.example.com")
{
LoadBalanceMode = LoadBalanceMode.Failover, // ĬÈÏÖµ
ShieldingTime = 60 // ²»¿ÉÓýڵãÆÁ±Î60Ãë
};
// Õý³£Çé¿öʹÓà primary£¬primary ²»¿ÉÓÃʱ×Ô¶¯Çл»µ½ backup
// 60Ãëºó»á³¢ÊÔÇÐ»Ø primary
var result = await client.GetAsync<Object>("api/data");
```
### ¼ÓȨÂÖѯģʽ
```csharp
// ¸ñʽ£ºname=weight*url
var client = new ApiHttpClient("master=3*http://api1.example.com,slave=7*http://api2.example.com")
{
LoadBalanceMode = LoadBalanceMode.RoundRobin
};
// master È¨ÖØ3£¬slave È¨ÖØ7
// 10´ÎÇëÇóÖУ¬master Ô¼3´Î£¬slave Ô¼7´Î
```
### ¾ºËÙµ÷ÓÃģʽ
```csharp
var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com,http://api3.example.com")
{
LoadBalanceMode = LoadBalanceMode.Race
};
// ²¢ÐÐÇëÇóËùÓнڵ㣬·µ»Ø×î¿ìµÄÏìÓ¦
// ÊÊÓÃÓÚ¶ÔÏìӦʱ¼äÒªÇ󼫸ߵij¡¾°
```
## Éí·ÝÑéÖ¤
### Token ÁîÅÆ
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Token = "your_access_token"
};
// ÇëÇóÍ·×Ô¶¯Ìí¼Ó£ºAuthorization: Bearer your_access_token
```
### Authentication ÊôÐÔ
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Authentication = new AuthenticationHeaderValue("Bearer", "your_token")
};
// »òÕßʹÓà Basic ÈÏÖ¤
client.Authentication = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes("user:password")));
```
### ·þÎñ½Úµã¶ÀÁ¢ Token
```csharp
// ÔÚ URL ÖÐÖ¸¶¨ Token
var client = new ApiHttpClient();
client.Add("service1", "http://api1.example.com#token=token_for_api1");
client.Add("service2", "http://api2.example.com#token=token_for_api2");
```
> **ÓÅÏȼ¶**£º`Token` ÊôÐÔÓÅÏÈÓÚ `Authentication` ÊôÐÔ¡£
## ÏìÓ¦½âÎö
### ±ê×¼ÏìÓ¦¸ñʽ
ĬÈÏÖ§³ÖÒÔÏÂÏìÓ¦¸ñʽ£º
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
### ×Ô¶¨Òå×Ö¶ÎÃû³Æ
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
CodeName = "status", // ״̬Âë×Ö¶ÎÃû£¬Ä¬ÈÏ×Ô¶¯Ê¶±ð code/errcode/status
DataName = "result" // Êý¾Ý×Ö¶ÎÃû£¬Ä¬ÈÏ data
};
// ÊÊÅäÏìÓ¦¸ñʽ£º{"status": 0, "result": {...}}
```
### Ö§³ÖµÄ״̬Âë×Ö¶Î
- `code`
- `errcode`
- `status`
### Ö§³ÖµÄÏûÏ¢×Ö¶Î
- `message`
- `msg`
- `errmsg`
- `error`
## Http ·½·¨
```csharp
var client = new ApiHttpClient("http://api.example.com");
// GET - ²ÎÊýÆ´½Óµ½ URL
var result = await client.GetAsync<T>("api/users", new { page = 1, size = 10 });
// POST - ²ÎÊý JSON ÐòÁл¯µ½ Body
var result = await client.PostAsync<T>("api/users", new { name = "test" });
// PUT
var result = await client.PutAsync<T>("api/users/1", new { name = "updated" });
// PATCH
var result = await client.PatchAsync<T>("api/users/1", new { name = "patched" });
// DELETE
var result = await client.DeleteAsync<T>("api/users/1");
// ͨÓõ÷ÓÃ
var result = await client.InvokeAsync<T>(HttpMethod.Post, "api/action", args);
```
## ¸ß¼¶ÅäÖÃ
### ³¬Ê±ÉèÖÃ
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Timeout = 30_000 // 30Ã룬ĬÈÏ15Ãë
};
```
### ´úÀíÉèÖÃ
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
UseProxy = true // ʹÓÃϵͳ´úÀí£¬Ä¬ÈÏfalse
};
```
### SSLÖ¤ÊéÑéÖ¤
```csharp
var client = new ApiHttpClient("https://api.example.com")
{
CertificateValidation = false // ²»ÑéÖ¤Ö¤Ê飬ĬÈÏfalse
};
```
### ×Ô¶¨Òå UserAgent
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
DefaultUserAgent = "MyApp/1.0"
};
```
### ×Ô¶¨Òå Json ÐòÁл¯
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
JsonHost = new FastJson() // ×Ô¶¨Òå Json ÐòÁл¯Æ÷
};
```
## ʼþÓë¹ýÂËÆ÷
### OnRequest ʼþ
```csharp
var client = new ApiHttpClient("http://api.example.com");
client.OnRequest += (sender, e) =>
{
// Ìí¼Ó×Ô¶¨ÒåÇëÇóÍ·
e.Request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString());
e.Request.Headers.Add("X-Timestamp", DateTime.Now.Ticks.ToString());
};
```
### OnCreateClient ʼþ
```csharp
client.OnCreateClient += (sender, e) =>
{
// ÅäÖÃ HttpClient
e.Client.DefaultRequestHeaders.Add("X-App-Version", "1.0.0");
};
```
### Http ¹ýÂËÆ÷
```csharp
// ʹÓÃÄÚÖõÄÁîÅÆ¹ýÂËÆ÷
var filter = new TokenHttpFilter
{
UserName = "app_id",
Password = "app_secret"
};
var client = new ApiHttpClient("http://api.example.com")
{
Filter = filter
};
// ¹ýÂËÆ÷»á×Ô¶¯´¦ÀíÁîÅÆµÄ»ñÈ¡ºÍË¢ÐÂ
```
### ×Ô¶¨Òå¹ýÂËÆ÷
```csharp
public class MyHttpFilter : IHttpFilter
{
public Task OnRequest(HttpClient client, HttpRequestMessage request, Object? state, CancellationToken cancellationToken)
{
// ÇëÇóǰ´¦Àí
request.Headers.Add("X-Custom", "value");
return Task.CompletedTask;
}
public Task OnResponse(HttpClient client, HttpResponseMessage response, Object? state, CancellationToken cancellationToken)
{
// ÏìÓ¦ºó´¦Àí
return Task.CompletedTask;
}
public Task OnError(HttpClient client, Exception ex, Object? state, CancellationToken cancellationToken)
{
// ´íÎó´¦Àí
return Task.CompletedTask;
}
}
```
## ·þÎñ״̬¼à¿Ø
### ²é¿´µ±Ç°·þÎñ
```csharp
var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com");
// µ±Ç°ÕýÔÚʹÓõķþÎñ
var current = client.Current;
Console.WriteLine($"µ±Ç°·þÎñ£º{current?.Name} - {current?.Address}");
// µ±Ç°·þÎñÃû³Æ
Console.WriteLine($"·þÎñÔ´£º{client.Source}");
```
### ²é¿´·þÎñÁбí״̬
```csharp
foreach (var svc in client.Services)
{
Console.WriteLine($"·þÎñ£º{svc.Name}");
Console.WriteLine($" µØÖ·£º{svc.Address}");
Console.WriteLine($" È¨ÖØ£º{svc.Weight}");
Console.WriteLine($" µ÷ÓôÎÊý£º{svc.Times}");
Console.WriteLine($" ´íÎó´ÎÊý£º{svc.Errors}");
Console.WriteLine($" ÊÇ·ñ¿ÉÓãº{svc.IsAvailable()}");
Console.WriteLine($" Ï´οÉÓÃʱ¼ä£º{svc.NextTime}");
}
```
## Á´Â·×·×Ù
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Tracer = DefaultTracer.Instance, // ÉèÖÃÁ´Â·×·×ÙÆ÷
SlowTrace = 5_000 // ³¬¹ý5Ãë¼Ç¼Âýµ÷ÓÃÈÕÖ¾
};
```
## ÒÀÀµ×¢Èë
### ASP.NET Core ¼¯³É
```csharp
// ×¢²á·þÎñ
services.AddSingleton<IApiClient>(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var client = new ApiHttpClient(config["ApiServer:Urls"])
{
Timeout = config.GetValue<Int32>("ApiServer:Timeout"),
ServiceProvider = sp
};
return client;
});
// ʹÓÃÅäÖÃÖÐÐÄ
services.AddSingleton<IApiClient>(sp =>
{
return new ApiHttpClient(sp, "ApiServerConfig"); // ´ÓÅäÖÃÖÐÐĶÁÈ¡
});
```
### IConfigMapping ½Ó¿Ú
```csharp
// ApiHttpClient ʵÏÖÁË IConfigMapping ½Ó¿Ú
// ¿ÉÒÔͨ¹ýÅäÖÃÖÐÐĶ¯Ì¬¸üзþÎñµØÖ·
var configProvider = services.GetRequiredService<IConfigProvider>();
configProvider.Bind(client, true, "ApiServer"); // °ó¶¨ÅäÖýÚ
```
## ÎļþÏÂÔØ
```csharp
var client = new ApiHttpClient("http://download.example.com");
// ÏÂÔØÎļþ²¢Ð£Ñé¹þÏ£
await client.DownloadFileAsync(
requestUri: "files/package.zip",
fileName: "D:/downloads/package.zip",
expectedHash: "sha256:abc123...", // ¿ÉÑ¡£¬Ö§³Ö md5/sha1/sha256/sha512
cancellationToken: default
);
```
## Òì³£´¦Àí
### ApiException
```csharp
try
{
var result = await client.GetAsync<Object>("api/data");
}
catch (ApiException ex)
{
// ÒµÎñÒì³££¨·þÎñ¶Ë·µ»ØµÄ´íÎóÂ룩
Console.WriteLine($"´íÎóÂ룺{ex.Code}");
Console.WriteLine($"´íÎóÐÅÏ¢£º{ex.Message}");
}
catch (HttpRequestException ex)
{
// ÍøÂçÒì³£
Console.WriteLine($"ÍøÂç´íÎó£º{ex.Message}");
}
```
## ×î¼Ñʵ¼ù
### 1. ¸´Óÿͻ§¶ËʵÀý
```csharp
// ? ÍÆ¼ö£º×÷Ϊµ¥ÀýʹÓÃ
public class MyService
{
private static readonly ApiHttpClient _client = new("http://api.example.com");
public Task<T> GetDataAsync<T>() => _client.GetAsync<T>("api/data");
}
// ? ±ÜÃ⣺ÿ´ÎÇëÇó´´½¨ÐÂʵÀý
public async Task<T> GetDataAsync<T>()
{
using var client = new ApiHttpClient("http://api.example.com"); // ²»ÍƼö
return await client.GetAsync<T>("api/data");
}
```
### 2. ºÏÀíÉèÖó¬Ê±
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Timeout = 10_000, // ¸ù¾Ý½Ó¿ÚÌØÐÔÉèÖúÏÀí³¬Ê±
SlowTrace = 3_000 // Âýµ÷ÓÃãÐÖµ
};
```
### 3. ÅäÖùÊÕÏ×ªÒÆ
```csharp
var client = new ApiHttpClient("http://primary.example.com,http://backup.example.com")
{
ShieldingTime = 30, // ¹ÊÕϽڵãÆÁ±Î30Ãë
LoadBalanceMode = LoadBalanceMode.Failover
};
```
### 4. ʹÓÃÁ´Â·×·×Ù
```csharp
var client = new ApiHttpClient("http://api.example.com")
{
Tracer = DefaultTracer.Instance,
Log = XTrace.Log // ¿ªÆôÈÕÖ¾
};
```
## ÍêÕûʾÀý
```csharp
using NewLife.Log;
using NewLife.Remoting;
// ´´½¨¿Í»§¶Ë
var client = new ApiHttpClient("master=3*http://api1.example.com,slave=7*http://api2.example.com")
{
Token = "your_access_token",
Timeout = 15_000,
ShieldingTime = 60,
LoadBalanceMode = LoadBalanceMode.RoundRobin,
CodeName = "code",
DataName = "data",
Tracer = DefaultTracer.Instance,
Log = XTrace.Log
};
// Ìí¼ÓÇëÇóÀ¹½Ø
client.OnRequest += (sender, e) =>
{
e.Request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString());
};
try
{
// ·¢ÆðÇëÇó
var users = await client.GetAsync<List<UserInfo>>("api/users", new { page = 1, size = 10 });
foreach (var user in users)
{
Console.WriteLine($"Óû§£º{user.Name}");
}
// ²é¿´µ±Ç°Ê¹ÓõķþÎñ
Console.WriteLine($"ÇëÇó·þÎñ£º{client.Source} - {client.Current?.Address}");
}
catch (ApiException ex)
{
Console.WriteLine($"ÒµÎñ´íÎó [{ex.Code}]£º{ex.Message}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"ÍøÂç´íÎó£º{ex.Message}");
}
```
## Ïà¹ØÀàÐÍ
| ÀàÐÍ | ˵Ã÷ |
|------|------|
| `ApiHttpClient` | Http Ó¦Óýӿڿͻ§¶Ë |
| `ServiceEndpoint` | ·þÎñ¶Ëµã£¬°üº¬µØÖ·¡¢È¨ÖØ¡¢×´Ì¬µÈÐÅÏ¢ |
| `ILoadBalancer` | ¸ºÔؾùºâÆ÷½Ó¿Ú |
| `FailoverLoadBalancer` | ¹ÊÕÏ×ªÒÆ¸ºÔؾùºâÆ÷ |
| `WeightedRoundRobinLoadBalancer` | ¼ÓȨÂÖѯ¸ºÔؾùºâÆ÷ |
| `RaceLoadBalancer` | ¾ºËÙ¸ºÔؾùºâÆ÷ |
| `IHttpFilter` | Http ¹ýÂËÆ÷½Ó¿Ú |
| `TokenHttpFilter` | ÁîÅÆ¹ýÂËÆ÷ |
| `ApiException` | Api ÒµÎñÒì³£ |
## °æ±¾ÀúÊ·
- **v11.0+**£ºÒýÈë¸ºÔØ¾ùºâģʽö¾Ù£¬Ö§³Ö¾ºËÙµ÷ÓÃ
- **v10.0+**£ºÖ§³Ö×Ô¶¨Òå CodeName/DataName
- **v9.0+**£ºÖ§³ÖÁ´Â·×·×Ù
|