後端站台在成功驗證並取得請求來源的身份資訊後,可以開始整合基本人員組織資料。
過去取得人資檔案需要先掌握全公司的人事與組織資料,模式通常是每日同步一份公司人事與組織的文檔,並寫入資料庫中。每個不同的系統就得重複這個流程一次。這次,我們想嘗試不一樣的做法:
- 人事與組織資料改為寫入快取,以加快讀取速度。
- 取得人事資料的方式改為透過 API 服務,並且可開放給後續其他專案與系統共享此服務。
因此需要增加一個服務站台,專門提供員工基本資料 API,未來也可以開放給其他系統使用。加入 HR API Service 服務後,單一 Request 流程如下:
圖11-1:合併人事資料後的資料流
minimal
。 dotnet new webapi -n <project name> --use-minimal-apis
appsettings.json
,新增讀取人員組織資料的位置設定 "HRFilePath": {
"EmployeeFilePath": "files/xxxxx_EMP",
"DepartmentFilePath": "files/XXXX_DEPT.v1.1" ,
}
Program.cs
,綁定讀取人員組織資料的位置,並啟用 Swagger。 builder.Services.Configure<HRFilePath>(builder.Configuration.GetSection("HRFilePath"));
app.UseSwagger();
c.SwaggerEndpoint("/ISMS_APSYS_HRAPI/swagger/v1/swagger.json", "My API V1");
c.RoutePrefix = "swagger";
DataReader.cs
用來讀取員工資料,並將讀取後的結果寫入 List<Employee>
,存放於 cache 中。因人事資料每天都會異動, cache 資料需要定期清除與更新,需滿足以下條件:public static class CsvReader
{
public static List<Employee> Read(IMemoryCache cache, ILogger logger, FilePaths FilePaths)
{
// 確認是否需要清除快取
// 設置快取條目並傳遞 ILogger
// 計算下次 07:00 的時間
DateTime now = DateTime.Now;
DateTime next7am = now.Hour < 7
? now.Date.AddHours(7)
: now.Date.AddDays(1).AddHours(7);
if (lines.Length > 10000) //確認文檔資料內容筆數正常
{
var cacheOptions = new MemoryCacheEntryOptions
{
AbsoluteExpiration = next7am, // 每天早上七點清除快取
PostEvictionCallbacks = // 添加回調以在快取條目過期時記錄日誌
{
new PostEvictionCallbackRegistration
{
EvictionCallback = (key, value, reason, state) =>
{
var log = state as ILogger;
log?.LogInformation($"Cache entry '{key}' was evicted. Reason: {reason}");
},
State = logger // 傳遞 ILogger 作為 State
}
}
};
cache.Set("employees", employees, cacheOptions);
logger.LogInformation("Cache entry 'employees' was set.");
}
}
//如果快取為空值,則重新讀取人事組織文檔
if (!cache.TryGetValue("employees", out List<Employee> employees))
{
employees = new List<Employee>();
csvFilePaths.syncFileDate();
var lines = File.ReadAllLines(csvFilePaths.EmployeeFilePath);
// 讀取第一行作為欄位名稱
var headers = lines.First().Split(',');
foreach (var line in lines.Skip(1)) // Skip header line
{
case "EMAIL_ADDR":
employee.Email = values[i];
break;
case "NAME":
employee.Name = values[i];
break;
case "EMPLID":
employee.EMPLID = values[i];
}
employees.Add(employee);
}
return employees;
}
Program.cs
新增取得員工資訊 APIapp.MapGet("/Employee", (string? email, string? emplid, IMemoryCache cache, ILogger<Program> logger, IOptions<FilePaths> FilePaths)
{
//透過 CsvReader.ReadCsv 讀取員工檔案資料
var employees = DataReader.Read(cache, logger, csvFilePaths.Value);
// 讀取完畢後進行資料搜尋,將搜尋結果回傳
Employee? employee = null;
if (!string.IsNullOrEmpty(email))
{
employee = employees.FirstOrDefault(p => p.Email == email );
}
else if (!string.IsNullOrEmpty(emplid))
{
employee = employees.FirstOrDefault(p => p.EMPLID == emplid);
}
if (employee == null)
{
return Results.NotFound();
}
var employeeJson = JsonSerializer.Serialize(employee,options1);
return Results.Ok(employee);
})
.WithName("GetEmployeeInfo")
.WithOpenApi()
.Produces<Employee>(StatusCodes.Status200OK) // 指定返回的對象類型
.Produces(StatusCodes.Status404NotFound); // 指定 404 狀態碼
啟動服務
圖11-2:成功啟動 HR API人事資料服務
執行測試呼叫 API 服務
圖11-3:可取得 API 回應
檢視回應時間
圖11-4:檢視回應時間為 15.15 秒,因為需要讀取文檔並寫入快取,時間較長。
重新測試呼叫 API 服務,第 2 次呼叫可直接由快取資料中讀取並回應,回應時間為 0.02 秒。
圖11-5:第 2 次呼叫可直接由快取資料中回應時間縮短,縮短15.13 秒 🎊🎊🎊🎊
一樣來個圖清楚了解知道每個環節的作用
圖11-6:員工資料 API 查詢與快取機制流程