WebApi使用 (.Net Framework版)

1 创建

使用.Net做web后端,推荐使用.Net Core,微软在此基础上做了很多适配,包括内置Swagger,可以直接启动等等。而.Net Framework版,需要手动配置很多内容。

如果需要调用的项目是基于.Net Framework,那么web项目也应基于.Net Framework开发。或者其他原因不得不使用.Net Framework开发web项目,可以参考本文。

打开VS,在搜索栏输入“ASP.NET Web”,选择.Net Framework版,注意,这里要创建的是空白API项目,在前后端分离的项目中只作为后端接口,而不是MVC(模型-视图-控制器)

填写项目名,选择位置,选择需要的框架

创建一个空白项目,勾选“Web API”,取消勾选“HTTPS配置”

添加完成后,会创建以下目录结构:

  • “App_Data”目录用于方式一些资源文件;
  • “App_Start”目录下用于放置一些配置资源,默认已有一个配置类“WebApiConfig”,内容如下:
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}
- config.MapHttpAttributeRoutes();表示启用了属性路由,允许在控制器和操作方法上直接使用特性(如 [Route])来定义路由规则。
- 下半部分表示定义默认路由规则。
  • “Controllers”目录下放置对外接口;
  • “Models”目录下放置后端接口的内部逻辑,比如要接入数据库的操作等等。这些目录作为一个规范,如果违反这个规范随意放置,也可以正常运行,只不过看着比较杂乱。

2 测试

项目创建完成后,并没有提供任何对外接口,添加一个测试接口。选中“Controllers”目录=>右键=>添加=>Web API控制器类

填写名称,建议名称为“xxxController”(xxx为需要写的名称),此名称会被上文提到的“默认路由规则”匹配,将“xxx”作为api的一部分。

类创建完成后,会自动生成示例程序,包含Get, Post, Put, Delete请求

public class TestController : ApiController
{
    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/<controller>
    public void Post([FromBody] string value)
    {
    }

    // PUT api/<controller>/5
    public void Put(int id, [FromBody] string value)
    {
    }

    // DELETE api/<controller>/5
    public void Delete(int id)
    {
    }
}

启动项目,基于.Net Framework的web项目需要借助于服务启动,vs调试默认使用IIS服务。

启动完成后,没有配置默认的访问地址就会显示如下界面。

测试Api访问。

3 配置属性路由规则

上文提到,配置类“WebApiConfig”中配置了默认路由规则,启用了属性路由。属性路由就是使用特性标记路由,使用属性路由代替了默认路由。

示例如下:

