Swagger与RESTful API

1. Swagger简介

在现代软件开发中,RESTful API已成为应用程序间通信的一个标准。这种架构风格通过使用标准的HTTP方法来执行网络上的操作,简化了不同系统之间的交互。API(应用程序编程接口)允许不同的软件系统以一种预定义的方式互操作,而REST(表述性状态转移)是实现这些接口的一种流行方式。RESTful API的设计原则强调简洁性、可读性和网络友好性,使其成为开发分布式系统和微服务架构的理想选择。

Swagger,现在更常被称为OpenAPI,提供了一个强大的界面,用于设计、构建、文档化以及使用RESTful API。Swagger不仅帮助开发者设计和测试API,还可以自动生成API文档,确保文档与API的实际行为保持同步。这是非常关键的,因为手动维护API文档既费时又易出错。通过Swagger自动化文档的生成和更新,团队能够确保所有开发者和最终用户都有最新的API信息,从而提高开发效率和API的可用性。

API文档是开发者之间交流的桥梁。一个良好的文档不仅提高了API的易用性,还减少了在集成过程中的错误和误解。Swagger通过其可视化界面,允许开发者和非技术利益相关者易于理解API的结构和功能,从而促进更广泛的技术合作和创新。

2. RESTful API基础

理解RESTful API首先需要明白REST架构的核心原则,这些原则包括无状态性、客户端-服务器分离、可缓存、统一接口、分层系统和按需代码。这些原则合起来定义了一个性能高效、规模可扩展、简单和可修改的分布式系统。

无状态性是REST服务的核心特征,意味着每个请求从客户端到服务器必须包含所有必要的信息,让服务器能理解请求并能独立响应。这种做法确保了服务的可靠性和可伸缩性,因为服务器不需要保存客户端的状态信息。这对于构建大规模的分布式系统尤其重要,因为它减少了服务器之间的耦合。

客户端-服务器架构是另一重要特性,它通过分离用户界面与数据存储的关注点,改善了用户界面的可移植性,并提高了多平台的灵活性。同时,这种分离也使得组件可以独立地演化,从而提高了系统的可维护性。

3. 设计RESTful API

设计一个优秀的RESTful API不仅要考虑如何有效地使用HTTP方法和状态码,还要注重资源的定义和请求的结构化。一个良好设计的API应该能够通过其结构清晰地表达其功能,同时也易于开发者理解和使用。

资源的定义和URI设计

在RESTful架构中,资源是一个关键概念。资源代表系统中的一个实体或一组实体,每个资源都应该有一个能够唯一标识它的URI(统一资源标识符)。设计良好的URI应该是可读的和具有自描述性,这样可以通过URI就能了解资源的类型和操作。

举例来说,假设我们正在开发一个电子商务系统,其中有一个资源是用户的订单。一个好的URI设计可能如下:

  • 获取订单列表:GET /orders
  • 获取特定订单:GET /orders/{orderId}
  • 创建新订单:POST /orders
  • 更新订单:PUT /orders/{orderId}
  • 删除订单:DELETE /orders/{orderId}

这些URI清晰地表明了资源是什么以及预期的操作。

使用HTTP状态码

HTTP状态码在RESTful API设计中发挥着重要作用,用于表示服务器对请求的响应状态。合理使用状态码可以让客户端理解他们请求的结果,以及在出错时采取适当的措施。以下是一些常用的HTTP状态码及其用途:

  • 200 OK - 请求成功,并且响应体中包含所请求的数据。
  • 201 Created - 请求成功,并且服务器创建了新的资源。
  • 204 No Content - 请求成功,但没有新的内容返回。
  • 400 Bad Request - 服务器无法理解请求,通常用于参数错误。
  • 404 Not Found - 请求的资源不存在。
  • 500 Internal Server Error - 服务器内部错误,无法完成请求。
Java代码示例:处理订单资源

为了加深理解,以下是一个使用Java和Spring Boot处理订单资源的简单示例。这段代码展示了如何使用Spring MVC注解来定义路由和处理HTTP请求。

import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;

@RestController
@RequestMapping("/orders")
public class OrderController {

    // 获取所有订单
    @GetMapping
    public ResponseEntity<List<Order>> getAllOrders() {
        List<Order> orders = orderService.findAll();
        return ResponseEntity.ok(orders);  // 返回200 OK状态和订单列表
    }

