提交
This commit is contained in:
parent
26b4c46206
commit
ea13fc70c6
@ -7,6 +7,50 @@ top_img: https://gcore.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/67239FB
|
|||||||
|
|
||||||
# ASP.Net 6
|
# ASP.Net 6
|
||||||
|
|
||||||
|
## Web API 项目初始化搭建
|
||||||
|
|
||||||
|
首先打开Visual Studio 2022,然后选择创建新项目
|
||||||
|
|
||||||
|
之后筛选下拉框选择如红框标注
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
起一个项目名称及选择项目位置,下一步
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
框架选择.Net 6.0(长期支持)
|
||||||
|
|
||||||
|
选择启用Docker,为了之后可以部署到Docker容器
|
||||||
|
|
||||||
|
启用OpenAPI支持是为了可以输出Swagger接口文档,但如果使用Furion框架的话,需要勾掉
|
||||||
|
|
||||||
|
顶级语句是无需在Program.cs中显式包含Main方法,可以使用顶级语句功能最大程度地减少必须编写的代码
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击创建即可
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 集成Furion框架
|
||||||
|
|
||||||
|
在NuGet包管理器中搜索`Furion`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
选择安装的项目,然后安装即可
|
||||||
|
|
||||||
|
### 可能遇到的问题
|
||||||
|
|
||||||
|
#### 包降级
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
将提示的NuGet包升级到 前者的版本即可,比如图内的 Swashbuckle.AspNetCore 原有的版本是 6.2.3 那么升级到 6.5.0即可
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 部署到Docker
|
## 部署到Docker
|
||||||
|
|
||||||
### 安装.Net SDK 6.0环境
|
### 安装.Net SDK 6.0环境
|
||||||
@ -63,6 +107,25 @@ builder.Services.AddControllers().AddJsonOptions(options => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Json序列化时日期类型格式化输出
|
||||||
|
|
||||||
|
```c#
|
||||||
|
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.JsonSerializerOptions.Converters.Add(new SystemTextJsonDateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 集成Furion框架
|
||||||
|
|
||||||
|
```c#
|
||||||
|
var builder = WebApplication.CreateBuilder(args).Inject();
|
||||||
|
builder.Services.AddControllers().AddInject();
|
||||||
|
app.UseInject();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 使用Autofac自动注入Service
|
### 使用Autofac自动注入Service
|
||||||
|
|
||||||
通过NuGet包管理器 安装NuGet包
|
通过NuGet包管理器 安装NuGet包
|
||||||
|
|||||||
18
source/_posts/Java.md
Normal file
18
source/_posts/Java.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Java
|
||||||
|
|
||||||
|
## Intellij IDEA 使用及配置
|
||||||
|
|
||||||
|
### 使用@Autowired注解报红的解决办法
|
||||||
|
|
||||||
|
打开Settings -> Editor -> Inspections -> Spring -> Spring Core -> Code,找到Incorrect autowiring in Spring bean components,将代码审查级别从Error修改为Warning
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 开源框架若依 RuoYi
|
||||||
|
|
||||||
|
### 替换Mybatis为Mybatis-Plus
|
||||||
|
|
||||||
6
source/_posts/Kubernetes.md
Normal file
6
source/_posts/Kubernetes.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Kubernetes整理
|
||||||
|
author: 文永达
|
||||||
|
top_img: https://gcore.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/00E0F0ED-9F1C-407A-9AA6-545649D919F4.jpeg
|
||||||
|
|
||||||
|
---
|
||||||
@ -33,7 +33,34 @@ dev:存放设备文件
|
|||||||
|
|
||||||
ip addr(ip a):查看主机的ip地址
|
ip addr(ip a):查看主机的ip地址
|
||||||
clear:清屏
|
clear:清屏
|
||||||
cd:进入指定的目录
|
|
||||||
|
### 跳转目录:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 跳转指定目录 root目录下的www
|
||||||
|
cd /root/www
|
||||||
|
# 返回跳转前的目录
|
||||||
|
cd -
|
||||||
|
# 跳转上一级目录
|
||||||
|
cd ../
|
||||||
|
# 跳转根目录
|
||||||
|
cd /
|
||||||
|
# 跳转root目录
|
||||||
|
cd ~
|
||||||
|
```
|
||||||
|
|
||||||
|
### 复制粘贴:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 把aa.txt复制到init目录下
|
||||||
|
cp aa.txt init/
|
||||||
|
# 把init文件夹以及所包含的文件复制到 spring文件夹下
|
||||||
|
cp -r init spring/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ls:列出当前目录下的所有文件及目录
|
ls:列出当前目录下的所有文件及目录
|
||||||
ls -l:给ls指令传了一个参数l。等同于ll。列出当前目录下的所有文件及目录的详情。
|
ls -l:给ls指令传了一个参数l。等同于ll。列出当前目录下的所有文件及目录的详情。
|
||||||
ls bin:ls后可以接目录名,要么接绝对路径。
|
ls bin:ls后可以接目录名,要么接绝对路径。
|
||||||
@ -66,6 +93,8 @@ tail -f xxxx:实时监控文本文件的变化
|
|||||||
Ctrl + c:几乎可以退出所有的操作
|
Ctrl + c:几乎可以退出所有的操作
|
||||||
echo:打印输出一句话。也可以用作向文本文件内写入信息。会自动追加并换行。
|
echo:打印输出一句话。也可以用作向文本文件内写入信息。会自动追加并换行。
|
||||||
|
|
||||||
|
find: 查找文件夹或目录 find /usr -iname "\*docker\*" 查找/usr目录下 名称为docker 的文件或目录 模糊查询 并忽略大小写
|
||||||
|
|
||||||
### 压缩:
|
### 压缩:
|
||||||
|
|
||||||
1、打包,把多个文件打成一个包。
|
1、打包,把多个文件打成一个包。
|
||||||
@ -581,3 +610,12 @@ cd build
|
|||||||
docker run -itd --name nodejs -v /usr/local/bin/npm:/usr/local/bin/npm n
|
docker run -itd --name nodejs -v /usr/local/bin/npm:/usr/local/bin/npm n
|
||||||
```
|
```
|
||||||
|
|
||||||
|
查看硬盘空间
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 统计磁盘整体情况,包括磁盘大小,已使用,可用
|
||||||
|
df -lh
|
||||||
|
# 查看根目录下文件夹大小
|
||||||
|
du -sh /*
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@ -341,7 +341,29 @@ ALTER TABLE BIND_PHONE_NUMBER RENAME COLUMN NAME TO APPNAME;
|
|||||||
|
|
||||||
### 使用关键字做完表名,列名
|
### 使用关键字做完表名,列名
|
||||||
|
|
||||||
使用""形式,如"INDEX"
|
使用双引号""形式,如"INDEX"
|
||||||
|
|
||||||
|
### 删除表数据
|
||||||
|
|
||||||
|
```sql
|
||||||
|
TRUNCATE TABLE 表名
|
||||||
|
-- or
|
||||||
|
DELETE FROM 表名
|
||||||
|
```
|
||||||
|
|
||||||
|
### 从其他表中复制数据到插入一张表中
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 标准语法
|
||||||
|
INSERT INTO table2
|
||||||
|
SELECT * FROM table1;
|
||||||
|
-- 多表插入到一张表 示例,ID为GUID,
|
||||||
|
-- 需要注意的是如果指定插入到哪些列中,不是根据后面SELECT的列的别名来插入,而是通过列的顺序插入,语句后可接WHERE条件
|
||||||
|
INSERT INTO table1(ID,NAME,TEXT) SELECT SYS_GUID(), t2.NAME, t3.TEXT FROM DUAL, TABLE2 t2, TABLE3 t3;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 内连接与外连接
|
## 内连接与外连接
|
||||||
|
|
||||||
@ -448,3 +470,37 @@ SELECT column,... FROM table2
|
|||||||
UNION 操作符返回两个查询的结果集的并集,去除重复记录。
|
UNION 操作符返回两个查询的结果集的并集,去除重复记录。
|
||||||
|
|
||||||
UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
|
UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
|
||||||
|
|
||||||
|
## Oracle 函数
|
||||||
|
|
||||||
|
### NVL()
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT a.OSPREQID,a.OSPREQNO FROM T_OSP_REQ a,T_OSP_REQDETAIL b WHERE a.OSPREQID = b.OSPREQID AND b.OSPNO IN (SELECT OSPNP FROM T_BPM_OSP WHERE OSPNO IN ('OSP202302280002')) AND NVL(DATASTATUS, ' ')<>'撤销'
|
||||||
|
```
|
||||||
|
|
||||||
|
如果**DATASTATUS**为**NULL**,则返回**' '**,否则返回**DATASTATUS**
|
||||||
|
|
||||||
|
官方解释
|
||||||
|
|
||||||
|
The Oracle NVL () function allows you to **replace null** with a more meaningful alternative in the results of a query. The following shows the syntax of the NVL () function: The NVL () function accepts two arguments. If e1 evaluates to null, then NVL () function returns e2. If e1 evaluates to non-null, the NVL () function returns e1.
|
||||||
|
|
||||||
|
Oracle NVL()函数允许您在查询结果中用更有意义的替代项替换NULL。下面显示了NVL()函数的语法:NVL()函数接受两个参数。如果e1的计算结果为空,则NVL()函数返回e2。如果e1的计算结果为非空,则nvl()函数返回e1。
|
||||||
|
|
||||||
|
### DECODE()
|
||||||
|
|
||||||
|
用法 DECODE(表达式, 条件1,返回值1,条件2,返回值2)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT DECODE(AMOUNT, 0, NULL, AMOUNT) FROM T_PO_ORDERDETAIL;
|
||||||
|
```
|
||||||
|
|
||||||
|
如果**AMOUNT**等于**0**,则返回**NULL**,否则返回**AMOUNT**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT DECODE(AMOUNT, 0, NULL, 1, 1, AMOUNT) FROM T_PO_ORDERDETAIL;
|
||||||
|
```
|
||||||
|
|
||||||
|
如果**AMOUNT**等于**0**,则返回**NULL**,否则如果AMOUNT等于1,则返回1,否则返回**AMOUNT**
|
||||||
|
|||||||
@ -6,6 +6,44 @@ top_img: https://gcore.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/B951AE1
|
|||||||
---
|
---
|
||||||
# Typora
|
# Typora
|
||||||
|
|
||||||
|
## 快捷键
|
||||||
|
|
||||||
|
### 字体操作快捷键
|
||||||
|
|
||||||
|
| 功能 | 快捷键 |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 字体加粗 | Ctrl+B |
|
||||||
|
| 下划线 | Ctrl+U |
|
||||||
|
| 倾斜 | Ctrl+I |
|
||||||
|
| 删除线 | Alt+Shift+5 |
|
||||||
|
|
||||||
|
### 插入功能快键键
|
||||||
|
|
||||||
|
| **功能** | **快键键** |
|
||||||
|
| ---------------------------- | ------------ |
|
||||||
|
| 插入图片(本地图片可直接拖入) | Ctrl+Shift+I |
|
||||||
|
| 插入表格 | Ctrl+T |
|
||||||
|
| 插入有序列表 | Ctrl+Shift+[ |
|
||||||
|
| 插入无序列表 | Ctrl+Shift+] |
|
||||||
|
| 插入超链接 | Ctrl+K |
|
||||||
|
| 插入代码片 | Ctrl+Shift+` |
|
||||||
|
| 插入代码块 | Ctrl+Shift+K |
|
||||||
|
| 插入公式块 | Ctrl+Shift+M |
|
||||||
|
| 插入引用块 | Ctrl+Shift+Q |
|
||||||
|
|
||||||
|
### 标题段落快捷键
|
||||||
|
|
||||||
|
| 功能 | 快捷键 |
|
||||||
|
| --------------------- | -------- |
|
||||||
|
| 段落(正文) | Ctrl+0 |
|
||||||
|
| 一级标题 | Ctrl+1 |
|
||||||
|
| 二级标题 | Ctrl+2 |
|
||||||
|
| 三–六级标题(以此类推) | Ctrl+3–6 |
|
||||||
|
| 提升标题级别 | Ctrl+‘+’ |
|
||||||
|
| 降低标题级别 | Ctrl+‘-’ |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 设置引用图片存储路径
|
## 设置引用图片存储路径
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@ -49,13 +49,14 @@ export default defineConfig({
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 淘宝镜像
|
# 淘宝镜像
|
||||||
|
# 永久生效
|
||||||
npm config set registry http://registry.npm.taobao.org/
|
npm config set registry http://registry.npm.taobao.org/
|
||||||
# 查看镜像
|
# 查看镜像
|
||||||
npm config get registry
|
npm config get registry
|
||||||
|
# 暂时生效
|
||||||
|
npm install --registry http://registry.npm.taobao.org/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### CentOS7安装node js
|
### CentOS7安装node js
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|||||||
@ -175,3 +175,85 @@ private void radioButton2_CheckedChanged(object sender, EventArgs e)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Net Core
|
||||||
|
|
||||||
|
### 打开其他窗体的三种方式
|
||||||
|
|
||||||
|
#### Show
|
||||||
|
|
||||||
|
例如登入界面进入主页面,直接将主页面展示出来,两个窗体互不影响
|
||||||
|
|
||||||
|
```c#
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Form2 form2 = new Form2();
|
||||||
|
form2.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Owner
|
||||||
|
|
||||||
|
例如text文件中的“替换”选项,打开界面后不关闭也是允许操作主页面的
|
||||||
|
|
||||||
|
```c#
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Form2 form2 = new Form2();
|
||||||
|
form2.Owner = this;
|
||||||
|
form2.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ShowDialog
|
||||||
|
|
||||||
|
例如text文件中的“打开”选项,打开界面后不关闭是不允许操作主页面的
|
||||||
|
|
||||||
|
### 让子窗体显示在父窗体之上
|
||||||
|
|
||||||
|
```c#
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Form2 form2 = new Form2();
|
||||||
|
form2.Show(this); // this代表父窗体也就是Form1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### TextBox
|
||||||
|
|
||||||
|
#### 属性
|
||||||
|
|
||||||
|
##### Multiline
|
||||||
|
|
||||||
|
控制编辑控件的文本是否能够跨越多行。
|
||||||
|
|
||||||
|
##### ScrollBars
|
||||||
|
|
||||||
|
指示对于多行编辑控件,将为此控件显示哪些滚动条
|
||||||
|
|
||||||
|
##### WordWrap
|
||||||
|
|
||||||
|
指示多行编辑控件是否自动换行
|
||||||
|
|||||||
191
source/_posts/gRPC.md
Normal file
191
source/_posts/gRPC.md
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
title: gRPC入门与实操
|
||||||
|
date: 2023-01-16 12:37:31
|
||||||
|
author: 文永达
|
||||||
|
top_img: https://gcore.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/67239FBB-E15D-4F4F-8EE8-0F1C9F3C4E7C.jpeg
|
||||||
|
---
|
||||||
|
|
||||||
|
# gRPC入门与实操
|
||||||
|
|
||||||
|
## 为什么选择gRPC
|
||||||
|
|
||||||
|
### 历史
|
||||||
|
|
||||||
|
长久以来,我们在前后端交互时使用`WebApi + JSON`方式,后端服务之间调用同样如此(或者更久远之前的`WCF + XML`方式)。WebApi + JSON 是优选的,很重要的一点是它们两者都是平台无关的三方标准,且足够语义化,便于程序员使用,在异构(前后端、多语言后端)交互场景下是不二选择。然而,在后端服务体系改进特别是后来微服务兴起后,我们发现,前后端交互理所当然认可的 WebApi + JSON 在后端体系内显得有点不太合适:
|
||||||
|
|
||||||
|
1. JSON 字符编码方式使得传输数据量较大,而后端一般并不需要直接操作 JSON,都会将 JSON 转为平台专有类型后再处理;既然需要转换,为什么不选择一个数据量更小,转换更方便的格式呢?
|
||||||
|
2. 调用双方要事先约定数据结构和调用接口,稍有变动就要手动更新相关代码(Model 类和方法签名);是否可以将约定固化为文档,服务提供者维护该文档,调用方根据该文档可以方便地生成自己需要的代码,在文档变化时代码也可以自动更新?
|
||||||
|
3. [之前] WebApi 基于的 Http[1.1] 协议已经诞生 20 多年,其定义的交互模式在今日已经捉襟见肘;业界需要一个更有效率的协议。
|
||||||
|
|
||||||
|
### 高效传输-Http2.0
|
||||||
|
|
||||||
|
我们先来说第 3 个问题,其实很多大厂内部早已开始着手处理,并诞生了一些应用广泛的框架,如阿里开源的`Dubbo`,直接抛弃了 Http 改为基于 TCP实现,效率得到明显提升,不过 Dubbo 依赖 Java 环境,无法跨平台使用,不在我们考虑范围。
|
||||||
|
|
||||||
|
另一个大厂 Google,内部也在长期使用自研的`Stubby`框架,与 Dubbo 不同的是,Stubby是跨平台的,但是 Google 认为 Stubby不基于任何标准,而且与其内部基础设施紧密耦合,并不适合公开发布。
|
||||||
|
|
||||||
|
同时 Google 也在对 Http1.1 协议进行增强,该项目是 2012 年提出的 SPDY 方案,其优化了 Http 协议层,新增的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。Google 表示,引入 SPDY 协议后,在实验室测试中页面加载速度比原先快 64%。巨大的提升让大家开始从正面看待和解决老版本 Http 协议的问题,这也直接加速了 Http2.0 的诞生。实际上,Http2.0 是以 SPDY 为原型进行讨论和标准化的,当然也做了更多的改进和调整。
|
||||||
|
|
||||||
|
随着 Http2.0 的出现和普及,许多与 Stubby 相同的功能已经出现在公共标准中,包括 Stubby 未提供的其他功能。很明显,是时候重做 Stubby 以利用这种标准化,并将其适用范围扩展到分布式计算的最后一英里,支持移动设备(如安卓)、物联网(IOT)、和浏览器连接到后端服务。
|
||||||
|
|
||||||
|
2015 年 3 月,Google决定在公开场合构建下一版 Stubby,以便与业界分享经验,并进行相关合作,也就是本文的主角`gRPC`。
|
||||||
|
|
||||||
|
### 高效编码-protobuf
|
||||||
|
|
||||||
|
回头来看第 1 个问题,解决起来相对比较简单,无非是将傻瓜式字符编码转为更有效的二进制编码(比如数字 10000 JSON 编码后是 5 个字节,按整型编码就是 4 个字节),同时加上些事先约定的编码算法使得最终结果更紧凑。常见的平台无关的编码格式有`MessagePack`和`protobuf`等,我们以 protobuf 为例。
|
||||||
|
|
||||||
|
protobuf 采用 `varint` 和 处理负数的 `ZigZag` 两种编码方式使得数值字段占用空间大大减少;同时它约定了字段类型和标识,采用 `TLV` 方式,将字段名映射为小范围结果集中的一项(比如对于不超过 256 个字段的数据体来说,不管字段名本身的长度多少,每个字段名都只要 1 个字节就能标识),同时移除了分隔符,并且可以过滤空字段(若字段没有被赋值,那么该字段不会出现在序列化结果中)。
|
||||||
|
|
||||||
|
### 高效编程-代码生成工具
|
||||||
|
|
||||||
|
第 2 个问题呢,其实需要的就是[每个平台]一套代码生成工具。生成的代码需要覆盖类的定义、对象的序列化/反序列化、服务接口的暴露和远程调用等等必要的模板代码,如此,开发人员只需要负责接口文档的维护和业务代码的实现(很自然的面向接口编程:))。此时,采用 protobuf 的`gRPC`自然而然的映入眼帘,因为对于目前所有主要的编程语言和平台,都有 gRPC 工具和库,包括 .NET、Java、Python、Go、C++、Node.js、Swift、Dart、Ruby 以及 PHP。可以说,这些工具和库的提供,使得 gRPC 可以跨多种语言和平台一致地工作,成为一个全面的 RPC 解决方案。
|
||||||
|
|
||||||
|
## gRPC 在 .NET 中的使用
|
||||||
|
|
||||||
|
`gRPC`作为 .NET 平台中的“一等公民”。
|
||||||
|
|
||||||
|
## proto文件
|
||||||
|
|
||||||
|
```protobuf
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option csharp_namespace = "GrpcDemo.Service";
|
||||||
|
|
||||||
|
package greet;
|
||||||
|
|
||||||
|
// The greeting service definition.
|
||||||
|
service Greeter {
|
||||||
|
// Sends a greeting
|
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request message containing the user's name.
|
||||||
|
message HelloRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The response message containing the greetings.
|
||||||
|
message HelloReply {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- syntax 标识Protobuf版本为v3
|
||||||
|
- option csharp_namespace 标识生成C#类的命名空间
|
||||||
|
- package 标识proto文件的命名空间
|
||||||
|
- service 定义服务
|
||||||
|
- rpc FuncName (Input) returns (Output) 定义一个远程过程
|
||||||
|
- message 声明数据结构
|
||||||
|
|
||||||
|
### Protobuf 消息(message)
|
||||||
|
|
||||||
|
消息是 Protobuf 中的主要数据传输对象。 它们在概念上类似于 .NET 类。
|
||||||
|
|
||||||
|
```protobuf
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option csharp_namespace = "Contoso.Messages";
|
||||||
|
|
||||||
|
message Person {
|
||||||
|
int32 id = 1;
|
||||||
|
string first_name = 2;
|
||||||
|
string last_name = 3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
前面的消息定义将三个字段指定为名称/值对。 与 .NET 类型上的属性类似,每个字段都有名称和类型。 字段类型可以是 Protobuf 标量值类型(如 `int32`),也可以是其他消息。
|
||||||
|
|
||||||
|
### 标量值类型
|
||||||
|
|
||||||
|
Protobuf 支持一系列本机标量值类型。 下表列出了全部本机标量值类型及其等效 C# 类型:
|
||||||
|
|
||||||
|
| **Protobuf 类型** | **C# 类型** |
|
||||||
|
| ----------------- | ------------ |
|
||||||
|
| `double` | `double` |
|
||||||
|
| `float` | `float` |
|
||||||
|
| `int32` | `int` |
|
||||||
|
| `int64` | `long` |
|
||||||
|
| `uint32` | `uint` |
|
||||||
|
| `uint64` | `ulong` |
|
||||||
|
| `sint32` | `int` |
|
||||||
|
| `sint64` | `long` |
|
||||||
|
| `fixed32` | `uint` |
|
||||||
|
| `fixed64` | `ulong` |
|
||||||
|
| `sfixed32` | `int` |
|
||||||
|
| `sfixed64` | `long` |
|
||||||
|
| `bool` | `bool` |
|
||||||
|
| `string` | `string` |
|
||||||
|
| `bytes` | `ByteString` |
|
||||||
|
|
||||||
|
### 日期和时间
|
||||||
|
|
||||||
|
本机标量类型不提供与 .NET 的 [DateTimeOffset](https://learn.microsoft.com/zh-cn/dotnet/api/system.datetimeoffset)、[DateTime](https://learn.microsoft.com/zh-cn/dotnet/api/system.datetime) 和 [TimeSpan](https://learn.microsoft.com/zh-cn/dotnet/api/system.timespan) 等效的日期和时间值。 可使用 Protobuf 的一些“已知类型”扩展来指定这些类型。 这些扩展为受支持平台中的复杂字段类型提供代码生成和运行时支持。
|
||||||
|
|
||||||
|
下表显示日期和时间类型:
|
||||||
|
|
||||||
|
| .NET 类型 | Protobuf 已知类型 |
|
||||||
|
| :--------------- | :-------------------------- |
|
||||||
|
| `DateTimeOffset` | `google.protobuf.Timestamp` |
|
||||||
|
| `DateTime` | `google.protobuf.Timestamp` |
|
||||||
|
| `TimeSpan` | `google.protobuf.Duration` |
|
||||||
|
|
||||||
|
```c#
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
message Meeting {
|
||||||
|
string subject = 1;
|
||||||
|
google.protobuf.Timestamp start = 2;
|
||||||
|
google.protobuf.Duration duration = 3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
C# 类中生成的属性不是 .NET 日期和时间类型。 属性使用 `Google.Protobuf.WellKnownTypes` 命名空间中的 `Timestamp` 和 `Duration` 类。 这些类提供在 `DateTimeOffset`、`DateTime` 和 `TimeSpan` 之间进行转换的方法。
|
||||||
|
|
||||||
|
```c#
|
||||||
|
// Create Timestamp and Duration from .NET DateTimeOffset and TimeSpan.
|
||||||
|
var meeting = new Meeting
|
||||||
|
{
|
||||||
|
Time = Timestamp.FromDateTimeOffset(meetingTime), // also FromDateTime()
|
||||||
|
Duration = Duration.FromTimeSpan(meetingLength)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert Timestamp and Duration to .NET DateTimeOffset and TimeSpan.
|
||||||
|
var time = meeting.Time.ToDateTimeOffset();
|
||||||
|
var duration = meeting.Duration?.ToTimeSpan();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 可为 null 的类型
|
||||||
|
|
||||||
|
C# 的 Protobuf 代码生成使用本机类型,如 `int` 表示 `int32`。 因此这些值始终包括在内,不能为 `null`。
|
||||||
|
|
||||||
|
对于需要显式 `null` 的值(例如在 C# 代码中使用 `int?`),Protobuf 的“已知类型”包括编译为可以为 null 的 C# 类型的包装器。 若要使用它们,请将 `wrappers.proto` 导入到 `.proto` 文件中,如以下代码所示:
|
||||||
|
|
||||||
|
```protobuf
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
|
||||||
|
message Person {
|
||||||
|
// ...
|
||||||
|
google.protobuf.Int32Value age = 5;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`wrappers.proto` 类型不会在生成的属性中公开。 Protobuf 会自动将它们映射到 C# 消息中相应的可为 null 的 .NET 类型。 例如,`google.protobuf.Int32Value` 字段生成 `int?` 属性。 引用类型属性(如 `string` 和 `ByteString` )保持不变,但可以向它们分配 `null`,这不会引发错误。
|
||||||
|
|
||||||
|
下表完整列出了包装器类型以及它们的等效 C# 类型:
|
||||||
|
|
||||||
|
| C# 类型 | 已知类型包装器 |
|
||||||
|
| :----------- | :---------------------------- |
|
||||||
|
| `bool?` | `google.protobuf.BoolValue` |
|
||||||
|
| `double?` | `google.protobuf.DoubleValue` |
|
||||||
|
| `float?` | `google.protobuf.FloatValue` |
|
||||||
|
| `int?` | `google.protobuf.Int32Value` |
|
||||||
|
| `long?` | `google.protobuf.Int64Value` |
|
||||||
|
| `uint?` | `google.protobuf.UInt32Value` |
|
||||||
|
| `ulong?` | `google.protobuf.UInt64Value` |
|
||||||
|
| `string` | `google.protobuf.StringValue` |
|
||||||
|
| `ByteString` | `google.protobuf.BytesValue` |
|
||||||
5
source/_posts/日志记录.md
Normal file
5
source/_posts/日志记录.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: 设计模式
|
||||||
|
date: 2023-01-03 10:11:47
|
||||||
|
author: 文永达
|
||||||
|
---
|
||||||
Loading…
x
Reference in New Issue
Block a user