[RoutePrefix("api/TestABC")]
public class TestController : ApiController
{
    [HttpGet]
    [Route("GetValue")]
    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

启动,测试访问,可以看到,路由规则已经由默认路由规则变为了属性路由规则。

4 配置Swagger

4.1 基本配置

在NuGet中下载安装“Swashbuckle”

安装完成后,在“App_Start”目录下会自动生成“SwaggerConfig”配置类。可以修改需要显示的内容,下图这个语句包含两条信息,“版本”和“Title”。

在项目属性中,勾选生成“XML文档文件”,本质上是Swagger将此xml转换为Swagger格式的内容。

安装完之后,再访问本地URL,可能会报一个错,这里不要慌,一般是安装的“Swashbuckle”包依赖的内容与现有安装的包不相符,在NuGet包管理器中全部更到最新即可。

启动后在原有url后加入/swagger即可访问文档。

展开后,可以点击“Try it out”按钮进行测试。

请求与相应如下:

测试Post,字符串一定要带""

程序中获取到浏览器发送的内容。

4.2 为程序添加注释

上文提到,勾选了生成“XML文档文件”,此xml是将写的注释记录下来。

比如为Get请求添加注释。

/// <summary>
/// 测试请求
/// </summary>
/// <returns>返回示例数据</returns>
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

然后在SwaggerConfig配置类中添加一条配置。

c.IncludeXmlComments(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin\\TestWebApi.xml"));

再次访问,可以看到,有了注释的内容。

4.3 汉化处理

安装“Swagger.Net.UI”

安装完成后,在“App_Start”目录下新增了一个SwaggerNet类

打开SwaggerNet类,注释掉这两行(这里我没做深究,参考的几篇文章都说注释掉这两行,可能后续运行有报错)

创建一个“SwaggerControllerDescProvider”类,用于对swagger文档中的内容进行汉化处理。

/// <summary>
/// swagger显示控制器的描述
/// </summary>
public class SwaggerControllerDescProvider : ISwaggerProvider
{
    private readonly ISwaggerProvider _swaggerProvider;
    private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
    private readonly string _xml;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="swaggerProvider"></param>
    /// <param name="xml">xml文档路径</param>
    public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
    {
        _swaggerProvider = swaggerProvider;
        _xml = xml;
    }

    public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
    {
        var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
        SwaggerDocument srcDoc = null;
        //只读取一次
        if (!_cache.TryGetValue(cacheKey, out srcDoc))
        {
            srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);

            srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
            _cache.TryAdd(cacheKey, srcDoc);
        }
        return srcDoc;
    }

    /// <summary>
    /// 从API文档中读取控制器描述
    /// </summary>
    /// <returns>所有控制器描述</returns>
    public ConcurrentDictionary<string, string> GetControllerDesc()
    {
        string xmlpath = _xml;
        ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
        if (File.Exists(xmlpath))
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(xmlpath);
            string type = string.Empty, path = string.Empty, controllerName = string.Empty;

            string[] arrPath;
            int length = -1, cCount = "Controller".Length;
            XmlNode summaryNode = null;
            foreach (XmlNode node in xmldoc.SelectNodes("//member"))
            {
                type = node.Attributes["name"].Value;
                if (type.StartsWith("T:"))
                {
                    //控制器
                    arrPath = type.Split('.');
                    length = arrPath.Length;
                    controllerName = arrPath[length - 1];
                    if (controllerName.EndsWith("Controller"))
                    {
                        //获取控制器注释
                        summaryNode = node.SelectSingleNode("summary");
                        string key = controllerName.Remove(controllerName.Length - cCount, cCount);
                        if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
                        {
                            controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
                        }
                    }
                }
            }
        }
        return controllerDescDict;
    }
}

在SwaggerUI文件夹中,创建一个swagger_lang.js的js,用于对swagger进行汉化处理(注:这个文件必须添加,否则汉化将失败)

swagger_lang.js 文件中的js内容如下。在最后几行有“公司名称”和对应的Url,可以自行更改,这里我写了百度的链接作为测试。