    // 获取特定订单
    @GetMapping("/{orderId}")
    public ResponseEntity<Order> getOrderById(@PathVariable String orderId) {
        Order order = orderService.findById(orderId);
        if (order == null) {
            return ResponseEntity.notFound().build();  // 返回404 Not Found
        }
        return ResponseEntity.ok(order);  // 返回200 OK和订单详情
    }

    // 创建新订单
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody Order order) {
        Order savedOrder = orderService.save(order);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedOrder);  // 返回201 Created和订单详情
    }

    // 更新订单
    @PutMapping("/{orderId}")
    public ResponseEntity<Order> updateOrder(@PathVariable String orderId, @RequestBody Order order) {
        Order updatedOrder = orderService.update(orderId, order);
        if (updatedOrder == null) {
            return ResponseEntity.notFound().build();  // 返回404 Not Found
        }
        return ResponseEntity.ok(updatedOrder);  // 返回200 OK和更新后的订单详情
    }

    // 删除订单
    @DeleteMapping("/{orderId}")
    public ResponseEntity<Void> deleteOrder(@PathVariable String orderId) {
        boolean isDeleted = orderService.deleteById(orderId);
        if (!isDeleted) {
            return ResponseEntity.notFound().build();  // 返回404 Not Found
        }
        return ResponseEntity.noContent().build();  // 返回204 No Content
    }
}

4. Swagger简介

Swagger(现称为OpenAPI)是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统保持同步更新,同时减少开发时间,并提升工作效率和透明度。

Swagger的组成部分

Swagger工具集包括多个与API生命周期密切相关的组件:

  1. Swagger Editor:基于网页的编辑器,用于编写OpenAPI规范的YAML或JSON文件。
  2. Swagger UI:将OpenAPI规范文件渲染成可交互的API文档,允许用户直接通过浏览器测试API。
  3. Swagger Codegen:可以根据OpenAPI规范自动生成服务器端和客户端代码,支持多种编程语言。

这些工具一起工作,为API的设计、测试和文档提供了全方位的支持。

为何选择Swagger

使用Swagger的好处是多方面的:

  • 标准化:Swagger提供了一种标准的API描述,这有助于不同的开发者和团队理解和使用API,无论其技术背景如何。
  • 互操作性:通过自动生成代码的能力,Swagger支持多种编程语言和框架,大大提高了API的互操作性。
  • 动态文档:Swagger文档是与代码紧密相连的,任何对API的更改都会实时反映在文档上。这消除了文档过时的问题,并保持了开发者之间的同步。

5. 在Java中集成Swagger

Swagger不仅强化了API文档的可读性和互动性,还简化了Java应用程序中RESTful服务的开发和维护。在本章中,我们将详细探讨如何在Java环境中,特别是使用Spring Boot框架,集成Swagger以自动生成和维护API文档。

推荐的Java库:Springfox

Springfox是一种流行的库,用于在Spring Boot应用中自动集成Swagger。它能够无缝地与Spring MVC集成,并自动从您的代码中生成和提供Swagger规范的文档。

添加Springfox依赖

在Spring Boot项目中使用Swagger的第一步是添加相关依赖。以下是在pom.xml中添加Springfox依赖的示例:

<dependencies>
    <!-- Springfox Swagger2 dependency -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>3.0.0</version>
    </dependency>
    <!-- Springfox Swagger UI dependency -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>3.0.0</version>
    </dependency>
</dependencies>

这两个依赖分别用于生成Swagger规范的文档和提供一个基于Web的UI,让用户可以直观地查看和测试API。

配置Swagger

在添加了必要的依赖之后,下一步是创建一个配置类来启用Swagger并定义其配置。这里使用Spring Boot的配置类和@Bean注解来设置Swagger:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.application"))
                .paths(PathSelectors.any())
                .build();
    }
}

这个配置类中的Docket Bean是Swagger配置的核心。它指定了Swagger应该针对哪些包进行文档生成(这里指定为com.example.application),以及应该包括哪些路径(这里使用.paths(PathSelectors.any())表示包括所有路径)。

使用Swagger注解增强文档

