前言
上一篇我们通过实战分享了使用 Go 推送钉钉消息, 由于技痒, 笔者现在也编写了一个. NET Core 的 Demo, 作为简单的对照和说明.
最后, 由于精力有限, 笔者希望有兴趣的朋友可以分享下使用 CoreRT 将. NET Core 编译成机器代码这块的实践.
目录
使用. NET Core 推送钉钉消息
获取参数
设置消息数据格式
发送请求
设置 Dockerfile
运行并设置环境变量推送消息
使用. NET Core 推送钉钉消息
这里我们使用. NET Core 来完成相关需求, 注意, 这里是. NET Core, 而不是 ASP.NET Core. 需求和上面类似, 工程相关依赖如下所示:
- <PackageReferenceInclude="Microsoft.Extensions.Configuration"Version="2.2.0"/>
- <PackageReferenceInclude="Microsoft.Extensions.Configuration.CommandLine"Version="2.2.0"/>
- <PackageReferenceInclude="Microsoft.Extensions.Configuration.EnvironmentVariables"Version="2.2.0"/>
- <PackageReferenceInclude="Microsoft.Extensions.Http"Version="2.2.0"/>
- <PackageReferenceInclude="Newtonsoft.Json"Version="12.0.1"/>
以下是相关的主体代码:
获取参数
从环境变量或者命令行参数获取配置:
- ///<summary>
- /// 环境变量列表
- ///</summary>
- privatestaticreadonlystring[] EnvList =
- {
- // 钉钉机器人地址
- "webHOOK",
- //@的手机号码
- "AT_MOBILES",
- //@所有人
- "IS_AT_ALL",
- // 消息内容
- "MESSAGE",
- // 消息类型 (仅支持文本和 Markdown)
- "MSG_TYPE"
- };
- privatestaticvoid Main(string[] args)
- {
- var config = newConfigurationBuilder()
- // 支持命令行参数
- .AddCommandLine(args)
- // 支持环境变量
- .AddEnvironmentVariables()
- .Build();
- #region 参数检查
- foreach (var envName in EnvList)
- {
- var value =config[envName];
- if (string.IsNullOrWhiteSpace(value)&& envName != "AT_MOBILES" && envName !="IS_AT_ALL")
- {
- Console.WriteLine($"{envName} 不能为空!");
- return;
- }
- }
- if (string.IsNullOrWhiteSpace(config["AT_MOBILES"]) &&string.IsNullOrWhiteSpace(config["IS_AT_ALL"]))
- {
- Console.WriteLine("必须设置参数 AT_MOBILES 和 IS_AT_ALL 两者之一!");
- return;
- }
- #endregion
- try
- {
- // 推送消息
- SetDataAndSendWebhooks(config).Wait();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- }
设置消息数据格式
设置消息格式, 为了简单, 这里我们使用匿名类:
- ///<summary>
- /// 设置消息并调用 Webhook
- ///</summary>
- ///<param name="config"></param>
- ///<returns></returns>
- privatestaticasync Task SetDataAndSendWebhooks(IConfigurationRoot config)
- {
- var at = new
- {
- AtMobiles = config["AT_MOBILES"]?.Split(','),
- IsAtAll = Convert.ToBoolean(config["IS_AT_ALL"] ?? "false")
- };
- switch (config["MSG_TYPE"])
- {
- case"text":
- {
- var data = new
- {
- Msgtype = "text",
- Text = new
- {
- Content =config["MESSAGE"]
- },
- At = at
- };
- awaitSendWebhooks(config["WEBHOOK"], data);
- break;
- }
- case"markdown":
- {
- var data = new
- {
- Msgtype = "markdown",
- Markdown = new
- {
- Title = "钉钉通知",
- Text = config["MESSAGE"]
- },
- At = at
- };
- awaitSendWebhooks(config["WEBHOOK"], data);
- break;
- }
- default:
- {
- Console.WriteLine($"不支持的格式:{config["MSG_TYPE"]}");
- break;
- }
- }
- }
发送请求
此处代码使用 Newtonsoft.JSON 做 JSON 序列化, 然后使用 Microsoft.Extensions.Http 的 HttpClient 库来发送 Post 请求.
在数据格式这块, 我们通过配置做了以下设置:
忽略 Null 值. 也就是为 null 的属性不做 JSON 序列化.
设置属性命名规则为 Camel-Case 驼峰式命名法, 首字母小写.
主体代码如下所示:
- ///<summary>
- /// 调用 webhook
- ///</summary>
- ///<typeparamname="T"></typeparam>
- ///<param name="url">webhook 地址 </param>
- ///<param name="data"> 消息 </param>
- ///<returns></returns>
- privatestaticasync Task SendWebhooks<T>(string url, T data) where T : class
- {
- JsonConvert.DefaultSettings = newFunc<JsonSerializerSettings>(() =>newJsonSerializerSettings()
- {
- NullValueHandling =NullValueHandling.Ignore,
- ContractResolver = newCamelCasePropertyNamesContractResolver()
- });
- var jsonData =JsonConvert.SerializeObject(data);
- Console.WriteLine(jsonData);
- using (var httpClient = new HttpClient())
- {
- var content = newStringContent(jsonData);
- content.Headers.ContentType = newMediaTypeHeaderValue("application/json");
- var result = awaithttpClient.PostAsync(url, content);
- result.EnsureSuccessStatusCode();
- Console.WriteLine($"Send webhook succeed. StatusCode:{result.StatusCode}");
- }
- }
设置 Dockerfile
在之前我们已经讲述过, 使用了分阶段构建. 整个 Dockerfile 基本上使用 VS Docker tool 生成:
- FROMmicrosoft/dotnet:2.2-runtime AS base
- WORKDIR /App
- FROMmicrosoft/dotnet:2.2-sdk AS build
- WORKDIR /src
- COPY DingTalk.NET/DingTalk.NET.csprojDingTalk.NET/
- RUN dotnet restoreDingTalk.NET/DingTalk.NET.csproj
- COPY . .
- WORKDIR /src/DingTalk.NET
- RUN dotnet buildDingTalk.NET.csproj -c Release -o /App
- FROM build AS publish
- RUN dotnet publish DingTalk.NET.csproj-c Release -o /App
- FROM base AS final
- WORKDIR /App
- COPY --from=publish/App .
- ENTRYPOINT ["dotnet", "DingTalk.NET.dll"]
- # 注意不要单独使用 MAINTAINER 指令, MAINTAINER 已被 Label 标签代替
- LABEL MAINTAINER ="xinlai@xin-lai.com"
- # LABEL 指令用于将元数据添加到镜像, 支持键值对和 JSON, 我们可以使用 docker inspect 命令来查看
- LABELDingtalkComponent='{\
- "description": "使用钉钉发送通知消息.",\
- "input": [\
- {"name": "WEBHOOK","desc": "必填, 钉钉机器人 Webhook 地址"},\
- {"name":"AT_MOBILES", "desc": "非必填, 被 @人的手机号"},\
- {"name":"IS_AT_ALL", "desc": "非必填,@所有人时: true, 否则为: false"},\
- {"name": "MESSAGE","desc": "必填, 自定义发送的消息内容"},\
- {"name":"MSG_TYPE", "desc": "必填, 自定义发送的消息类型, 目前仅支持 text 和 markdown"}\
- ]\
- }'
编译完成后, 我们来查看下镜像大小:
注意:
通过上图我们可以看到, 镜像大小不到 200M, 相比 GO 体重大了许多, 但是相比其他语言却轻了不少. 不过, 我们可以通过官方开源库 CoreRT 将. NET Core 编译成机器代码, 也就是. NET Core 也可以做到编译完成后只有几 M 大小. 有兴趣的朋友可以分享下这块的实践.
运行并设置环境变量推送消息
我们使用 PowerShell 编写简单脚本如下所示:
- docker build --rm-f "Dockerfile" -t dingtalk.NET:latest .
- docker run --rm -e"WEBHOOK=https://oapi.dingtalk.com/robot/send?access_token={yourAccess Token}" `
- -e "MESSAGE=* 使用. NET Core 发送钉钉消息.*" `
- -e "IS_AT_ALL=true" `
- -e "MSG_TYPE=markdown" `
- -d dingtalk.NET
效果如图:
来源: https://www.cnblogs.com/codelove/p/10576322.html