/// <summary>
/// 中文转换
/// </summary>
var SwaggerTranslator = (function () {
    //定时执行检测是否转换成中文,最多执行500次  即500*50/1000=25s
    var iexcute = 0,
        //中文语言包
        _words = {
            "Warning: Deprecated": "警告:已过时",
            "Implementation Notes": "实现备注",
            "Response Class": "响应类",
            "Status": "状态",
            "Parameters": "参数",
            "Parameter": "参数",
            "Value": "值",
            "Description": "描述",
            "Parameter Type": "参数类型",
            "Data Type": "数据类型",
            "Response Messages": "响应消息",
            "HTTP Status Code": "HTTP状态码",
            "Reason": "原因",
            "Response Model": "响应模型",
            "Request URL": "请求URL",
            "Response Body": "响应体",
            "Response Code": "响应码",
            "Response Headers": "响应头",
            "Hide Response": "隐藏响应",
            "Headers": "头",
            "Try it out!": "试一下!",
            "Show/Hide": "显示/隐藏",
            "List Operations": "显示操作",
            "Expand Operations": "展开操作",
            "Raw": "原始",
            "can't parse JSON.  Raw result": "无法解析JSON. 原始结果",
            "Model Schema": "模型架构",
            "Model": "模型",
            "apply": "应用",
            "Username": "用户名",
            "Password": "密码",
            "Terms of service": "服务条款",
            "Created by": "创建者",
            "See more at": "查看更多:",
            "Contact the developer": "联系开发者",
            "api version": "api版本",
            "Response Content Type": "响应Content Type",
            "fetching resource": "正在获取资源",
            "fetching resource list": "正在获取资源列表",
            "Explore": "浏览",
            "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
            "Can't read from server.  It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。",
            "Please specify the protocol for": "请指定协议:",
            "Can't read swagger JSON from": "无法读取swagger JSON于",
            "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI",
            "Unable to read api": "无法读取api",
            "from path": "从路径",
            "Click to set as parameter value": "点击设置参数",
            "server returned": "服务器返回"
        },
 
        //定时执行转换
        _translator2Cn = function () {
            if ($("#resources_container .resource").length > 0) {
                _tryTranslate();
            }
 
            if ($("#explore").text() == "Explore" && iexcute < 500) {
                iexcute++;
                setTimeout(_translator2Cn, 50);
            }
        },
 
        //设置控制器注释
        _setControllerSummary = function () {
            $.ajax({
                type: "get",
                async: true,
                url: $("#input_baseUrl").val(),
                dataType: "json",
                success: function (data) {
                    var summaryDict = data.ControllerDesc;
                    var id, controllerName, strSummary;
                    $("#resources_container .resource").each(function (i, item) {
                        id = $(item).attr("id");
                        if (id) {
                            controllerName = id.substring(9);
                            strSummary = summaryDict[controllerName];
                            if (strSummary) {
                                var option = $(item).children(".heading").children(".options");
                                if ($(option).children(".controller-summary").length > 0) {
                                    $(option).children(".controller-summary").remove();
                                }
                                $(option).prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
                            }
                        }
                    });
                }
            });
        },
 
        //尝试将英文转换成中文
        _tryTranslate = function () {
            $('[data-sw-translate]').each(function () {
                $(this).html(_getLangDesc($(this).html()));
                $(this).val(_getLangDesc($(this).val()));
                $(this).attr('title', _getLangDesc($(this).attr('title')));
            });
        },
        _getLangDesc = function (word) {
            return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;
        };
 
    return {
        Translator: function () {
            $("#logo").html("公司名称").attr("href", "https://www.baidu.com");
            $('body').append('<style type="text/css">.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} </style>');
            //设置控制器描述
            _setControllerSummary();
            _translator2Cn();
        },
        translate: function () {
            this.Translator();
        }
    }
})();
//执行转换
SwaggerTranslator.Translator();

新增的swagger_lang.js文件需要修改文件属性,将文件生成操作修改为“嵌入的资源”。

将创建的swagger_lang.js在SwaggerConfig文件中进行引用。注意文件的路径。

c.InjectJavaScript(thisAssembly, "TestWebApi.SwaggerUI.swagger_lang.js");  //引用中文包

汉化结果:

5 包装返回结果

5.1 IHttpActionResult接口

默认生成的测试程序,请求到的数据都直接返回的数据内容。

public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

// GET api/<controller>/5
public string Get(int id)
{
    return "value";
}

如果需要自主决定状态码或者返回错误结果内容时携带异常信息等,可以使用C#提供的IHttpActionResult接口。

public IHttpActionResult Get()
{
    return Ok(new string[] { "value1", "value2" });
}

其中Ok()是ASP.NET Web API 提供了一些常用的IHttpActionResult实现,代表200状态码,只使用Ok(),与不使用IHttpActionResult接口并无明显的区别。

5.2 其它方法

除了常见的 Ok 方法外,ASP.NET Web API 还提供了多个 IHttpActionResult 的实现类或方法,用于构建特定的 HTTP 响应。以下是常用的 IHttpActionResult 实现及其对应的用途:

5.2.1 Ok
  • 返回 HTTP 状态码:200 OK
  • 用法
    • 用于返回一个成功的响应,并可以附带一个对象作为响应体。