为了使API文档更加详细和有用,Swagger提供了一系列注解,可以用来描述API的细节,如参数、响应以及模型定义。以下是一些常用的Swagger注解的示例,这些注解可以直接应用于Spring MVC的控制器方法中:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Api(value = "User Management", description = "Operations pertaining to users in User Management System")
@RestController
public class UserController {

    @ApiOperation(value = "View a list of available users", response = Iterable.class)
    @GetMapping("/users")
    public Iterable<User> listUsers() {
        return userService.findAll();
    }

    @ApiOperation(value = "Get a user by ID", response = User.class)
    @GetMapping("/users/{id}")
    public User getUserById(@ApiParam(value = "ID value for the user you need to retrieve", required = true) @RequestParam int id) {
        return userService.findById(id);
    }
}

在上面的示例中,@Api注解用于描述整个类的用途,而@ApiOperation注解描述了每个方法的具体操作。@ApiParam注解则用来描述参数的详细信息,增强了参数的文档描述。

6. 使用Swagger注解

Swagger注解是Swagger工具集的核心功能之一,通过它们可以增加API的文档详情,使API的使用和理解变得更加直观和简单。本章节将深入探讨Swagger注解的使用,展示如何通过它们来丰富API文档的内容。

常用的Swagger注解介绍

Swagger提供了一系列注解用于详细描述API的各个方面,以下是一些最常用的Swagger注解:

  • @Api: 用于类,标记这个类是swagger资源。
  • @ApiOperation: 用于方法,描述一个操作或者请求的性质。
  • @ApiParam: 用于参数,描述操作参数的细节。
  • @ApiResponse: 用于方法,描述可能的响应消息和状态码。
  • @ApiModel: 用于模型,描述数据模型。
  • @ApiModelProperty: 用于模型属性,描述模型属性的细节。

这些注解在增强API文档的可读性和可用性方面发挥着重要作用。

实例演示:使用注解增强API文档

接下来,我们将通过一个实例来展示如何使用这些Swagger注解来增强一个简单的用户管理系统的API文档。

创建用户管理API

首先,我们定义一个基本的用户模型和API控制器。在这个控制器中,我们将应用Swagger注解来增加操作的文档描述。

import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/api/users")
@Api(value = "User Management System", description = "Operations pertaining to user in User Management System")
public class UserController {

    @ApiOperation(value = "View a list of available users", response = Iterable.class)
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        // 模拟用户列表
        List<User> users = Arrays.asList(new User(1, "John Doe"), new User(2, "Jane Doe"));
        return ResponseEntity.ok(users);
    }

    @ApiOperation(value = "Get a user by ID", response = User.class)
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@ApiParam(value = "ID value for the user you need to retrieve", required = true) @PathVariable int id) {
        // 模拟根据ID查找用户
        User user = new User(id, "John Doe");
        return ResponseEntity.ok(user);
    }

    @ApiOperation(value = "Add a new user", response = User.class)
    @PostMapping
    public ResponseEntity<User> createUser(@ApiParam(value = "User object store in database table", required = true) @RequestBody User user) {
        // 模拟创建用户
        return ResponseEntity.ok(user);
    }

    @ApiOperation(value = "Update an existing user", response = User.class)
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@ApiParam(value = "ID value for the user you need to update", required = true) @PathVariable int id,
                                           @ApiParam(value = "Updated user object", required = true) @RequestBody User user) {
        // 模拟更新用户
        user.setId(id);
        return ResponseEntity.ok(user);
    }

    @ApiOperation(value = "Delete a user", response = String.class)
    @DeleteMapping("/{id}")
    public ResponseEntity<String> deleteUser(@ApiParam(value = "ID of the user to be deleted", required = true) @PathVariable int id) {
        // 模拟删除用户
        return ResponseEntity.ok("Deleted user with id " + id);
    }
}

@ApiModel(description = "All details about the User.")
class User {
    @ApiModelProperty(notes = "The database generated user ID")
    private int id;

    @ApiModelProperty(notes = "The user's name")
    private String name;

    // 构造函数、Getter和Setter
    User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

7. API安全性

在设计和部署RESTful API时,确保API的安全是至关重要的。安全漏洞可能会导致数据泄露、服务中断以及其他严重后果。本章将探讨在RESTful API中实施的安全最佳实践,并展示如何在Swagger中配置API安全性。

安全最佳实践

实现API安全性应考虑以下关键方面:

