当前位置: 首页 > news >正文

Java 开发——(下篇)从零开始搭建后端基础项目 Spring Boot 3 + MybatisPlus

上篇速递 - Spring Boot 3 + MybatisPlus


五、静态资源访问

1. 基础配置

在 Spring Boot 中访问静态资源非常方便。Spring Boot 默认支持从以下位置加载静态资源

  • /META-INF/resources/
  • /resources/
  • /static/
  • /public/

这些目录下的文件可以直接通过 URL 访问。

例如,如果有一个图片文件放在 src/main/resources/static/logo.png,那么可以通过 http://localhost:8080/logo.png 来访问这个图片。(假设服务器运行在 8080 端口)


定义过滤规则

在默认的情况下,访问静态资源的 URLhttp://localhost:8080/图片名.文件后缀

如果想要自定义其他的过滤规则,可以在 application.properties 配置文件中进行配置。

例如,在 application.properties 中添加如下配置:

# 定义过滤规则 /images/**
spring.mvc.static-path-pattern=/images/**

这会告诉 Spring Boot 访问静态资源的 URLhttp://localhost:8080/images/图片名.文件后缀


配置静态资源路径

如果想自定义静态资源的位置,或添加额外的静态资源目录,可以在 application.properties 配置文件中进行配置。

例如,在 application.properties 中添加如下配置:

# 定义多个位置,使用逗号分隔
spring.resources.static-locations=classpath:/my-resources/,classpath:/static/

这会告诉 Spring Boot 从 /my-resources//static/ 这两个目录下加载静态资源。


2. 项目搭建

我们可以在项目中进行如下配置:

# 静态资源配置
# 定义过滤规则 /images/**
spring.mvc.static-path-pattern=/images/**# 定义静态资源位置,对静态资源进行放行允许浏览器访问 classpath:/static/
#spring.web.resources.static-locations=classpath:/static/# 定义静态资源位置,会覆盖原先默认的静态资源位置
# 定义多个位置,使用逗号分隔
# 用户上传文件位置 upload,相对于配置文件的位置,"/"代表服务器所在路径
spring.web.resources.static-locations=/upload/,classpath:/static/

3. 注意事项

当我们想要测试这个静态资源的访问时,可能会遇到以下这个问题:

我们使用 IDEA 开发,就会直接把电脑上的测试图片直接复制到项目的 /resources/static 目录下,然后用 http://localhost:8080/images/test.jpg 进行测试,发现测试图片加载失败了

这并非项目配置的问题。

而是由于导入的图片是放到项目的 static 目录下,而编译后的 target 中没有该资源,所以访问不到。

简单来说就是项目需要重新编译 Rebuild Project,重新编译后静态资源会被加载到 target 目录下,此时就可以通过浏览器访问到图片了。


六、文件上传

前端通过 API 接口上传文件是一个常见的需求,通常涉及以下几个步骤:前端准备文件数据、发送 HTTP 请求到后端、后端接收并处理文件。

在后端 Spring Boot 项目中,我们可以对接收的文件进行如下处理。

1. 配置文件上传

application.properties 中配置文件上传的最大大小:

# tomcat 限制请求上传文件的大小
# 每个文件配置最大大小,单个上传文件最大为 10MB
spring.servlet.multipart.max-file-size=10MB# 单次请求的文件总大小
#spring.servlet.multipart.max-request-size=10MB

2. 创建控制器

创建一个控制器 FileUploadController 来处理文件上传请求:

@RestController
public class FileUploadController {@PostMapping("/upload")public String upload(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException {System.out.println(nickname);//获取图片原始名称System.out.println(photo.getOriginalFilename());// 获取文件类型System.out.println(photo.getContentType());// 设置上传图片的保存位置// 这表示上传文件的位置是动态的,是 tomcat 服务器所在位置// 获取服务器上某个虚拟路径的实际物理路径String path = request.getServletContext().getRealPath("/upload/");// 打印出图片上传位置System.out.println(path);// 保存图片saveFile(photo, path);return "上传成功";}private void saveFile(MultipartFile photo, String path) throws IOException {// 判断存储目录是否存在,如果不存在则创建该目录File dir = new File(path);if (!dir.exists()) {// 创建目录dir.mkdir();}// 储存后文件File file = new File(path + photo.getOriginalFilename());// 把网络上的文件存储到服务器本地photo.transferTo(file);}}

3. 设置静态资源放行

通过 request.getServletContext().getRealPath() 可以获取服务器上某个虚拟路径的实际物理路径,及 tomcat 服务器所在位置。

由上面的文件上传控制器所知,前端上传的图片被存放到了 tomcat 服务器所在位置的 upload 文件夹下。

如果我们想在前端(浏览器)访问到这些图片,可以把这个文件夹设置成静态资源目录

在配置文件 application.properties 中如何获取到这个目录?

在配置文件中 “/” 代表服务器所在路径,故这个目录用 “/upload/” 表示。

# 定义静态资源位置,会覆盖原先默认的静态资源位置
# 定义多个位置,使用逗号分隔
# 用户上传文件位置 upload,相对于配置文件的位置,"/"代表服务器所在路径
spring.web.resources.static-locations=/upload/,classpath:/static/

需要注意的点:在开发阶段,Spring Boot 项目的内置 tomcat 服务器所在位置不是固定的每次重启项目位置都会发生变化


4. 测试方法

使用 Postman 测试下这个接口,文件上传的格式一般选择 form-data 格式。

在这里插入图片描述


在浏览器中访问:

http://localhost:8080/images/bus.jpg

七、拦截器

在 Spring Boot 中,拦截器(Interceptor)是一种常用的机制,用于在请求到达控制器之前或之后执行某些操作。拦截器可以用于日志记录、权限校验、性能监控等多种场景。

下面是如何在 Spring Boot 中定义和使用拦截器的详细步骤。

1. 定义拦截器

创建拦截器类:实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类。

如,在项目中我们创建了一个拦截器类 LoginInterceptor,让它继承 HandlerInterceptor 接口。

返回值 return 表示是否拦截:

  • true:不拦截;
  • false:拦截。
// 添加拦截器
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 拦截器打印的信息,在控制台看到它就说明拦截器生效了System.out.println("拦截器打印的信息");return true;// 如果 false 代表拦截,具体的拦截规则在拦截器注册文件中}
}// config 中注册拦截器,使拦截器生效

2. 注册拦截器

我们需要在配置类中注册拦截器,拦截器才会生效。

注册拦截器:创建一个配置类,实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法。

如,在项目中我们创建了配置类 WebConfig,让它继承 WebMvcConfigurer 接口,重写 addInterceptors 方法,同时添加注解 @Configuration 使配置类生效。

addInterceptors 方法中,可以设置拦截的具体位置。

// 添加注解 @Configuration 使配置类生效
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// config 中注册拦截器,使拦截器生效// 表示拦截所有的请求
//        registry.addInterceptor(new LoginInterceptor());// 有针对性的拦截// /hello 表示路由映射的路径 http://localhost:8080/hello?nickname=zhangsan&phone=123// 拦截所有/hello/开头的请求registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/hello/**");}
}

测试一个 /hello/ 开头的请求,观察后端控制台中拦截器打印的信息。


八、RESTful 风格

RESTful(Representational State Transfer)风格是一种设计网络应用程序架构的方式,它利用 HTTP 协议的特性来实现客户端和服务器之间的通信。

RESTful API 设计的核心原则是使用标准的 HTTP 方法(如 GET、POST、PUT、DELETE 等)来操作资源,每个资源都有唯一的标识符(通常是 URL)。

下面是一些关于如何设计 RESTful API 的基本指南。

1. RESTful API 设计原则

资源命名

  • 使用名词而不是动词来表示资源。
  • 使用复数形式来表示集合资源。
  • 使用连字符或驼峰命名法来提高可读性。

HTTP 方法(关键点)

  • GET:用于获取资源。
  • POST:用于创建资源。
  • PUT:用于更新资源(替换整个资源)。
  • PATCH:用于部分更新资源。
  • DELETE:用于删除资源。

状态码

  • 200 OK:请求成功。
  • 201 Created:资源已创建。
  • 204 No Content:请求成功,但没有返回内容。
  • 400 Bad Request:客户端请求有误。
  • 401 Unauthorized:请求未授权。
  • 403 Forbidden:请求被拒绝。
  • 404 Not Found:资源未找到。
  • 500 Internal Server Error:服务器内部错误。

版本控制

  • 可以通过 URL 路径或请求头来实现API版本控制。

2. 在项目中应用

实体类

需要用到我们之前创建的实体类 User

// 用于封装参数的实体类
public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

控制类

创建一个控制器类 UserController 来尝试使用这个 RESTful 风格。

@RestController
public class UserController {// Get:用于获取资源// 动态方式获取 {id},需要添加注解 @PathVariable@GetMapping("/user/{id}")public String getUserById(@PathVariable int id) {return "根据 ID 获取用户信息:" + id;}// Post:用于创建资源@PostMapping("/user")public String addUser(User user) {System.out.println(user.toString());return "添加用户";}// Put:用于更新资源@PutMapping("/user")public String updateUser(User user) {return "更新用户";}// Delete:用于删除资源@DeleteMapping("/user/{id}")public String deleteUser(@PathVariable int id) {return "根据 ID 删除用户信息:" + id;}}

测试方法

比如测试一下第一个 GET 方法。

在这里插入图片描述


九、Swagger3

在 Spring Boot 3.0 中使用 Swagger 所需要的依赖和 2.7 有所不同。

原因很简单,Spring Boot 3.0 是一次大版本升级,故造成了很多不兼容更新。

例如最低兼容的 Java 版本为 17,底层也切换到了 Spring 6。

所以自 2020 年以来没有更新过的 springfox-swagger2 和 springfox-swagger-ui 自然不会兼容 2022 年发布的 Spring Boot 3.0。


1. 添加 Maven 依赖

pom.xml 文件中添加 Maven 依赖,用于 Swagger3 的使用。

<!-- Swagger(openAPI) 相关功能依赖-->
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version>
</dependency>
<!--  搭配校验使用,使用与 Spring Boot 相同的版本号  -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>3.3.4</version>
</dependency>

2. 配置 Swagger3

application.properties 中添加如下配置,启用并配置 OpenAPISwagger UI

OpenAPISwagger UI 有自己默认的访问地址,当然也可以自己设置。

# 配置 swagger
# 启用并配置 OpenAPI 文档生成
springdoc.api-docs.enabled=true
# 默认地址 http://localhost:8080/v3/api-docs
# 自定义访问地址
#springdoc.api-docs.path=/user-service/v3/api-docs# 配置 Swagger UI
springdoc.swagger-ui.enabled=true
# 默认地址 http://localhost:8080/swagger-ui/index.html
# 自定义访问地址
#springdoc.swagger-ui.path=/user-service/swagger-ui/index.html

然后,创建 Swagger3 的配置类 SwaggerConfig,对文档的一些细节进行设置。

  • title - 标题
  • description - 描述
  • version - 版本
@Configuration
public class SwaggerConfig {@Beanpublic OpenAPI swaggerOpenApi() {return new OpenAPI().info(new Info().title("XXX微服务平台").description("描述平台").version("v1.0.0")).externalDocs(new ExternalDocumentation().description("设计文档").url("https://blog.csdn.net/Sareur_1879?type=blog"));}
}

3. 网址访问

然后启动项目,就可以通过网址进行访问 API 文档了。

// 默认地址 http://localhost:8080/swagger-ui/index.html
// 自定义访问地址 http://localhost:8080/user-service/swagger-ui/index.html

4. 存在的问题

在 Swagger2 版本是可以正常上传文件的(我们上面那个文件上传接口是可以正常使用的,文档中的参数类型 form-data 是对的)

但是,新版本的 OpenAPI(Swagger3) 在文件上传方面存在问题,在 Postman 中测试文件上传功能正确后,Swagger3 中无法正确识别上传参数的类型 form-data,它显示的是 String

这导致了文件类型上传不成功。(Postman 测试是成功的,Swagger3 反而不成功,可见 Swagger3 也不是很可信)

这个问题笔者尝试了多种方法后尚未解决,期待好心人的告知。


十、MyBatisPlus

MyBatisPlus 是一个 MyBatis 的增强工具,旨在简化开发、提高效率。它在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。接下来我们在 Spring Boot 项目中尝试使用 MyBatisPlus。

1. 添加 Maven 依赖

pom.xml 文件中添加。

Lombok

Lombok 是一个 Java 库,使用 Lombok 可以简化实体类的代码,例如自动生成 gettersetter 方法、构造函数、toString 方法等,可以减少样板代码的编写。

<!-- lombok 用于自动 getter/setter -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope>
</dependency>

MyBatisPlus 需要的依赖

<!-- MyBatisPlus-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.8</version>
</dependency><!-- MySQL 驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency><!-- 数据连接池 druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.23</version>
</dependency>

2. ORM 框架

ORM(Object-Relational Mapping,对象关系映射)是一种编程技术,用于将对象模型与关系型数据库模型之间进行转换。简单来说,ORM 允许开发者使用面向对象的编程语言(如 Java)来操作数据库,而不需要直接编写 SQL 语句。这种方式可以提高开发效率,减少错误,并且使代码更易于维护。

MyBatis 是一个非常强大且灵活的 ORM 框架,特别适合需要精细控制 SQL 语句的场景。


配置数据库

在配置文件 application.properties 中配置数据库

# 数据库配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 用 jdbc 连接数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# mydb 对应本地 mysql 的数据库
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false
spring.datasource.username=数据库账号
spring.datasource.password=数据库密码
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

创建数据表

使用 Navicat 工具连接本地 MySQL 数据库,新建数据库 mydb,在 mydb 中创建数据表 user

表结构如下,可以新建查询,运行 sql 文件直接生成。

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`birthday` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

然后插入一些测试数据

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'zhangsan', '123456', '2020-01-13');
INSERT INTO `user` VALUES (2, 'lisi', '123', '2020-03-13');
INSERT INTO `user` VALUES (3, 'wangwu', '14567', '2023-07-09');

在 Navicat 中新建查询,选择对应的数据库,写入 sql 语句,然后点击运行。

在这里插入图片描述


修改实体类

@Data 是 Lombok 提供的一个非常强大的注解,它可以一次性给类生成多个常用的方法,从而大大减少样板代码的编写。具体来说,@Data 注解会为类中的每个字段自动生成以下这些方法:

  • Getter 方法:为每个字段生成 get 方法。
  • Setter 方法:为每个字段生成 set 方法。
  • toString 方法:生成一个 toString 方法,包含所有字段的信息。
  • equals 和 hashCode 方法:生成 equalshashCode 方法,用于比较对象是否相等。
  • RequiredArgsConstructor:生成一个包含所有 final 字段和 @NonNull 字段的构造函数。

实体类 User 对应数据库 MySQL 中的 user 表,user 表中的字段与 User 中的变量一一对应。

  • 表名与类名应该一致;
  • 如果表名与类名不一致,使用 @TableName 注解进行匹配;
  • @TableId 注解用于标记实体类中的主键字段,如 id;
  • IdType.AUTO 表示自增。

配合添加的 Lombok 使用,我们修改一下 User 类,使用 @Data 注解后,实体类中的样板代码明显减少。

/*** @TableName("user")* 如果表名与类名不一致,使用该注解进行匹配*/
@Data   // Lombok 会自动生成相关 Getter/Setter 方法,以及 toString 方法
public class User {/*** @TableId 该注解用于标记实体类中的主键字段* IdType.AUTO 自增*/@TableId(type = IdType.AUTO)private int id;private String username;private String password;private String birthday;}