public IHttpActionResult Get()
{
    var data = new { Id = 1, Name = "Example" };
    return Ok(data);
}

5.2.2 BadRequest
  • 返回 HTTP 状态码:400 Bad Request
  • 用法
    • 用于表示客户端发送的请求无效,例如参数验证失败或格式错误。
public IHttpActionResult Post(string value)
{
    if (string.IsNullOrEmpty(value))
    {
        return BadRequest("Value cannot be null or empty.");
    }
    return Ok();
}

5.2.3 Unauthorized
  • 返回 HTTP 状态码:401 Unauthorized
  • 用法
    • 用于指示需要身份验证或身份验证失败。
public IHttpActionResult Get()
{
    if (!User.Identity.IsAuthenticated)
    {
        return Unauthorized();
    }
    return Ok();
}

5.2.4 NotFound
  • 返回 HTTP 状态码:404 Not Found
  • 用法
    • 用于表示所请求的资源不存在。
public IHttpActionResult Get(int id)
{
    var item = _repository.GetItem(id);
    if (item == null)
    {
        return NotFound();
    }
    return Ok(item);
}

5.2.5 Conflict
  • 返回 HTTP 状态码:409 Conflict
  • 用法
    • 用于表示请求无法完成,因为发生了冲突(例如重复数据或违反约束)。
public IHttpActionResult Post(Item item)
{
    if (_repository.Contains(item.Id))
    {
        return Conflict();
    }
    _repository.Add(item);
    return Ok();
}

5.2.6 Created / CreatedAtRoute
  • 返回 HTTP 状态码:201 Created
  • 用法
    • 用于表示资源已成功创建,并可以附带新资源的 URI。
public IHttpActionResult Post(Item item)
{
    _repository.Add(item);
    return Created(new Uri(Request.RequestUri + "/" + item.Id), item);
}

// 或者使用 CreatedAtRoute 指定路由名称
public IHttpActionResult Post(Item item)
{
    _repository.Add(item);
    return CreatedAtRoute("DefaultApi", new { id = item.Id }, item);
}

5.2.7 NoContent
  • 返回 HTTP 状态码:204 No Content
  • 用法
    • 用于表示请求已成功处理,但不需要返回响应体内容(例如更新操作)。
public IHttpActionResult Put(int id, Item item)
{
    if (!_repository.Update(id, item))
    {
        return NotFound();
    }
    return StatusCode(HttpStatusCode.NoContent); // 或者直接 NoContent()
}

5.2.8 Redirect / RedirectToRoute
  • 返回 HTTP 状态码:302 Found 或其他重定向状态码
  • 用法
    • 用于表示需要重定向到另一个 URI。
public IHttpActionResult Get()
{
    return Redirect("https://www.example.com");
}

// 使用特定路由
public IHttpActionResult Get()
{
    return RedirectToRoute("DefaultApi", new { id = 1 });
}

5.2.9 InternalServerError
  • 返回 HTTP 状态码:500 Internal Server Error
  • 用法
    • 用于表示服务器内部发生错误。
public IHttpActionResult Get()
{
    try
    {
        // 处理逻辑
    }
    catch (Exception ex)
    {
        return InternalServerError(ex);
    }
}

5.2.10 ResponseMessage
  • 返回自定义的 HTTP 响应消息
  • 用法
    • 用于完全自定义 HTTP 响应,灵活构建响应消息。
public IHttpActionResult Get()
{
    var response = Request.CreateResponse(HttpStatusCode.OK, "Custom Message");
    return ResponseMessage(response);
}

5.2.11 StatusCode
  • 返回任意 HTTP 状态码
  • 用法
    • 用于返回特定的 HTTP 状态码,而不需要返回额外的内容。
public IHttpActionResult Delete(int id)
{
    _repository.Remove(id);
    return StatusCode(HttpStatusCode.NoContent); // 返回 204 No Content
}