  1. 认证:确保只有合法用户或系统可以访问API。常用的认证机制包括基本认证、Token认证和OAuth。
  2. 授权:一旦认证用户,需要确定他们可以执行的操作。例如,某些用户可能只能访问API的一部分资源。
  3. 传输安全:使用HTTPS来加密客户端和服务器之间的通信,防止数据在传输过程中被窃听或篡改。
  4. 输入验证:对所有输入数据进行校验,防止注入攻击和其他形式的攻击。
  5. 错误处理:不要在API响应中返回敏感信息或系统细节,这可能会给攻击者提供攻击线索。
在Swagger中配置API安全性

Swagger提供了多种机制来描述和配置API的安全策略。这包括定义全局安全策略和操作级别的安全策略。

添加安全定义

首先,需要在Swagger配置中添加安全定义。这里以OAuth2为例,展示如何在Java使用Swagger来配置OAuth2安全性。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.OAuth;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.application"))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Arrays.asList(new OAuth("oauth2schema", authorizationScopes())))
                .securityContexts(Arrays.asList(securityContext()));
    }

    private List<AuthorizationScope> authorizationScopes() {
        AuthorizationScope[] scopes = {
            new AuthorizationScope("read", "for read operations"),
            new AuthorizationScope("write", "for write operations")
        };
        return Arrays.asList(scopes);
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(
                        Arrays.asList(new SecurityReference("oauth2schema", authorizationScopes().toArray(new AuthorizationScope[0])))
                )
                .forPaths(PathSelectors.regex("/api/.*"))
                .build();
    }
}

在这个配置中,我们定义了一个OAuth2安全方案,并指定了适用的授权范围。securityContext()方法确定哪些API路径应用这个安全方案。

使用注解添加操作级别的安全

在控制器层,可以使用Swagger的注解来指定特定操作的安全要求。以下示例展示了如何为特定的API端点指定安全配置:

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Authorization;

@RestController
public class SecureController {

    @ApiOperation(value = "Get secure resource", authorizations = {@Authorization(value = "oauth2schema")})
    @GetMapping("/secure")
    public String getSecureResource() {
        return "This is a secure resource";
    }
}

这种方法允许细粒度控制API安全性,确保只有具备适当授权的用户才能访问敏感数据或操作。

8. 测试RESTful API

有效的API测试是确保RESTful服务按预期工作的关键。本章将探讨如何对RESTful API进行系统的测试,包括单元测试和集成测试,以及如何利用Swagger UI进行手动测试。

单元测试与集成测试

在开发RESTful API时,单元测试和集成测试是保证API可靠性和功能完整性的重要工具。

单元测试

单元测试关注于验证API的各个独立模块是否正确执行其定义的功能。在Java中,常用JUnit和Mockito等框架来实施单元测试。以下是一个使用Spring Boot和JUnit进行单元测试的例子,测试一个简单的获取用户信息的API:

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.mockito.Mockito.when;
import static org.mockito.BDDMockito.given;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.http.MediaType;

@ExtendWith(SpringExtension.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    public void shouldReturnUserDetails() throws Exception {
        given(userService.getUserById(1)).willReturn(new User(1, "John Doe"));

        mockMvc.perform(get("/api/users/1")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().json("{\"id\":1,\"name\":\"John Doe\"}"));
    }
}

这个测试案例通过模拟UserService的行为,检查当调用/api/users/1端点时,是否返回正确的用户详情。

集成测试

集成测试验证不同模块或服务间交互是否按预期工作。在Spring Boot中,可以使用@SpringBootTestTestRestTemplateMockMvc来进行集成测试。以下是一个API集成测试的例子:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.ResponseEntity;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class IntegrationTests {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void userEndpointShouldReturnUserDetails() {
        ResponseEntity<User> response = restTemplate.getForEntity("/api/users/1", User.class);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
        assertThat(response.getBody().getName(), equalTo("John Doe"));
    }
}

这种测试方法实际启动了一个HTTP服务器,验证API端点在真实服务器环境中的行为。

使用Swagger UI进行手动测试

Swagger UI不仅可以用于API文档的展示,还允许开发者和测试人员直接在浏览器中手动执行API调用。这种互动方式使得非开发人员也能轻松验证API的行为。