3. 修改主启动类

在主启动文件中添加 @MapperScan 注解,扫描 mapper 包。

UserMapper 接口就放在 mapper 包下面,记得要写一整串的包名,建议右键 Copy Reference

在这里插入图片描述


4. 创建 Mapper 接口

创建 UserMapper 接口

  • 添加注解 @Mapper
  • 继承 BaseMapper<User> 接口,根据传入的 User 自动匹配数据库中同名的表。
  • MyBatis-Plus 提供了丰富的 CRUD(增删改查) 操作。
  • 可以调用 BaseMapper 中写好的方法,实现数据增删改查。一些 SQL 语句不需要自己重复写了。
@Mapper
public interface UserMapper extends BaseMapper<User> {/*** 继承 BaseMapper<User>* 根据传入的 User 自动匹配数据库中同名的表* 可以调用 BaseMapper 中写好的方法,实现数据增删改查*/}

5. 创建 Controller 层

创建 UserController2:响应前端网络请求。

在项目中,我们使用 MybatisPlus 提供的两个操作:

  • 查询:调用 BaseMapper 中的 selectList() 方法,null 表示没有查询条件,也就是查询全部记录的意思。
  • 插入数据
    • 调用 BaseMapper 中的 insert() 方法,user 对象中的数据是前端发送过来的,需要插入到底层的数据库表中;
    • id 是自增字段,不需要插入,会自己生成;
    • 由于 User 类的 id 使用了注解标注为主键和自增,当我们在控制台打印 user 对象时,会自动读取数据表中的 id 字段。这就是为什么前端请求中没有参数 id,后端控制台却能打印出 id 的原因。
  • BaseMapper 是自带的,UserMapper 继承了这个接口,子类对象可以使用父类中的一些方法