5.2.12 Json
  • 返回 JSON 格式的响应
  • 用法
    • 用于直接返回 JSON 数据,而不依赖模型绑定。
public IHttpActionResult Get()
{
    var data = new { Id = 1, Name = "Example" };
    return Json(data);
}

5.2.13 ExceptionResult
  • 返回异常结果
  • 用法
    • 用于返回一个表示异常的响应。
public IHttpActionResult Get()
{
    try
    {
        throw new InvalidOperationException("An unexpected error occurred.");
    }
    catch (Exception ex)
    {
        return InternalServerError(ex); // 适用于返回异常信息的场景
    }
}

5.2.14 NotImplemented
  • 返回 HTTP 状态码:501 Not Implemented
  • 用法
    • 用于表示服务端还未实现某个功能。
public IHttpActionResult Get()
{
    return StatusCode(HttpStatusCode.NotImplemented);
}

5.2.15 总结

以下是常见的 IHttpActionResult 方法及其对应的 HTTP 状态码:

方法HTTP 状态码描述
Ok200 OK请求成功并返回数据。
BadRequest400 Bad Request客户端请求无效。
Unauthorized401 Unauthorized表示未通过身份验证。
NotFound404 Not Found资源不存在。
Conflict409 Conflict请求冲突(如违反约束)。
Created201 Created成功创建资源,并返回资源 URI。
NoContent204 No Content请求成功,但没有返回内容。
Redirect302 Found重定向到另一个 URI。
InternalServerError500 Internal Server Error服务器内部错误。
ResponseMessage自定义状态码返回自定义的 HTTP 响应消息。
StatusCode任意状态码返回指定的 HTTP 状态码。
Json任意状态码返回 JSON 响应内容。

通过这些方法,开发者可以灵活地编写符合 HTTP 规范的响应,满足各种 RESTful API 的需求。

6 标明返回类型

书接第五部分,返回类型如果使用IHttpActionResult接口,Swagger文档中无法解析出响应的具体内容,如下图所示。

如果希望显示响应内容,可以使用特性标明。

[SwaggerResponse(200, "Success", typeof(string[]))]
public IHttpActionResult Get()
{
    return Ok(new string[] { "value1", "value2" });
}

有关这方面的扩展内容很多,感兴趣可以自行查阅。

7 一键启动

在项目的Web.config文件同目录下创建一个.bat文件

.bat文件的内容如下,相关信息修改为适合本项目的内容。这里有一点,正常来说应该先启动IIS Express,再执行“浏览器访问URL”,但是启动IIS Express这个行为会阻塞到当前语句,不再往下执行,所以这里将“浏览器访问URL”语句提前,浏览器会等待IIS Express启动后访问成功。

@echo off
:: 设置IIS Express的路径(通常位于Program Files中,如果安装在其他位置,请调整路径)
set IIS_EXPRESS_PATH="C:\Program Files\IIS Express\iisexpress.exe"

:: 项目的物理路径,这条语句不需要修改,意为访问bat文件所在目录
cd /d "%~dp0"

:: Web项目的端口
set PORT=63027

:: 项目的启动URL(如果需要)
set URL=http://localhost:%PORT%/swagger/ui/index#/

:: 打开默认浏览器访问URL(可选)
start %URL%

:: 启动IIS Express
%IIS_EXPRESS_PATH% /path:"%cd%" /port:%PORT%

pause

双击该bat文件即可将项目内容自动配置到IIS服务中。

8 打包

选择“发布”。

发布位置选择“文件夹”。

点击“发布”。

生成的内容如下:

将“配置Swagger”中生成的xml文件拷到bin目录下,这是Swagger文档的基础,发布操作不会自动复制该文件,需要手动复制。然后将“一键启动”生成的.bat文件复制到Web.config文件同目录下,双击即可打开。

9 参考

.net framework中webapi使用swagger进行接口文档展示

ASP.NET WebApi项目框架搭建(一):创建项目

WebApi 接口返回值类型详解 ( 转 )