安装并配置好Swagger后,你可以通过访问http://localhost:8080/swagger-ui.html(根据你的实际配置调整端口和路径)来访问Swagger UI界面。这里你可以看到所有公开的API端点和它们的详细描述,包括可用的操作和预期的响应。

在Swagger UI中,选择一个API端点,填入必要的参数后,就可以发送请求并看到实时的响应结果。这种方式非常适合进行快速测试和验证API的修改是否符合预期。

通过上述方法结合使用单元测试、集成测试和Swagger UI进行手动测试,可以确保RESTful API在开发和部署过程中的质量和稳定性,有效地支持持续集成和持续部署的实践。

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

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

相关文章

一键进阶ComfyUI!懂AI的设计师现在都在用的节点式Stable Diffusion

前言 _ 万字教程&#xff01;奶奶看了都会的 ComfyUI 入门教程 推荐阅读 一、川言川语 大家好&#xff0c;我是言川。 阅读文章 > ](https://www.uisdc.com/comfyui-3) 目前使用 Stable Diffusion 进行创作的工具主要有两个&#xff1a;WebUI 和 ComfyUI。而更晚出现的…

2000—2022年青藏高原遥感生态指数数据集

该数据集是基于多套MODIS数据集&#xff0c;选取NDVI、LST、WET、NDBSI四项指标&#xff0c;采用主成分分析法&#xff0c;生成2000-2022年500米空间分辨率的遥感生态指数&#xff08;RSEI&#xff09;数据集。 遥感生态指数&#xff1a;是一种基于遥感技术的生态环境质量综合评…

容联云容犀Desk在线客服:全渠道+全场景+全智能辅助,提升客户体验

如今&#xff0c;客户体验已经从基础的对话、交易、业务办理&#xff0c;转变为深度的生活联结、情感共鸣、价值认可。客户期待的转变&#xff0c;也让更多企业越发重视“以客户为中心”的业务增长战略。 容犀Desk营销服统一体验工作空间应运而生&#xff0c;其核心能力在线客…

wsl ubuntu 安装Anaconda3步骤

如何在Ubuntu上安装Anaconda3呢?本章记录整个安装过程。 1、下载脚本 https://mirrors.bfsu.edu.cn/anaconda/archive/Anaconda3-2023.09-0-Linux-x86_64.sh 下载之后,将脚本上传到Ubuntu里。 2、安装脚本 bash Anaconda3-2021.11-Linux-x86_64.sh根据提示进行安装,提示输…

React:tabs或标签页自定义右击菜单内容,支持内嵌iframe关闭菜单方案

React&#xff1a;tabs或标签页自定义右击菜单内容&#xff0c;支持内嵌iframe关闭菜单方案 不管是react、vue还是原生js&#xff0c;原理是一样的。 注意如果内嵌iframe情况下&#xff0c;iframe无法使用事件监听&#xff0c;但是可以使用iframe的任何点击行为都会往父级wind…

【等保】网络安全等级保护(等保2.0PPT)

等保2.0&#xff08;网络安全等级保护基本要求的第二代标准&#xff09;的推出和实施&#xff0c;是基于多方面的考虑和需求。以下是实施等保2.0的主要原因&#xff1a; 加强网络安全保护&#xff1a; 随着网络技术的不断发展和网络威胁的不断增加&#xff0c;传统的网络安全保…

BGP中的TCP连接源地址问题

3.TCP连接源地址&#xff08;用loop back地址是最优选择&#xff09; 应用场景与理论&#xff1a; 由于BGP应用于大型网络中&#xff0c;为了避免单点失败&#xff0c;往往需要通过多条链路连接&#xff0c;当一条链路故障时候就用另一条链路继续工作&#xff0c;但是BGP又无法…

Swift 6:导入语句上的访问级别