@RestController
public class UserController2 {@Autowired  // spring 注入 UserMapperprivate UserMapper userMapper;// 查询@GetMapping("/user2")public List<User> query() {List<User> list = userMapper.selectList(null);System.out.println(list);return list;}// 插入数据@PostMapping("/user2")public String save(User user) {// 当数据插入成功后,insert 方法的返回值大于 0int i = userMapper.insert(user);// 虽然没有插入 id,但使用注解标注为主键和自增,user 中会读取数据表中的 id,然后打印到控制台上System.out.println(user);if (i > 0) {return "插入成功";} else {return "插入失败";}}
}

6. 测试方法

使用 Postman 工具对这两个 API 接口进行测试。

查找测试

在这里插入图片描述



新增测试

在这里插入图片描述


(全文完)


参考资料

上篇速递 - Spring Boot 3 + MybatisPlus:https://blog.csdn.net/Sareur_1879/article/details/143181790

参考学习视频 - SpringBoot + Vue 全栈开发:https://www.bilibili.com/video/BV1nV4y1s7ZN/

参考文章 - Java 开发环境搭建:https://blog.csdn.net/Sareur_1879/article/details/137963848

参考文章 - Maven 在 IDEA 中的配置与使用:https://blog.csdn.net/Sareur_1879/article/details/143091933

