美文网首页.NET
.Net微服务,一步一步从零开始搭建 .Net6 + Mong

.Net微服务,一步一步从零开始搭建 .Net6 + Mong

作者: KunHo | 来源:发表于2022-07-18 17:17 被阅读0次

    我的开发环境:VS Code、Docker Desktop,都是目前的最新版本。

    1.创建RESTful API

    首先,我们新建一个文件夹,并用vs code打开该文件夹(我的文件夹名称叫"dotnet_docker")。
    然后我们打开shell命令行,输入如下命令:

    dotnet new webapi -o StudentApi
    cd StudentApi
    

    创建一个名为"StudentApi"的webapi项目,并切换到该项目的目录下。
    如图1:

    图1

    添加mongodb驱动,输入如下命令:

    dotnet add package MongoDB.Driver
    
    • 添加model
      创建一个文件夹名为"Models",然后在里面添加一个"Student"的class,代码如下:
    using MongoDB.Bson;
    using MongoDB.Bson.Serialization.Attributes;
    
    namespace StudentApi.Models;
    
    public class Student
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string? Id { get; set; }
    
        [BsonElement("name")]
        public string Name { get; set; } = null!;
    
        [BsonElement("age")]
        public int Age { get; set; }
    }
    
    • 添加数据库配置
      修改开发环境配置文件appsettings.Development.json,添加"StudentStoreDatabase"节点,代码如下:
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "StudentStoreDatabase": {
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "StudentStore",
        "StudentsCollectionName": "Students"
      }
    }
    

    在"Models"文件夹添加一个名为"StudentStoreDatabaseSettings"的model用来映射"StudentStoreDatabase节点,代码如下:

    namespace StudentApi.Models;
    
    public class StudentStoreDatabaseSettings
    {
        public string ConnectionString { get; set; } = null!;
    
        public string DatabaseName { get; set; } = null!;
    
        public string StudentsCollectionName { get; set; } = null!;
    }
    
    • 在Program.cs文件中,添加数据库映射
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<StudentStoreDatabaseSettings>(
        builder.Configuration.GetSection("StudentStoreDatabase")); //添加数据库映射
    

    在最顶部添加StudentStoreDatabaseSettings的引用

    using StudentApi.Models;
    
    • 添加增删改查CRUD service
      创建一个名为"Services"文件夹,并往里面添加"StudentsService"的class
    using StudentApi.Models;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    
    namespace StudentApi.Services;
    
    public class StudentsService
    {
        private readonly IMongoCollection<Student> _studentsCollection;
    
        public StudentsService(
            IOptions<StudentStoreDatabaseSettings> studentStoreDatabaseSettings)
        {
            var mongoClient = new MongoClient(
                studentStoreDatabaseSettings.Value.ConnectionString);
    
            var mongoDatabase = mongoClient.GetDatabase(
                studentStoreDatabaseSettings.Value.DatabaseName);
    
            _studentsCollection = mongoDatabase.GetCollection<Student>(
                studentStoreDatabaseSettings.Value.StudentsCollectionName);
        }
    
        public async Task<List<Student>> GetAsync() =>
            await _studentsCollection.Find(_ => true).ToListAsync();
    
        public async Task<Student?> GetAsync(string id) =>
            await _studentsCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
    
        public async Task CreateAsync(Student newStudent) =>
            await _studentsCollection.InsertOneAsync(newStudent);
    
        public async Task UpdateAsync(string id, Student updatedStudent) =>
            await _studentsCollection.ReplaceOneAsync(x => x.Id == id, updatedStudent);
    
        public async Task RemoveAsync(string id) =>
            await _studentsCollection.DeleteOneAsync(x => x.Id == id);
    }
    
    
    • 添加单例模式依赖(singleton)
      这里用singleton而不是像之前的EF那样用scoped,因为根据官网文档它是直接依赖MongoClient。
      在Program.cs添加如下代码代码:
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<StudentStoreDatabaseSettings>(
        builder.Configuration.GetSection("StudentStoreDatabase"));//添加数据库映射
    builder.Services.AddSingleton<StudentsService>(); //添加单例模式依赖(singleton)
    
    • 添加controller
      在Controllers文件夹添加""的class文件:
    using StudentApi.Models;
    using StudentApi.Services;
    using Microsoft.AspNetCore.Mvc;
    
    namespace StudentApi.Controllers;
    
    [ApiController]
    [Route("api/[controller]")]
    public class StudentsController : ControllerBase
    {
        private readonly StudentsService _studentsService;
    
        public StudentsController(StudentsService studentsService) =>
            _studentsService = studentsService;
    
        [HttpGet]
        public async Task<List<Student>> Get() =>
            await _studentsService.GetAsync();
    
        [HttpGet("{id:length(24)}")]
        public async Task<ActionResult<Student>> Get(string id)
        {
            var student = await _studentsService.GetAsync(id);
    
            if (student is null)
            {
                return NotFound();
            }
    
            return student;
        }
    
        [HttpPost]
        public async Task<IActionResult> Post(Student newStudent)
        {
            await _studentsService.CreateAsync(newStudent);
    
            return CreatedAtAction(nameof(Get), new { id = newStudent.Id }, newStudent);
        }
    
        [HttpPut("{id:length(24)}")]
        public async Task<IActionResult> Update(string id, Student updatedStudent)
        {
            var student = await _studentsService.GetAsync(id);
    
            if (student is null)
            {
                return NotFound();
            }
    
            updatedStudent.Id = student.Id;
    
            await _studentsService.UpdateAsync(id, updatedStudent);
    
            return NoContent();
        }
    
        [HttpDelete("{id:length(24)}")]
        public async Task<IActionResult> Delete(string id)
        {
            var student = await _studentsService.GetAsync(id);
    
            if (student is null)
            {
                return NotFound();
            }
    
            await _studentsService.RemoveAsync(id);
    
            return NoContent();
        }
    }
    

    另外,需要把https跳转关了,因为我们本地没有验证证书。
    在Program.cs文件中,在注释"app.UseHttpsRedirection();"

    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    
    //注释这里
    // app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    
    

    至此,整体目录结构应该如图2:


    图2
    • 测试web API
      打开shell命令行,输入如下命令运行项目:
     dotnet run
    

    运行成功应该会如图3所示:


    图3
    • 测试API
      这边我是用Postman来测试请求:
      图4,post添加数据:


      图4

    图5,get请求所有数据:


    图5

    2.创建Dockerfile

    Dockerfile就是把你目前的项目打包成已经镜像,然后用这个镜像进行部署。
    我们先在shell命令行按 "control+c" 把运行中的项目停了,然后在项目目录(StudentApi)中添加一个名为"Dockerfile"的文件,注意不要加任何后续,如"txt"这些,并添加如下代码:

    #第一阶段,利用sdk镜像环境生成发布dll,主要是运行"dotnet publish"这个命令;
    #这个阶段也可以在外面用shell直接运行。
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-evn
    WORKDIR /source
    
    COPY . ./
    RUN dotnet restore
    RUN dotnet publish -c Release -o /out
    
    #第二阶段,利用aspnet镜像运行第一阶段生成发布的dll,主要是"dotnet xxx.dll"这个命令,跟我们在linux运行.net一样
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    WORKDIR /app
    
    COPY --from=build-evn /out .
    ENTRYPOINT ["dotnet","StudentApi.dll"]
    
    

    3.创建docker-compose.yml

    有时候我们的docker run命令会很长很长,每次部署服务器时候都写一次十分不现实, docker-compose可以把你docker run命令写到一个文件中,而且默认是用同一个docker network,假如你安装的是docker desktop,则不需要额外安装docker-compose,如果你是linux服务器,除了安装docker engine外,还要自己手动安装docker-compose。
    在项目目录(StudentApi)中添加一个名为"docker-compose.yml"的文件,并添加如下代码:

    version: '3.6'
    services:
      web:
        build: . #根目录下会找到我们之前的Dockerfile,并运行生成镜像
        ports:
          - "8080:80" #在docker容器中.net默认是80端口,可以通过environment指定
        depends_on:
          - db
      
      db: #这里名称会默认为网络的别名,这样我们web就可以不需要知道mongodb的ip,直接用这个名称代替ip
        image: mongo #我这里的mongodb没有指定用户密码,可以通过environment指定
        
    

    注意,我这里没有用 volume,所以容器一旦关掉了数据都丢失了,我这里不是服务器,只是演示,所以我希望数据用完就丢失,假如有需要的同学可以加个volume

    4.修改数据库连接

    在1步中,我们用来连接数据的配置文件是"appsettings.Development.json",这文件在开发环境生效,
    现在我们需要在"appsettings.json"添加mongodb的配置,添加"StudentStoreDatabase"节点,代码如下:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "StudentStoreDatabase": {
        "ConnectionString": "mongodb://db:27017",
        "DatabaseName": "StudentStore",
        "StudentsCollectionName": "Students"
      }
    }
    

    这里注意ConnectionString,在"appsettings.Development.json"中是"localhost",现在我们改成"db",db这个名字在"docker-compose.yml"文件中取。

    5.打包镜像并运行

    打开shell命令行,输入如下命令运行打包镜像并运行:

    docker-compose up -d
    

    运行成功应该会如图6:


    图6

    我们ps一下看看当前运行的镜像(图7):


    图7

    这两个就是我们刚才运行的运行的镜像。

    6.测试

    我们刚才在docker-compose.yml指定了映射8080端口,先在在Postman访问http://localhost:8080/api/students,get一下所有数据,如图7:

    image.png
    然后我们随便post加一条数据,如图8:
    图8
    我们再回过来get所有数据,如图9:
    图9
    进入mongo容器查看一下我们刚才数据:
    在shell命令行ps一下拿到id并exec进去,并连接mongodb,如图10:
    图10
    找到我们创建的数据库,集,并查看数据,如图11:
    图11

    再一次提醒,这里数据因为我没有在docker-compose.yml加volume,所以容器关了就会丢失。

    至此,完成。

    相关文章

      网友评论

        本文标题:.Net微服务,一步一步从零开始搭建 .Net6 + Mong

        本文链接:https://www.haomeiwen.com/subject/uwnrirtx.html