文章目录 前言示例启用 AccessLevelOnImport破坏性变更采用这些更改总结前言 SE-0409 提案引入了一项新功能,即允许使用 Swift 的任何可用访问级别标记导入声明,以限制导入的符号可以在哪些类型或接口中使用。由于这些变化,现在可以将依赖项标记为对当前源文件(private 或…

IO-Link软件开发流程

目录 了解IO-Link协议&#xff1a; 确定物理连接方式&#xff1a; 编写驱动程序&#xff1a; 测试通信&#xff1a; 集成与应用&#xff1a; 优化与迭代&#xff1a; 文档编写与用户支持&#xff1a; IO-Link产品的开发流程主要包括以下几个步骤 了解IO-Link协议&#x…

【java实习评审】 项目详情模块,如何设计关联表,提高查询性能

大家好&#xff0c;本篇文章分享一下【校招VIP】免费商业项目“推评分16”第一期电影详情模块 java同学的文档周最佳作品。 1、本项目是基于年轻人的喜好&#xff0c;更个性的电影推荐网站。筛选各分类的知名电影&#xff0c;并给出推荐理由和下载链接。另外&#xff0c;通过…

泰迪智能科技实验室产品-云计算资源管理平台介绍

云计算资源管理平台是一款集群应用程序管理平台&#xff0c;以Docker、Kubernetes为核心引擎的容器化应用部署、运行环境&#xff0c;对数据中心的物理服务器、网络、存储、虚拟服务器等基础架构资源进行集中统一的管理、分配、监控等。平台旨在围绕行业应用逐步由“虚拟化”向…

Docker部署前端,动态配置后端地址

本文介绍了使用Docker环境变量动态配置nginx。采用的是通过docker run -e xxxxxxx先往容器注入环境变量&#xff0c;然后进一步通过envsubst指令将环境变量写入到conf文件中&#xff0c;实现动态配置文件内容。 背景 前后端分离的架构下&#xff0c;经常会用到nginx反向代理来…

深度学习 --- stanford cs231学习笔记七(训练神经网络之梯度下降优化器)

5&#xff0c;梯度下降优化器 5&#xff0c;1 梯度下降在深度学习中的作用 在深度学习中&#xff0c;权重W的值是否合理是由损失函数L来判断的。L越小&#xff0c;表示W的设置越happy。L越大&#xff0c;表示W的值越unhappy。 为了让L越来越小&#xff0c;常用的方法是梯度下降…

自主可控的芯片设计供应链软件:保障芯片产业安全的关键

在当前的科技浪潮中&#xff0c;芯片作为信息技术的核心&#xff0c;其设计、制造和供应链的安全性和自主可控性显得尤为重要。而自主可控的芯片设计供应链软件&#xff0c;正是保障这一产业链安全的关键环节。 首先&#xff0c;我们要明确自主可控芯片设计供应链软件的核心价值…

【强化学习】第02期:动态规划方法

笔者近期上了国科大周晓飞老师《强化学习及其应用》课程&#xff0c;计划整理一个强化学习系列笔记。笔记中所引用的内容部分出自周老师的课程PPT。笔记中如有不到之处&#xff0c;敬请批评指正。 文章目录 2.1 动态规划&#xff1a;策略收敛法/策略迭代法2.2 动态规划&#xf…

聚星文社AI工具

聚星文社AI工具是一种基于人工智能技术开发的工具&#xff0c;旨在辅助作者和写作人员提升创作效率和质量。 点击下载 该工具可以提供多项功能&#xff0c;包括语法纠错、智能推荐、文章自动摘要等。 通过使用聚星文社AI工具&#xff0c;用户可以在写作过程中得到即时的纠错建…

数据库使用笔记

1.mysql数据库频繁访问导致连接超时 解决办法一&#xff1a; 优化查询&#xff1a;检查并优化SQL查询语句&#xff0c;减少不必要的数据库调用。增加连接池大小&#xff1a;如果应用程序使用连接池&#xff0c;可以考虑增加连接池的最大连接数。&#xff08;注&#xff1a;不能…

权限维持-域环境单机版---自启动

免责声明:本文仅做技术交流与学习... 目录 1.windows自启动路径加载 2.自启动服务加载 3.自启动注册表加载 所在regedit目录: -添加启动项 --重启生效 4.计划计时任务 windows软件或程序服务开机自启动的四种方式-CSDN博客 1.windows自启动路径加载 --当windows注销…

LabVIEW在机器人研究所中的应用

机器人研究所致力于机器人技术的研究与开发&#xff0c;涵盖工业机器人、服务机器人、医疗机器人等多个领域。研究所需要一个高效、灵活的实验控制和数据采集系统&#xff0c;以进行复杂的机器人实验&#xff0c;并对实验数据进行实时处理和分析。 项目需求 实时控制与监控&am…

ai轨迹过京东m端

声明(a15018601872) 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本…