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 {// 获取所有订单@GetMappingpublic 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和订单详情}// 创建新订单@PostMappingpublic 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生命周期密切相关的组件:
- Swagger Editor:基于网页的编辑器,用于编写OpenAPI规范的YAML或JSON文件。
- Swagger UI:将OpenAPI规范文件渲染成可交互的API文档,允许用户直接通过浏览器测试API。
- 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 {@Beanpublic 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)@GetMappingpublic 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)@PostMappingpublic 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和SetterUser(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安全性应考虑以下关键方面:
- 认证:确保只有合法用户或系统可以访问API。常用的认证机制包括基本认证、Token认证和OAuth。
- 授权:一旦认证用户,需要确定他们可以执行的操作。例如,某些用户可能只能访问API的一部分资源。
- 传输安全:使用HTTPS来加密客户端和服务器之间的通信,防止数据在传输过程中被窃听或篡改。
- 输入验证:对所有输入数据进行校验,防止注入攻击和其他形式的攻击。
- 错误处理:不要在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 {@Beanpublic 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 {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService;@Testpublic 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中,可以使用@SpringBootTest
和TestRestTemplate
或MockMvc
来进行集成测试。以下是一个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 {@Autowiredprivate TestRestTemplate restTemplate;@Testpublic 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在开发和部署过程中的质量和稳定性,有效地支持持续集成和持续部署的实践。
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/04cca3ad62040bf203fdd0b752151d4d.png)
Swagger与RESTful API
1. Swagger简介 在现代软件开发中,RESTful API已成为应用程序间通信的一个标准。这种架构风格通过使用标准的HTTP方法来执行网络上的操作,简化了不同系统之间的交互。API(应用程序编程接口)允许不同的软件系统以一种预定义的方式…...
![](https://img-blog.csdnimg.cn/direct/4b97006f2f034a8c97b23d064699d752.png)
MySQL84 -- ERROR 1524 (HY000): Plugin ‘msql_native_password‘ is not loaded.
【问题描述】 MySQL 8.4版本,配置用户使用mysql_native_password认证插件验证用户身份,报错: 【解决方法】(Windows, MySQL 8.4) 1、修改MySQL配置文件my.ini,在[mysqld]段添加mysql_native_passwordON。 2、管理员…...
![](https://img-blog.csdnimg.cn/20210916225739194.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzU3MTU4NDk2,size_16,color_FFFFFF,t_70)
将Excel中的错误值#N/A替换成心仪的字符串,瞬间爱了……
常用表格的人都晓得,看到满屏悦动的#N/A,心情都会不好。把它替换成自己心仪的字符,瞬间就爱了。 (笔记模板由python脚本于2024年06月13日 19:32:37创建,本篇笔记适合常用Excel,喜欢数据的coder翻阅) 【学习的细节是欢悦…...
![](https://img-blog.csdnimg.cn/img_convert/49297956b0df21798d5a7bd95e802814.webp?x-oss-process=image/format,png)
AI大模型日报#0628:谷歌开源9B 27B版Gemma2、AI首次实时生成视频、讯飞星火4.0发布
导读:AI大模型日报,爬虫LLM自动生成,一文览尽每日AI大模型要点资讯!目前采用“文心一言”(ERNIE-4.0-8K-latest)生成了今日要点以及每条资讯的摘要。欢迎阅读!《AI大模型日报》今日要点…...
![](https://www.ngui.cc/images/no-images.jpg)
【随笔】提高代码学习水平(以更高的视角看事物)
最近,我感觉到自己的代码水平似乎卡在了一个瓶颈。似乎只想着数仓,Hive,Spark技术优化,但只要稍微离开这几个点,我就感到无所适从。我开始反思,或许,我应该总结一下自己的学习方法。 1.站的高&…...
游戏AI的创造思路-技术基础-深度学习(5)
继续深度学习技术的探讨,填坑不断,头秃不断~~~~~ 目录 3.5. 自编码器(AE) 3.5.1. 定义 3.5.2. 形成过程 3.5.3. 运行原理 3.5.3.1.运行原理及基本框架 3.5.3.2. 示例代码 3.5.4. 优缺点 3.5.5. 存在的问题和解决方法 3.5…...
![](https://img-blog.csdnimg.cn/direct/cd105cd5861b45d485e964e314b4d6bc.png)
基于SpringBoot养老院管理系统设计和实现(源码+LW+调试文档+讲解等)
💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟感兴趣的可以先收藏起来,还…...
![](https://img-blog.csdnimg.cn/direct/5ffdfb14380049789cb0050a37dd344b.png)
餐饮点餐的简单MySQL集合
ER图 模型图(没有进行排序,混乱) DDL和DML /* Navicat MySQL Data TransferSource Server : Mylink Source Server Version : 50726 Source Host : localhost:3306 Source Database : schooldbTarget Server Type …...
![](https://img-blog.csdnimg.cn/direct/316d434f38774f159a3e9b81616f71c4.png)
STM32驱动-ads1112
汇总一系列AD/DA的驱动程序 ads1112.c #include "ads1112.h" #include "common.h"void AD5726_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE );//PORTA、D时钟使能 G…...
![](https://www.ngui.cc/images/no-images.jpg)
数据结构与算法高频面试题
初级面试题及详细解答 当涉及到数据结构与算法的初级面试题时,通常涉及基本的数据结构操作、算法复杂度分析和基本算法的应用。 1. 什么是数组?数组和链表有什么区别? 解答: 数组:是一种线性数据结构,用…...
![](https://img-blog.csdnimg.cn/direct/ba9a90026153476ca777b9ab48653ec8.png)
uni-app的showModal提示框,进行删除的二次确认,可自定义确定或取消操作
实现效果: 此处为删除的二次确认示例,点击删除按钮时出现该提示,该提示写在js script中。 实现方式: 通过uni.showModal进行提示,success为确认状态下的操作自定义,此处调用后端接口进行了删除操作&#…...
![](https://img-blog.csdnimg.cn/img_convert/b8029be48d3db26cb185f7db49a81608.png)
5款提高工作效率的免费工具推荐
SimpleTex SimpleTex是一款用于创建和编辑LaTeX公式的简单工具。它能够识别图片中的复杂公式并将其转换为可编辑的数据格式。该软件提供了一个直观的界面,用户可以在编辑LaTeX代码的同时实时预览公式的效果,无需额外的编译步骤。此外,SimpleT…...
![](https://www.ngui.cc/images/no-images.jpg)
区块链的技术架构:节点、网络和数据结构
区块链技术听起来很高大上,但其实它的核心架构并不难理解。今天我们就用一些简单的例子和有趣的比喻,来聊聊区块链的技术架构:节点、网络和数据结构。 节点:区块链的“细胞” 想象一下,区块链就像是一个大型的组织&a…...
![](https://www.ngui.cc/images/no-images.jpg)
pdfmake不能设置表格边框颜色?
找到pdfmake>build>pdfmake.js中: 找到定义的“TableProcessor.prototype.drawVerticalLine”和“TableProcessor.prototype.drawHorizontalLine”两个方法: 重新定义borderColor: var borderColor this.tableNode.table.borderColor||"#…...
![](https://www.ngui.cc/images/no-images.jpg)
laravel 使用RabbitMQ作为消息中间件
先搞定环境,安装amqp扩展 确保已安装rabbitmq-c-dev。 比如 可以使用apk add rabbmit-c-dev安装 cd ~ wget http://pecl.php.net/get/amqp-1.10.2.tgz tar -zxf amqp-1.10.2.tgz cd amqp-1.10.2 phpize ./configure make && make install cd ~ rm -rf am…...
![](https://img-blog.csdnimg.cn/direct/aab17b9679b24f74a2d29f7572f69522.png)
web项目打包成可以离线跑的exe软件
目录 引言打开PyCharm安装依赖创建 Web 应用运行应用程序打包成可执行文件结语注意事项 引言 在开发桌面应用程序时,我们经常需要将网页集成到应用程序中。Python 提供了多种方法来实现这一目标,其中 pywebview 是一个轻量级的库,它允许我们…...
![](https://img-blog.csdnimg.cn/direct/971edb767400417f962d026f60d1d582.jpeg)
BFS:队列+树的宽搜
一、二叉树的层序遍历 . - 力扣(LeetCode) 该题的层序遍历和以往不同的是需要一层一层去遍历,每一次while循环都要知道在队列中节点的个数,然后用一个for循环将该层节点走完了再走下一层 class Solution { public:vector<vec…...
![](https://img-blog.csdnimg.cn/direct/c7eb519efcb645909f7e54cf7be02f69.png)
MySQL高级-SQL优化- count 优化 - 尽量使用count(*)
文章目录 1、count 优化2、count的几种用法3、count(*)4、count(id)5、count(profession)6、count(null)7、 count(1) 1、count 优化 MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高&a…...
![](https://www.ngui.cc/images/no-images.jpg)
python Flask methods
在 Flask 中,app.route() 装饰器用于定义 URL 路由和与之关联的视图函数。当你想指定某个 URL 可以接受哪些 HTTP 方法时,你可以使用 methods 参数。methods 是一个列表,它可以包含任何有效的 HTTP 方法。 Falsk文章中的描述: 链…...
![](https://img-blog.csdnimg.cn/direct/9e9c7b830e4b4566bfbb957eb1746b9c.png)
three.js场景三元素
three.js是一个基于WebGL的轻量级、易于使用的3D库。它极大地简化了WebGL的复杂细节,降低了学习成本,同时提高了性能。 three.js的三大核心元素: 场景(Scene) 场景是一个三维空间,是所有物品的容器。可以将…...
![](https://www.ngui.cc/images/no-images.jpg)
Spring AOP(面向切面编程)详解
Spring AOP(面向切面编程)详解 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 什么是Spring AOP? Spring AOP(…...
![](https://img-blog.csdnimg.cn/direct/c2022fcf402a48369de36203b2395d88.png)
Kafka第一篇——内部组件概念架构启动服务器zookeeper选举以及底层原理
目录 引入 ——为什么分布式系统需要用第三方软件? JMS 对比 组件 架构推演——备份实现安全可靠 , Zookeeper controller的选举 controller和broker底层通信原理 BROKER内部组件 编辑 topic创建 引入 ——为什么分布式系统需要用第三方软件&#…...
![](https://www.ngui.cc/images/no-images.jpg)
14、顺时针打印矩阵
题目: 顺时针打印矩阵 描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字, 例如, 如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字:1,2,3,4,8,1…...
![](https://img-blog.csdnimg.cn/direct/6b52804e15ed49f6aa22fcb8e7ed99ca.png)
毅速丨金属3D打印是制造业转型升级的重要技术
随着科技的进步,金属3D打印技术已成为制造业升级的重要驱动力。它以其独特的优势,正引领着制造业迈向新的未来。 金属3D打印技术的突破: 设计自由。金属3D打印能制造任意形状和结构的零件,为设计师提供了无限的创意空间。 快速制…...
![](https://img-blog.csdnimg.cn/direct/bf0ff7691f9b44f498210d9055b1b3ae.png)
uni-app uni-data-picker级联选择器无法使用和清除选中的值
出现问题: 使用点击右边的叉号按钮无法清除已经选择的uni-data-picker值 解决办法: 在uni-app uni-data-picker使用中,要添加v-model,v-model在官网的示例中没有体现,但若不加则无法清除。 <uni-data-picker v-m…...
![](https://img-blog.csdnimg.cn/direct/e016214b1eb24f43b83f758f146e2227.png)
构造函数的小白理解
一、实例 using System; using System.Collections; using System.Collections.Generic; using UnityEngine;//定义一个名为Question的类,用于存储问题及相关信息 [Serializable] public class Question {public string questionText;//存储题目文本字段public str…...
![](https://img-blog.csdnimg.cn/img_convert/61e20917888fdb77a12d9deceb4d9096.png)
招聘,短信与您:招聘人员完整指南
招聘人员面临的最大挑战之一就是沟通和联系候选人。为何?我们可以从以下原因开始:候选人通常被太多的招聘人员包围,试图联系他们,这使得你很难吸引他们的注意。在招聘过程的不同阶段,根据不同的工作量,让申请人保持最…...
![](https://img-blog.csdnimg.cn/direct/0151a695e28f4b85b50669d5acdd98df.png)
JAVA-矩阵置零
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 思路: 找到0的位置,把0出现的数组的其他值夜置为0 需要额外空间方法: 1、定义两个布尔数组标记二维数组中行和列…...
![](https://img-blog.csdnimg.cn/direct/8b2c16cd5f084d8a9a6eba3c68107ed8.png)
[信号与系统]模拟域中的一阶低通滤波器和二阶滤波器
前言 不是学电子出身的,这里很多东西是问了朋友… 模拟域中的一阶低通滤波器传递函数 模拟域中的一阶低通滤波器的传递函数可以表示为: H ( s ) 1 s ω c H(s) \frac{1}{s \omega_c} H(s)sωc1 这是因为一阶低通滤波器的设计目标是允许低频信…...
![](https://img-blog.csdnimg.cn/direct/ccc5df67988049e1be13887ac83f27e0.png)
Mac环境 aab包转apks,并安装apks
一、下载下载bundletool工具 Releases google/bundletool GitHub 二、将下载bundletool.jar包、aab、keystore文件全部放到同一个目录下 例如我全部放到download目录下 转换命令行: java -jar bundletool-all-1.16.0.jar build-apks --modeuniversal --bundle…...
![](https://img-blog.csdnimg.cn/direct/163525bcfc764b4c923644dda05e5c7d.png)
银河麒麟V10 SP1.1操作系统 离线安装 nginx1.21.5、redis 服务
银河麒麟官网地址:国产操作系统、麒麟操作系统——麒麟软件官方网站 一、查看系统版本 命令:nkvers 我的是 release V10 (SP1),根据这个版本去官网找对应的rpm包 银河麒麟操作系统的rpm包必须从官方找, 要是随便找个Centos的rp…...
![](https://www.ngui.cc/images/no-images.jpg)
ios swift5 视频播放 播放视频失败 无法播放HEVC (H.265) 格式的视频 H.264格式的可以播放
文章目录 1.问题2.原因:iOS swift AVPlayerViewController无法播放HEVC (H.265) 格式的视频3.解决方法用第三方框架MobileVLCKit来播放4.用MobileVLCKit写的播放器4.1 两个oc版本的4.2 两个swiftUI版本的5.苹果是支持HEVC (H.265) 格式的视频,是硬件那边…...
![](https://img-blog.csdnimg.cn/img_convert/1e473ef201dd27dfb15b89d81db7ab3d.jpeg)
网工内推 | 网络工程师,IE认证优先,最高18k*14薪,周末双休
01 上海吾索信息科技有限公司 🔷招聘岗位:网络工程师 🔷岗位职责: 1)具备网络系统运维服务经验以及数据库实施经验,具备网络系统认证相关资质或证书; 2)掌握常用各设备的运维巡检…...
![](https://img-blog.csdnimg.cn/direct/4fc3d934863e480985de70ca2f0649bb.png)
【Qt】QMessageBox 各种对话框的默认显示效果
1. 函数原型 void about(QWidget *parent, const QString &title, const QString &text)void aboutQt(QWidget *parent, const QString &title QString())QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &…...
![](https://img-blog.csdnimg.cn/direct/36c0aeaeaa1446e48c3adfa607be70be.png#pic_center)
一文弄懂线性回归模型
1、引言 今天,我们将深入探讨机器学习中的三个关键概念:线性回归、代价函数和梯度下降。这些概念构成了许多机器学习算法的基础。起初,我决定不写一篇关于这些主题的文章,因为它们已经被广泛涉及。不过,我改变了主意&…...
![](https://img-blog.csdnimg.cn/direct/de466be8dde94ce8b4b09fef2bb92d30.png)
uniApp获取实时定位
通过你获取的key放到项目manifest.json里面,对应填写你所需要的key值,还有高德用户名 用户名: key值的位置: 代码: html: <view class"intList pdNone"><view class"label">详细地…...
![](https://www.ngui.cc/images/no-images.jpg)
linux的source命令
用法 source file 也可以用.空格file来代替 . file 作用 在当前bash环境下读取并执行FileName中的命令. source(或点)令通常用于重新执行刚修改的初始化文档,如 .bash_profile 和 .profile等配置文件. 简单的说就是: source命令会把file里的命令在当前shell里一…...
![](https://www.ngui.cc/images/no-images.jpg)
特种作业操作证(焊接与热切割作业)2024年理论考试题库。
1.关于隐弧排烟罩下列说法正确的是()。 A.这类排烟罩适用于焊接大而长的焊件时排除电焊烟尘和有毒气体 B.这类排烟罩对焊接区实行密闭,能最大限度地减少臭氧等有毒气体的弥散 C.利用压缩空气从主管中高速喷出时,在副管形成负压…...
![](https://img-blog.csdnimg.cn/direct/e28aa01cc2824f8e8817a62f29a76d13.png)
免交互和嵌入执行模式
目录 概念 语法格式 统计行数 赋值变量 修改密码编辑往文件里添加内容 编辑编辑引入变量 整体赋值编辑 加引号不赋值变量 expect实现免交互 免交互设置密码 免交互切换用户 嵌入执行模式 添加用户并免交互设置密码 免交互登录 传参实现ssh 练习 概念 …...
![](https://i-blog.csdnimg.cn/direct/d4b4218775d44dd9abbb0f284106f0d7.png)
Hadoop版本演变、分布式集群搭建
Hadoop版本演变历史 Hadoop发行版非常的多,有华为发行版、Intel发行版、Cloudera Hadoop(CDH)、Hortonworks Hadoop(HDP),这些发行版都是基于Apache Hadoop衍生出来的。 目前Hadoop经历了三个大的版本。 hadoop1.x:HDFSMapReduce hadoop2.x…...
![](https://www.ngui.cc/images/no-images.jpg)
【Qt C++实现绘制仪表盘】
要在Qt C中绘制仪表盘,您可以使用QChart、QSeries、QBarSeries、QPointSeries等类。以下是一个简单的示例,演示如何使用这些类创建一个绘图仪表盘: #include <QApplication> #include <QChart> #include <QChartView> #in…...
![](https://www.ngui.cc/images/no-images.jpg)
一文看懂LLaMA 2:大型多模态模型的新里程碑
一文看懂LLaMA 2:大型多模态模型的新里程碑 LLaMA 2是OpenAI继GPT-3之后推出的又一重磅模型,它不仅在文本生成方面有所突破,而且在图像处理和语音识别等领域也展现出了令人印象深刻的能力。本文将全面介绍LLaMA 2的背景、技术细节、应用场景…...
![](https://www.ngui.cc/images/no-images.jpg)
基于Spring Boot构建淘客返利平台
基于Spring Boot构建淘客返利平台 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将讨论如何基于Spring Boot构建一个淘客返利平台。 淘客返利平台通过…...
![](https://img-blog.csdnimg.cn/direct/94f31d0ecbdf404491a41357843ea49a.png)
Qt—贪吃蛇项目(由0到1实现贪吃蛇项目)
用Qt实现一个贪吃蛇项目 一、项目介绍二、游戏大厅界面实现2.1完成游戏大厅的背景图。2.2创建一个按钮,给它设置样式,并且可以跳转到别的页面 三、难度选择界面实现四、 游戏界面实现五、在文件中写入历史战绩5.1 从文件里提取分数5.2 把贪吃蛇的长度存入…...
![](https://www.ngui.cc/images/no-images.jpg)
Java导出Excel并邮件发送
一、导出Excel 添加maven依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.10-FINAL</version></dependency><dependency><groupId>org.apache.poi</groupI…...
![](https://img-blog.csdnimg.cn/img_convert/1749a8c86d6e38798d8e1ed9f073b8a9.png)
【课程总结】Day12:YOLO的深入了解
前言 在【课程总结】Day11(下):YOLO的入门使用一节中,我们已经了解YOLO的使用方法,使用过程非常简单,训练时只需要三行代码:引入YOLO,构建模型,训练模型;预测…...
![](https://www.ngui.cc/images/no-images.jpg)
保护隐私,释放智能:使用LangChain和Presidio构建安全的AI问答系统
保护隐私,释放智能:使用LangChain和Presidio构建安全的AI问答系统 在人工智能(AI)飞速发展的今天,AI问答系统已经成为企业与客户互动的重要工具。然而,随之而来的个人数据隐私问题也日益凸显。如何在不泄露…...
![](https://www.ngui.cc/images/no-images.jpg)
【高考志愿】自动化
目录 一、专业概述 二、课程设计 三、就业前景与方向 四、志愿填报 五、自动化专业排名 一、专业概述 高考志愿自动化专业选择,无疑是迈向现代化工业与科技发展的一把金钥匙。自动化专业,作为现代工程领域的重要支柱,融合了计算机、电子…...
![](https://img-blog.csdnimg.cn/img_convert/3f0a800dae76e07ea45f3b2bae00e4c9.png)
技巧类题目
目录 技巧类题目 136 只出现一次的数字 191 位1的个数 231. 2 的幂 169 多数元素 75 颜色分类 (双指针) 287. 寻找重复数 136 只出现一次的数字 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均…...
![](https://www.ngui.cc/images/no-images.jpg)
Vue3自定义指令参数修饰符值(3)
自定义指令参数修饰符值 在vue3中我们如何获取自定义的参数的内容,并根据业务来修改展示的内容呢,需要依靠mounted方法中的bindings参数来获取。 参考实例 directives/unit.js文件 export default function directiveUnit(app){app.directive("unit",{…...
![](https://img-blog.csdnimg.cn/direct/257c84f8ee2f4b18b6634b4c105385db.png)
魔行观察-AI数据分析>>勒泰中心购物中心
摘要 本报告基于 魔行观察 搜集整理的数据,对勒泰中心购物中心的营业状态、商户构成、业态分布以及消费者评价进行了详细分析。 商场概览 勒泰中心是一个正常营业的购物中心,自2013年开业以来,已成为当地居民和游客的重要购物和休闲场所。…...
![](https://img-blog.csdnimg.cn/img_convert/34fdecb3bb797a56ef4ad80b1f46146f.png)
gdb-dashboard:用Python重塑GDB调试体验
gdb-dashboard;一目了然的GDB调试,尽在掌控之中- 精选真开源,释放新价值。 概览 gdb-dashboard是一个用Python编写的模块化视觉界面,为GNU Debugger(GDB)提供了一个现代化的工作空间。它通过集成多个面板和…...
![](https://www.ngui.cc/images/no-images.jpg)
python爬虫之实现edge无头浏览器和规避检测
python爬虫之实现edge无头浏览器和规避检测 爬取百度网页源码但不打开浏览器 实现代码如下: #需求:实现edge无头浏览器和规避检测 from selenium import webdriver from time import sleep from selenium.webdriver.edge.options import Options# 实现…...
![](https://img-blog.csdnimg.cn/direct/ae093a7c949e40d3bbd01a2931bd801a.webp#pic_center)
po文件并转换成mo文件
po文件转换成mo文件 简介 .po和.mo文件是WordPress中语言相关的两种文件。po 是Portable Object(可移植对象)的缩写,存放待翻译的字符串信息,可直接用文本编辑器打开编辑;mo 是Machine Object的缩写,二进制文件,程序…...
![](https://www.ngui.cc/images/no-images.jpg)
git出现Permission denied问题
Warning: Permanently added ‘icode.baidu.com,10.11.81.103’ (RSA) to the list of known hosts. Permission denied (baas,keyboard-interactive,publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the…...
![](https://www.ngui.cc/images/no-images.jpg)
前端:Vue中使用JS-Cookie
在我们构建Vue站点时候,可能需要使用 cookie 来记录用户信息或者偏好设置,我们可以引入第三方库 GitHub - js-cookie/js-cookie: A simple, lightweight JavaScript API for handling browser cookies 来方便地操作 cookie。接下来我们就来一步一步地实…...
![](https://img-blog.csdnimg.cn/direct/5bbabccdd6734121abf2e649491a3d9d.png)
电脑录屏怎么录?7个电脑录屏软件免费版强势来袭,赶快收藏!
电脑录屏怎么录?相信很多小伙伴们都不知道怎么在Windows电脑上录屏吧?在当今社会,随着互联网的快速发展,越来越多的小伙伴们开始通过制作视频内容来分享知识、展示技能或者记录生活。电脑录屏成为了一种简单高效的方式,…...
![](https://img-blog.csdnimg.cn/direct/d22eab445ba14ba3b620d4885f847f38.png)
0基础认识C语言(理论+实操 2)
小伙伴们大家好,今天也要撸起袖子加油干!万事开头难,越学到后面越轻松~ 话不多说,开始正题~ 前提回顾: 接上次博客,我们学到了转义字符,最后留下两个转义字符不知道大家有没有动手尝试了一遍&a…...
![](https://img-blog.csdnimg.cn/direct/67b4928b99dc4f798d9118caea135570.png)
数据清洗(ETL)案例实操
文章目录 数据清洗(ETL)概述案例需求和分析代码实现和结果分析 数据清洗(ETL)概述 “ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(Extract)、转换&…...
![](https://img-blog.csdnimg.cn/direct/054129603ef24345b52c0cc7509e1065.png)
vue 表格表头展示不下,显示。。。;鼠标悬浮展示全部
vue 表格表头展示不下,显示。。。;鼠标悬浮展示全部 <templateslot-scope"scope"slot"header"><span:title"临时证券类型"style"white-space:nowrap">{{ 临时证券类型 }}</span></templa…...
![](https://img-blog.csdnimg.cn/direct/5d445eb0820d43948dcc3d5f40deafce.png)
时间|基于SprinBoot+vue的时间管理系统(源码+数据库+文档)
时间管理系统 目录 基于SprinBootvue的时间管理系统 一、前言 二、系统设计 三、系统功能设计 1管理员功能模块 2用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农…...
![](https://www.ngui.cc/images/no-images.jpg)
嘉道理慈善基金会董事到访中国残联
5月22日下午,中国残联副理事长尤亮在京会见嘉道理慈善基金会董事彼得保罗一行。尤亮对彼得保罗一行到访中国残联表示欢迎。他介绍了近年来中国残疾人事业发展的新成就,并回顾了中国残联与嘉道理基金会自1997年以来的合作历程。他表示,在长期合作过程中,双方在残疾人教育、就…...