参考文章 - Spring Boot 项目是两种创建方式:https://blog.csdn.net/Sareur_1879/article/details/139201323

Maven 官网:https://maven.apache.org/download.cgi

MVN 仓库:https://mvnrepository.com/

Spring Boot 官网:https://spring.io/projects/spring-boot

Oracle 官网:https://www.oracle.com

IDEA 官网:https://www.jetbrains.com.cn/idea/

Postman 官网:https://www.postman.com/

Notepad++ 下载地址:https://notepad-plus.en.softonic.com/

WinRAR 下载地址:https://www.winrar.com.cn/

相关文章:

Java 开发——(下篇)从零开始搭建后端基础项目 Spring Boot 3 + MybatisPlus

上篇速递 - Spring Boot 3 MybatisPlus 五、静态资源访问 1. 基础配置 在 Spring Boot 中访问静态资源非常方便。Spring Boot 默认支持从以下位置加载静态资源&#xff1a; /META-INF/resources//resources//static//public/ 这些目录下的文件可以直接通过 URL 访问。 例…...

Redis 线程控制 问题

前言 相关系列 《Redis & 目录》《Redis & 线程控制 & 源码》《Redis & 线程控制 & 总结》《Redis & 线程控制 & 问题》 参考文献 《Redis分布式锁》 Redis如何实现分布式锁&#xff1f; Redis是单进程单线程的&#xff0c;指令执行时不会…...