如果觉得文章还不错的话,请点一个大大的赞吧,感谢支持!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/946372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 ASP.NET Core wwwroot 上传和存储文件

在 ASP.NET Core 应用程序中上传和存储文件是用户个人资料、产品目录等功能的常见要求。本指南将解释使用wwwroot存储图像&#xff08;可用于文件&#xff09;的过程以及如何在应用程序中处理图像上传。 步骤 1&#xff1a;设置项目环境 确保您的 ASP.NET 项目中具有必要的依…

2024年中国新能源汽车用车发展怎么样 PaperGPT(一)

概述 在国家政策的强力扶持下&#xff0c;2024年中国新能源汽车市场迎来了新的发展机遇。本文将基于《中国新能源汽车用车报告&#xff08;2024年&#xff09;》的数据&#xff0c;对新能源汽车的市场发展和用车趋势概述。 新能源汽车市场发展 政策推动&#xff1a;国家和地…

[论文粗读]A Simple Framework for Contrastive Learning of Visual Representations

引言 今天带来一篇经典论文A Simple Framework for Contrastive Learning of Visual Representations的笔记。 本篇工作提出了SimCLR&#xff0c;一种用于视觉表征对比学习的简单框架。提出(1)数据增强组合在定义有效预测任务中起到至关重要的作用&#xff1b;(2)在表示和对比…

(leetcode算法题)188. 买卖股票的最佳时机 IV

题目中要求最多可以完成k次交易&#xff0c;很多时候不要把问题搞复杂了&#xff0c; 按照题目要求&#xff0c;研究对象是最后一天结束后最多进行了 k 次交易获得的最大利润 那么就可以把问题拆分成 第 1 天结束后完成 0 次交易获得的最大利润&#xff0c;第 1 天结束后完成…

使用 Docker 搭建 Hadoop 集群

1.1. 启用 WSL 与虚拟机平台 1.1.1. 启用功能 启用 WSL并使用 Moba 连接-CSDN博客 1.2 安装 Docker Desktop 最新版本链接&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 指定版本链接&#xff1a;Docker Desktop release notes | Do…

win32汇编环境,对话框程序模版,含文本框与菜单简单功能

;运行效果 ;win32汇编环境,对话框程序模版&#xff0c;含文本框与菜单简单功能 ;直接抄进RadAsm可编译运行。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>&g…

【赵渝强老师】MongoDB文档级别的并发控制

MongoDB在执行写操作时&#xff0c;WiredTiger存储引擎会在文档级别进行并发控制。换句话说在同一时间点上&#xff0c;多个写操作能够修改同一个集合中的不同文档&#xff1b;而当多个写操作修改同一个文档时&#xff0c;必须以序列化方式执行。这意味着如果当前文档正在被修改…

Java开发 PDF文件生成方案

业务需求背景 业务端需要能够将考试答卷内容按指定格式呈现并导出为pdf格式进行存档&#xff0c;作为紧急需求插入。导出内容存在样式复杂性&#xff0c;包括特定的字体&#xff08;中文&#xff09;、字号、颜色&#xff0c;页面得有页眉、页码&#xff0c;数据需要进行表格聚…

C++文件流 例题

问题&#xff1a; 设计一个留言类&#xff0c;实现以下的功能&#xff1a; 1) 程序第一次运行时&#xff0c;建立一个 message.txt 文本文件&#xff0c;并把用 户输入的信息存入该文件&#xff1b; 2) 以后每次运行时&#xff0c;都先读取该文件的内容并显示给用户&#xf…

Xilinx DCI技术

Xilinx DCI技术 DCI技术概述Xilinx DCI技术实际使用某些Bank特殊DCI要求 DCI级联技术DCI端接方式阻抗控制驱动器&#xff08;源端接&#xff09;半阻抗控制阻抗驱动器&#xff08;源端接&#xff09;分体式DCI&#xff08;戴维宁等效端接到VCCO/2&#xff09;DCI和三态DCI&…