005 IP地址的分类

拓扑结构如下 两台主机处于同一个网关下&#xff0c;通过ping命令检测&#xff0c;可以连通 &nbps; 拓扑结构如下 使用ping 检查两台电脑是否相通, 因为网络号不一样&#xff0c;表示两台电脑不在同一个网络&#xff0c;因此无法连通 拓扑结构如下 不在同一网络的PC要相…...

Java 并发工具(12/30)

目录 Java 并发工具 1. Executor 框架 1.1 线程池 1.2 ExecutorService 和 Future 2. 同步辅助类 2.1 CountDownLatch 2.2 Semaphore 3. 并发集合 3.1 ConcurrentHashMap 总结与后续 Java 并发工具 在多线程编程中&#xff0c;高效管理线程和任务至关重要。Java 提供…...

filebeat+elasticsearch+kibana日志分析

1 默认配置 1.1 filebeat filebeat-7.17.yml,从网关中下载k8s的配置&#xff0c;指定es和kibana的配置 通过kibana查询可以查询到日志了&#xff0c;但此时还不知道具体怎么用。 1.2 kibana 在Discover中创建索引格式&#xff1a;filebeat-*&#xff0c;得到如下图&#xf…...

Google Recaptcha V2 简单使用

最新的版本是v3&#xff0c;但是一直习惯用v2&#xff0c;就记录一下v2 的简单用法&#xff0c;以免将来忘记了 首先在这里注册你域名&#xff0c;如果是本机可以直接直接填 localhost 或127.0.0.1 https://www.google.com/recaptcha/about/ 这是列子 网站密钥&#xff1a;是…...

Rust编程中的浮点数比较

缘由&#xff1a;在看Rust编写的代码&#xff0c;发现了一行浮点数等于比较的代码&#xff0c;于是编辑如下内容。 在Rust中&#xff0c;进行浮点数比较时需要特别小心&#xff0c;因为浮点数由于精度限制无法精确表示小数&#xff0c;可能会导致直接比较&#xff08;如 &…...

java访问华为网管软件iMaster NCE的北向接口

最近做的一个项目&#xff0c;需要读取华为一个叫iMaster NCE的网管软件的北向接口。这个iMaster NCE&#xff08;以下简称NCE&#xff09;用于管理项目的整个网络&#xff0c;尤其是光网络。业主要求我们访问该软件提供的对外接口&#xff0c;读取一些网络信息&#xff0c;比如…...

UV紫外相机

在产业设备领域&#xff0c;运用相机进行检测的需求很大&#xff0c;应用也很多样&#xff0c;对于图像传感器性能的期望逐年提升。在这样的背景下&#xff0c;可拍摄紫外线&#xff08;UV&#xff1a;Ultra Violet&#xff09;图像的相机拥有越来越广泛的应用场景。将UV照明和…...

第十八届联合国世界旅游组织/亚太旅游协会旅游趋势与展望大会在广西桂林开幕

10月19日&#xff0c;第十八届联合国世界旅游组织/亚太旅游协会旅游趋势与展望大会(以下简称“大会”)在广西桂林开幕&#xff0c;来自美国、英国、德国、俄罗斯、柬埔寨等25个国家约120名政府官员、专家学者和旅游业界精英齐聚一堂&#xff0c;围绕“亚洲及太平洋地区旅游业&a…...