「Mac畅玩鸿蒙与硬件51」UI互动应用篇28 - 模拟记账应用

本篇教程将介绍如何创建一个模拟记账应用&#xff0c;通过账单输入、动态列表展示和实时统计功能&#xff0c;学习接口定义和组件间的数据交互。 关键词 UI互动应用接口定义动态列表实时统计数据交互 一、功能说明 模拟记账应用包含以下功能&#xff1a; 账单输入&#xff1…

阴阳师の新手如何速刷5个SP/SSR?!(急速育成)

目标&#xff1a;攒5个SP/SSR式神&#xff0c;参与急速育成&#xff0c;省四个黑蛋&#xff08;想要快速升级技能而且经常上场的式神在攒够5个式神前先不升级&#xff09;【理论上组成&#xff1a;10蓝40蓝预约召唤福利20修行or抽卡】 关键点&#xff1a;蓝票&#xff0c;新手…

Linux应用软件编程-多任务处理(进程,线程)-通信(管道,信号,内存共享)

多任务处理&#xff1a;让系统具备同时处理多个事件的能力。让系统具备并发性能。方法&#xff1a;进程和线程。这里先讲进程。 进程&#xff08;process&#xff09;&#xff1a;正在执行的程序&#xff0c;执行过程中需要消耗内存和CPU。 进程的创建&#xff1a;操作系统在…

使用 TensorFlow 打造企业智能数据分析平台

文章目录 摘要引言平台架构设计核心架构技术栈选型 数据采集与预处理代码详解 数据分析与预测代码详解 数据可视化ECharts 配置 总结未来展望参考资料 摘要 在大数据时代&#xff0c;企业决策正越来越依赖数据分析。然而&#xff0c;面对海量数据&#xff0c;传统分析工具常因…

初始JavaEE篇 —— Maven相关配置

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 介绍 创建第一个Maven项目 Maven的核心功能 项目构建 依赖管理 添加依赖 依赖排除 依赖调解 Maven仓库 配置本地仓…

Linux套接字通信学习

Linux套接字通信 代码源码&#xff1a;https://github.com/say-Hai/TcpSocketLearn/tree/CThreadSocket 在网络通信的时候, 程序猿需要负责的应用层数据的处理(最上层)&#xff0c;而底层的数据封装与解封装&#xff08;如TCP/IP协议栈的功能&#xff09;通常由操作系统、网络协…

职场常用Excel基础01-数据验证

大家好&#xff0c;excel在职场中使用非常频繁&#xff0c;今天和大家一起分享一下excel中数据验证相关的内容~ 在Excel中&#xff0c;数据验证&#xff08;Data Validation&#xff09;是一项非常有用的功能&#xff0c;它可以帮助用户限制输入到单元格中的数据类型和范围&am…

建造者设计模式学习

1.介绍 建造者模式是一种创建型设计模式&#xff0c;它将一个复杂对象的构建过程与它的表示分离&#xff0c;使得相同的构建过程可以创建不同的表示。通过分步骤地构建对象&#xff0c;建造者模式提供了更细粒度的控制和灵活性&#xff0c;特别适合需要灵活创建复杂对象的场景…

ROS2+OpenCV综合应用--10. AprilTag标签码追踪

1. 简介 apriltag标签码追踪是在apriltag标签码识别的基础上&#xff0c;增加了小车摄像头云台运动的功能&#xff0c;摄像头会保持标签码在视觉中间而运动&#xff0c;根据这一特性&#xff0c;从而实现标签码追踪功能。 2. 启动 2.1 程序启动前的准备 本次apriltag标签码使…

mysql乱码、mysql数据中文问号

网上排出此错误方法的很多&#xff0c;但是 都不简洁&#xff0c;找不到根本原因 主要排查两点&#xff1a; 1.代码中jdbc链接的编码规则 urljdbc:mysql://localhost:3306/title?useUnicodetrue&amp;characterEncodingutf8 将characterEncoding设置为utf8 2.设置mysq…