Effective Java(第三版) _ 创建和销毁对象

一、前言 《Effective Java》 这本书&#xff0c;在刚从事 Java 开发的时候就被老师推荐阅读过&#xff0c;当时囫囵吞枣的看了一部分&#xff0c;不是特别的理解&#xff0c;也就搁置了&#xff0c;现在已经更新到第三版了&#xff0c;简单翻阅了一下&#xff0c;发现有些条例…...

你的EA无法运行的几种常见原因

大多数情况下&#xff0c;EA正常运行是指其能够自动开仓交易&#xff0c;毕竟EA的主要目的是根据某种策略自动进行交易。如果从网上下载或其他途径获得的EA在开始时能够正常交易&#xff0c;但在修改参数后却不再交易&#xff0c;可能的问题是什么呢&#xff1f;下面列举了一些…...

通过自定义指令实现图片懒加载

前提&#xff1a;使用到了VueUse插件。 先创建自定义插件文件夹 // 定义懒加载插件 import { useIntersectionObserver } from vueuse/core // 这个是VueUse里的一个方法export const lazyPlugin {install(app) {// 懒加载指令逻辑 定义全局指令app.directive(img-lazy, {mo…...

QT项目-仿QQ聊天(带宠物系统)

目录 一&#xff0c;项目介绍 二&#xff0c;开发环境 三&#xff0c;涉及技术 四&#xff0c;项目效果示例图 1&#xff0c;登录界面 2&#xff0c;主界面 3&#xff0c;聊天界面 4&#xff0c;功能界面 5&#xff0c;宠物界面 一&#xff0c;项目介绍 这是一个基于u…...

前端算法题:3216. 交换后字典序最小的字符串(力扣每日一题)

今日题目为&#xff1a;3216. 交换后字典序最小的字符串 题目详情&#xff1a; 给你一个仅由数字组成的字符串 s&#xff0c;在最多交换一次 相邻 且具有相同 奇偶性 的数字后&#xff0c;返回可以得到的字典序最小的字符串。 如果两个数字都是奇数或都是偶数&#xff0c;则…...

29.1 时序监控和日志监控的对比,分析日志监控的核心诉求

本节重点介绍 : 监控系统分类时序监控和日志监控的对比轻量日志监控系统的诉求 监控系统分类 监控系统按照原理和作用大致可以分为三类 日志类&#xff08;Log&#xff09;调用链类&#xff08;Tracing&#xff09;度量类&#xff08;Metrics&#xff09; 日志类&#xff08…...

git仓库分支

操作 切换分支 git checkout 1.2.5 git checkout 1.3.0 使用命令切换分支之后&#xff0c;代码内容加载过后也是切换好的...

多模态机器学习在精准健康中的应用--九五小庞

这篇综述文章探讨了将多模态数据融合应用于医疗诊断和预后预测的最新研究进展。 本文作者们确定了三个主要的研究问题&#xff1a;多模态数据融合在健康领域的文献特征是什么&#xff1f;用于分析多模态健康数据的不同分析技术、方法和策略是什么&#xff1f;不同类型的异构数…...

提升网站速度与性能优化的有效策略与实践

内容概要 在数字化快速发展的今天&#xff0c;网站速度与性能优化显得尤为重要&#xff0c;它直接影响用户的浏览体验。用户在访问网站时&#xff0c;往往希望能够迅速获取信息&#xff0c;若加载时间过长&#xff0c;轻易可能导致他们转向其他更为流畅的网站。因此&#xff0…...

MySQL索引从基础到原理,看这一篇就够了

https://developer.aliyun.com/article/841106 https://zhuanlan.zhihu.com/p/29118331 索引创建使用总结 因为索引对于改善查询性能的作用是巨大的&#xff0c;所以我们的目标是尽量使用索引。 1. 索引的创建 • 1、在用于 where 判断 order 排序和 join 的(on)字段上创…...

普通高考预报名上传蓝底证件照手机自拍方法详解

普通高考预报名过程中&#xff0c;上传一张合规的蓝底证件照是必不可少的一步。本文将详细介绍如何使用手机自拍并使用工具来制作符合要求的蓝底证件照。注意&#xff0c;目前仅有广东等个别省份允许特定类型考生使用自拍照上传&#xff08;例如普高预报名阶段、学考报名&#…...

Webserver(2.3)exec函数族

目录 exec函数族介绍execl函数execlp函数 exec函数族介绍 c语言中没有重载&#xff0c;因为不允许同名函数 一系列功能相似的函数称为函数族 exec函数族的作用是根据指定的文件名找到可执行文件&#xff0c;并用它来取代调用进程的内容。 程序在运行的时候&#xff0c;fork一…...

LeetCode Hot100 - 子串篇

前言 挑战一个月刷完力扣的hot100&#xff0c;记录一下每题的思路~ 这次是子串相关的题目 &#xff08;1&#xff09;560. 和为 K 的子数组 ①暴力枚举&#xff0c;使用一个变量sum记录以l开头r结尾的情况 class Solution {public int subarraySum(int[] nums, int k) {int r…...

【Android】Convenient ADB Commands

Install adb install -r <path>Uninstall adb uninstall <pkg>Start adb shell am start -n <pkg>/.SplashActivityStop adb shell am force-stop <pkg>Reset adb shell pm clear <pkg>Reboot adb rebootShutdown adb reboot -p...

elementUI 时间控件控制时间选择

选择时间大于当前月或小于2024年一月禁止选择 <el-form-item label"成交月份:" label-width"105px" ><div class"block"><el-date-pickerv-model"formData.deal_month"type"month":picker-options"pick…...

什么是x86架构,什么是arm架构

什么是 x86 架构&#xff1f; x86 架构是一种经典的指令集架构&#xff08;ISA&#xff09;&#xff0c;最早由英特尔在 1978 年推出&#xff0c;主要用于 PC、服务器等领域。 它是一种复杂指令集计算&#xff08;CISC&#xff09;架构&#xff0c;支持大量的复杂指令和操作&…...

c语言水仙花,超简单讲解

效果 3或者大于3位数 每一位的位数次方相加等于 自身 例如 153 13 53 33 结果为112527 153 1634&#xff1a; 计算过程&#xff1a; 14643444112968125616341^4 6^4 3^4 4^4 1 1296 81 256 16341464344411296812561634 过程 求得单独将所有位数的正数拎出来…...

Flutter 13 网络层框架架构设计,支持dio等框架。

在移动APP开发过程中&#xff0c;进行数据交互时&#xff0c;大多数情况下必须通过网络请求来实现。客户端与服务端常用的数据交互是通过HTTP请求完成。面对繁琐业务网络层&#xff0c;我们该如何通过网络层架构设计来有效解决这些问题&#xff0c;这便是网络层框架架构设计的初…...

Python小白学习教程从入门到入坑------第二十课 闭包修饰器(语法基础)

一、递归函数 1.1 基本信息 递归函数是指一个函数在其定义中直接或间接地调用了自身 递归在解决许多问题&#xff08;如树的遍历、图的搜索、数学中的分治算法等&#xff09;时非常有用 在Python中&#xff0c;递归函数可以通过简单的语法来实现 然而&#xff0c;使用递归…...

Vue+element-ui实现网页右侧快捷导航栏 Vue实现全局右侧快捷菜单功能组件

Vue+element-ui实现网页右侧快捷导航栏 Vue实现全局右侧快捷菜单功能组件 可视区域没超过当前屏幕高度时候只显示三个菜单效果 可视区域超过当前屏幕高度时,显示可回到顶部菜单的,当然这个菜单显示条件可以自定义,根据需求设置 然后将这个整体功能创建为一个全局组件 代…...