SpringMVC 控制层框架-下

五、SpringMVC其他扩展


1. 异常处理机制
1.1 异常处理概念

开发过程中是不可避免地会出现各种异常情况,例如网络连接异常、数据格式异常、空指针异常等等。异常的出现可能导致程序的运行出现问题,甚至直接导致程序崩溃。因此,在开发过程中,合理处理异常、避免异常产生、以及对异常进行有效的调试是非常重要的。

对于异常的处理,一般分为两种方式:

  • 编程式异常处理:是指在代码中显式地编写处理异常的逻辑。它通常涉及对异常类型的检测及其处理,例如使用 try-catch 块来捕获异常,然后在 catch 块中编写特定的处理代码,或者在 finally 块中执行一些清理操作。在编程式异常处理中,开发人员需要显式地进行异常处理,异常处理代码混杂在业务代码中,导致代码可读性较差。
  • 声明式异常处理:则是将异常处理的逻辑从具体的业务逻辑中分离出来,通过配置等方式进行统一的管理和处理。在声明式异常处理中,开发人员只需要为方法或类标注相应的注解(如 @Throws 或 @ExceptionHandler),就可以处理特定类型的异常。相较于编程式异常处理,声明式异常处理可以使代码更加简介、易于维护和扩展。

站在宏观角度来看待声明式事务处理:

整个项目从架构这个层面设计的异常处理的统一机制和规范。

一个项目中会包含很多个模块,各个模块需要分工完成。如果张三负责的模块按照 A 方案处理异常,李四负责的模块按照 B 方案处理异常...各个模块处理异常的思路、代码、命名细节都不一样,那么就会让整个项目非常混乱。

使用声明式异常处理,可以统一项目处理异常思路,项目更加清晰了。

1.2 声明式异常的好处
  • 使用声明式代替编程式来实现异常处理管理
    • 让异常控制和核心业务解耦,二者各自维护,结构性更好
  • 整个项目层面使用同一套规则来管理异常
    • 整个项目代码风格更加统一、简介
    • 便于团队成员之间的彼此协作
1.3 基于注解异常声明异常处理

1)声明异常处理控制器类

异常处理控制类,统一定义异常处理 handler 方法

/*** projectName: com.atguigu.execptionhandler* * description: 全局异常处理器,内部可以定义异常处理Handler!*/
/*** @RestControllerAdvice = @ControllerAdvice + @ResponseBody* @ControllerAdvice 代表当前类的异常处理controller! */
@RestControllerAdvice
public class GlobalExceptionHandler {}

2)声明异常处理 handler 方法

异常处理 handler 方法和普通的 handler 方法参数接收和响应都一致。只不过异常处理 handler 方法要映射异常,发生对应的异常会调用。普通的 handler 方法要使用 @RequestMapping 注解映射路径,发生对应的路径调用。

/*** 异常处理handler * @ExceptionHandler(HttpMessageNotReadableException.class) * 该注解标记异常处理Handler,并且指定发生异常调用该方法!* * * @param e 获取异常对象!* @return 返回handler处理结果!*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public Object handlerJsonDateException(HttpMessageNotReadableException e){return null;
}/*** 当发生空指针异常会触发此方法!* @param e* @return*/
@ExceptionHandler(NullPointerException.class)
public Object handlerNullException(NullPointerException e){return null;
}/*** 所有异常都会触发此方法!但是如果有具体的异常处理Handler! * 具体异常处理Handler优先级更高!* 例如: 发生NullPointerException异常!*       会触发handlerNullException方法,不会触发handlerException方法!* @param e* @return*/
@ExceptionHandler(Exception.class)
public Object handlerException(Exception e){return null;
}

3)配置文件扫描控制器类配置

确保异常处理控制类被扫描

 <!-- 扫描controller对应的包,将handler加入到ioc--><context:component-scan base-package="com.atguigu.controller,com.atguigu.exceptionhandler" />
2. 拦截器使用
2.1 拦截器概念

拦截器和过滤器解决问题

  • 生活中

为了提高乘客效率,在乘客进入站台前统一检票

  • 程序中

在程序中,使用拦截器在请求到达具体 handler 方法前统一执行检测

拦截器 VS 过滤器:

  • 相似点
    • 拦截:必须先把请求拦住,才能执行后续操作
    • 过滤:拦截器或过滤存在的意义就是对请求进行统一处理
    • 放行:对请求执行了必要操作后,放请求过去,让它访问原本想要访问的资源
  • 不同点
    • ​​​​​​​工作平台不同
      • ​​​​​​​过滤器工作在 Servlet 容器中
      • 拦截器工作在 SpringMVC 的基础上
    • 拦截的范围
      • ​​​​​​​过滤器:能够拦截到的最大范围是整个 Web 应用
      • 拦截器:能够拦截到的最大范围是整个 SpringMVC 负责的请求
    • IOC 容器支持
      • ​​​​​​​过滤器:想得到 IOC 容器需要调用专门的工具方法,是间接的
      • 拦截器:它自己就在 IOC 容器中,所以可以直接从 IOC 容器中装配组件,也就是可以直接得到 IOC 容器的支持

选择:

功能需要如果用 SpringMVC 的拦截器能够实现,就不使用过滤器。

2.2 拦截器使用

1)创建拦截器类

public class Process01Interceptor implements HandlerInterceptor {// 在处理请求的目标 handler 方法前执行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("request = " + request + ", response = " + response + ", handler = " + handler);System.out.println("Process01Interceptor.preHandle");// 返回true:放行// 返回false:不放行return true;}// 在目标 handler 方法之后,handler报错不执行!@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", modelAndView = " + modelAndView);System.out.println("Process01Interceptor.postHandle");}// 渲染视图之后执行(最后),一定执行!@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", ex = " + ex);System.out.println("Process01Interceptor.afterCompletion");}
}

 单个拦截器执行顺序:

  • preHandle() 方法
  • 目标 handler 方法
  • postHandle() 方法
  • 渲染视图(返回 json 没有此步骤)
  • afterCompletion() 方法

2)拦截器配置

springmvc.xml

<!-- 配置拦截器-->
<mvc:interceptors><!-- 默认拦截器,拦截所有请求--><bean class="com.atguigu.interceptor.Process01Interceptor" />
</mvc:interceptors>

 3)配置详解

① 默认拦截全部

<!-- 具体配置拦截器可以指定拦截的请求地址 -->
<mvc:interceptor><!-- 精确匹配 --><mvc:mapping path="/common/request/one"/><bean class="com.atguigu.mvc.interceptor.Process03Interceptor"/>
</mvc:interceptor>

② 精准配置

<!-- 具体配置拦截器可以指定拦截的请求地址 -->
<mvc:interceptor><!-- 精确匹配 --><mvc:mapping path="/common/request/one"/><bean class="com.atguigu.mvc.interceptor.Process03Interceptor"/>
</mvc:interceptor><mvc:interceptor><!-- /*匹配路径中的一层 --><mvc:mapping path="/common/request/*"/><bean class="com.atguigu.mvc.interceptor.Process04Interceptor"/>
</mvc:interceptor><mvc:interceptor><!-- /**匹配路径中的多层 --><mvc:mapping path="/common/request/**"/><bean class="com.atguigu.mvc.interceptor.Process05Interceptor"/>
</mvc:interceptor>

③ 排除配置

<mvc:interceptor><!-- /**匹配路径中的多层 --><mvc:mapping path="/common/request/**"/><!-- 使用 mvc:exclude-mapping 标签配置不拦截的地址 --><mvc:exclude-mapping path="/common/request/two/bbb"/><bean class="com.atguigu.mvc.interceptor.Process05Interceptor"/>
</mvc:interceptor>

 ④ 多个拦截器执行顺序

  1. preHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置顺序调用各个 preHandle() 方法。
  2. postHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 postHandle() 方法。
  3. afterCompletion() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 afterCompletion() 方法。
2.3 拦截器作用位置图解

 2.4 拦截器案例

一个网站有 5、6个资源,其中有一个为登录资源,两个无需登录即可访问,另外三个需要登录后才能访问,如果不登录就访问那三个资源,需要拦截,并且提示登录后访问。

访问资源的请求地址:

登录资源:/public/resource/login

公共资源1:/public/resource/one

公共资源2:/public/resource/two

私密资源1:/private/resource/one

私密资源2:/private/resource/two

私密资源3:/private/resource/three

案例实现:

1) 声明资源类

① PublicController

/*** projectName: com.atguigu.controller* description: 公有资源控制类*/
@RestController
@RequestMapping("public/resource")
public class PublicController {/*** 模拟登录,将假用户数据存储到session中!*/@GetMapping("login")public Object login(HttpSession session){session.setAttribute("user","root");return "login success!!";}@GetMapping("one")public Object one(){return "public one";}@GetMapping("two")public Object two(){return "public two";}
}

② PrivateController

@RestController
@RequestMapping("private/resource")
public class PrivateController {@GetMapping("one")public Object one(){return "private one";}@GetMapping("two")public Object two(){return "private two";}@GetMapping("three")public Object three(){return "private two";}}

2)声明拦截器类

/*** projectName: com.atguigu.interceptor** description: 登录保护拦截器*/
public class LoginProtectInterceptor implements HandlerInterceptor {/*** 登录保护方法* @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance evaluation* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object user = request.getSession().getAttribute("user");if (user == null){response.setContentType("text/html;charset=utf-8");//没有登录response.getWriter().print("请先登录,再访问! <a href='/public/resource/login'>点击此处登录</a>");//拦截,不到达目标地址return false;}return true;}
}

3)配置拦截器类 

<!-- 配置拦截器-->
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/private/**"/><bean class="com.atguigu.interceptor.LoginProtectInterceptor" /></mvc:interceptor>
</mvc:interceptors>
 3. 参数校验

在Web 应用三层架构体系中,表述层负责接收浏览器提交的数据,业务逻辑层负责数据的处理。为了能够让业务逻辑层基于正确的数据进行处理,我们需要在表述层对数据进行检查,将错误的数据隔绝在业务逻辑层之外。

1)校验概述

JSR 303 是 Java 为Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0标准中。JSR 303 通过在 Bean 属性上标注类似于 @NoNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证。

 

注解规则
@Null标注值必须为 null
@NotNull标注值不可为 null
@AssertTrue标注值必须为 true
@AssertFalse标注值必须为 false
@Min(value)标注值必须大于或等于 value
@Max(value)标注值必须小于或等于 value
@DecimalMin(value)标注值必须大于或等于 value
@DecimalMax(value)标注值必须小于或等于 value
@Size(max,min)标注值大小必须在 max 和 min 限定的范围内
@Digits(integer,fratction)标注值值必须是一个数字,且必须在可接受的范围内
@Past标注值只能用于日期型,且必须是过去的日期
@Future标注值只能用于日期型,且必须是将来的日期
@Pattern(value)标注值必须符合指定的正则表达式
JSR 303 只是一套标准,需要提供其实现才可以使用。Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:
注解规则
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@Email标注值必须是格式正确的 Email 地址
@Length标注值字符串大小必须在指定的范围内
@NotEmpty标注值字符串不能是空字符串
@Range标注值必须在指定的范围内
Spring 4.0 版本已经拥有自己独立的数据校验框架,同时支持 JSR 303 标准的校验框架。Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。在SpringMVC 中,可直接通过注解驱动 mvc:annotation-driven 的方式进行数据校验。Spring 的 LocalValidatorFactoryBean 既实现了 Spring 的 Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在Spring容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean中。Spring本身并没有提供JSR 303的实现,所以必须将JSR 303的实现者的jar包放到类路径下。
配置 mvc:annotation-driven 后,SpringMVC 会默认装配好一个 LocalValidatorFactoryBean,通过在处理方法的入参上标注 @Validated 注解即可让 SpringMVC 在完成数据绑定后执行数据校验的工作。

2)操作演示

导入依赖

<!-- 校验注解 -->
<dependency><groupId>jakarta.platform</groupId><artifactId>jakarta.jakartaee-web-api</artifactId><version>9.1.0</version><scope>provided</scope>
</dependency><!-- 校验注解实现-->        
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>8.0.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-annotation-processor</artifactId><version>8.0.0.Final</version>
</dependency>

应用校验注解

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import org.hibernate.validator.constraints.Length;/*** projectName: com.atguigu.pojo*/
public class User {//age   1 <=  age < = 150@Min(10)private int age;//name 3 <= name.length <= 6@Length(min = 3,max = 10)private String name;//email 邮箱格式@Emailprivate String email;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}

 handler 标记和绑定错误收集

@RestController
@RequestMapping("user")
public class UserController {/*** @Validated 代表应用校验注解! 必须添加!*/@PostMapping("save")public Object save(@Validated @RequestBody User user,//在实体类参数和 BindingResult 之间不能有任何其他参数, BindingResult可以接受错误信息,避免信息抛出!BindingResult result){//判断是否有信息绑定错误! 有可以自行处理!if (result.hasErrors()){System.out.println("错误");String errorMsg = result.getFieldError().toString();return errorMsg;}//没有,正常处理业务即可System.out.println("正常");return user;}
}

 3)易混总结

@NotNull (包装类型不为null)、@NotEmpty(集合类型长度大于0) 、@NotBlank(字符串,不为null,切不为" "字符串) 都是用于在数据校验中检查字段值是否为空的注解,但是它们的用法和校验规则有所不同。

4. 文件上传和下载
4.1 文件上传

1)文件上传表单页面

位置:index.xml

  • 第一点:请求方式必须是 POST
  • 第二点:请求体的编码方式必须是 multipart / form-data(通过form 标签的 enctype 属性设置)
  • 第三点:使用 input 标签、type 属性设置为 file 来生成文件上传框
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/save/picture" method="post" enctype="multipart/form-data">昵称:<input type="text" name="nickName" value="龙猫" /><br/>头像:<input type="file" name="headPicture" /><br/>背景:<input type="file" name="backgroundPicture" /><br/><button type="submit">保存</button></form>
</body>
</html>

 2)springmvc 环境要求

pom.xml 添加依赖

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version>
</dependency>

配置文件上传处理器(springmvc配置)

<!-- 文件上传处理器,可处理 multipart/* 请求并将其转换为 MultipartFile 对象-->
<bean id="multipartResolver"class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

注:CommonsMultipartResolver 的 bean 的 id,必须是:multipartResolver 如果不是这个值,会在上传文件时报错 在 web.xml 文件中添加 Multipart 配置

<servlet><servlet-name>yourAppServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><multipart-config><!-- 定义文件上传时所需的最大值,单位为字节 --><max-file-size>10485760</max-file-size><!-- 定义单个上传文件的最大值,单位为字节 --><max-request-size>20971520</max-request-size><!-- 定义内存中存储文件的最大值,超过此大小的文件会写入到硬盘中 --><file-size-threshold>5242880</file-size-threshold></multipart-config><load-on-startup>1</load-on-startup>
</servlet>

3)handler 方法接收数据

/*** 上传的文件使用 MultipartFile 类型接收其相关数据* @param nickName* @param picture* @param backgroundPicture* @return* @throws IOException*/
@PostMapping ("picture")
public String upload(String nickName, @RequestParam("headPicture") MultipartFile picture, @RequestParam("backgroundPicture")MultipartFile backgroundPicture) throws IOException {System.out.println(nickName);String inputName = picture.getName();System.out.println("文件上传表单项的 name 属性值:" + inputName);// 获取这个数据通常都是为了获取文件本身的扩展名String originalFilename = picture.getOriginalFilename();System.out.println("文件在用户本地原始的文件名:" + originalFilename);String contentType = picture.getContentType();System.out.println("文件的内容类型:" + contentType);boolean empty = picture.isEmpty();System.out.println("文件是否为空:" + empty);long size = picture.getSize();System.out.println("文件大小:" + size);byte[] bytes = picture.getBytes();System.out.println("文件二进制数据的字节数组:" + Arrays.asList(bytes));InputStream inputStream = picture.getInputStream();System.out.println("读取文件数据的输入流对象:" + inputStream);Resource resource = picture.getResource();System.out.println("代表当前 MultiPartFile 对象的资源对象" + resource);return "home";
}
```

4)MultipartFile 接口

5)文件转存

① 底层机制

② 本地转存

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LoFTR关键点特征匹配算法环境构建与图像匹配测试Demo

0&#xff0c;LoFTR CVPR 2021论文《LoFTR: Detector-Free Local Feature Matching with Transformers》开源代码 1&#xff0c;项目主页 LoFTR: Detector-Free Local Feature Matching with Transformers 2&#xff0c;GItHub主页 GitHub - zju3dv/LoFTR: Code for "…

Vue 状态管理 Vue CLI

Vue 状态管理 & Vue CLI 1、状态管理2、集中状态管理2.1 Vuex2.1.1 Vuex核心概念2.1.2 Vuex Store实例2.1.3 Vuex Getter2.1.4 Vuex Mutation2.1.4 Vuex Actions2.1.4 Vuex Module 2.2 Pinia2.2.1功能增强 3、Vuex 实现原理4、Pinia 实现原理5、CLI5.1 实现 1、状态管理 将…

vue 搜索框

效果 创建搜索组件&#xff1a; 在Vue项目中&#xff0c;首先需要创建一个搜索组件。这个组件通常包含一个输入框和一个搜索按钮。使用v-model指令将输入框与组件的数据属性&#xff08;如searchKeyword&#xff09;进行双向绑定&#xff0c;以便获取用户输入的关键词。处理搜索…

MongoDB教程(二十一):MongoDB大文件存储GridFS

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、GridFS…

科技云报道:算网筑基AI注智,中国联通如何讲出AI时代的“新故事”?

科技云报道原创。 AI从未停止进化&#xff0c;也从未停止给人类带来惊喜。 从ChatGPT代表的文生文、Dall-E代表的文生图&#xff0c;到Sora代表的文生视频&#xff0c;Suno为代表的文生音乐&#xff0c;生成式AI的“暴力美学”持续突破内容生产的天花板&#xff0c;大模型技术…

【LLM】-07-提示工程-聊天机器人

目录 1、给定身份 1.1、基础代码 1.2、聊天机器人 2、构建上下文 3、订餐机器人 3.1、窗口可视化 3.2、构建机器人 3.3、创建JSON摘要 利用会话形式&#xff0c;与具有个性化特性&#xff08;或专门为特定任务或行为设计&#xff09;的聊天机器人进行深度对话。 在 Ch…

vue import from

vue import from 导入文件&#xff0c;从XXXX路径&#xff1b;引入文件 import xxxx from “./minins/resize” import xxxx from “./minins/resize.js” vue.config.js 定义 : resolve(src)&#xff1b;就是指src 目录 import xxxx from “/utils/auth” im…

新版GPT-4omini上线!快!真TM快!

大半夜&#xff0c;OpenAI突然推出了GPT-4o mini版本。 当我看到这条消息时&#xff0c;正准备去睡觉。mini版本质上是GPT-4o模型的精简版本&#xff0c;没有什么革命性的创新&#xff0c;因此我并没有太在意。 结果今天早上一觉醒来发现伴随GPT-4o mini上线&#xff0c;官网和…

RAS--APEI 报错解析流程(2)

RAS--APEI 报错解析流程(1) 除了APEI 中除了GHES会记录错误&#xff0c;在Post过程中的错误通常是通过BERT Table汇报 1.BERT Boot Error Record Table is used to report unhandled errors that occurred in a previous boot&#xff0c;it is reported as a ‘one-time polle…

stats 监控 macOS 系统

Stats 监控 macOS 系统 CPU 利用率GPU 利用率内存使用情况磁盘利用率网络使用情况电池电量 brew install stats参考 stats github

Ansible的脚本-----playbook剧本【上】

目录 1.playbook剧本组成 2.playbook剧本实战演练 2.1 实战演练一&#xff1a;给被管理主机安装httpd服务 2.2 实战演练二&#xff1a;定义、引用变量 2.3 实战演练三&#xff1a;指定远程主机sudo切换用户 2.4 实战演练四&#xff1a;when条件判断 2.5 实战演练五&…

ElasticSearch(六)— 全文检索

一、match系列查询 前面讲到的query中的查询&#xff0c;都是精准查询。可以理解成跟在关系型数据库中的查询类似。match系列的查询&#xff0c;是全文检索的查询。会通过分词进行评分&#xff0c;匹配&#xff0c;再返回搜索结果。 1.1 match 查询 "query": {&qu…

.Net Core 微服务之Consul(三)-KV存储分布式锁

引言: 集合上两期.Net Core 微服务之Consul(一)(.Net Core 微服务之Consul(一)-CSDN博客) 。.Net Core 微服务之Consul(二)-集群搭建)(.Net Core 微服务之Consul(二)-集群搭建-CSDN博客) 目录 一. Consul KV 存储 1. KV 存储介绍 1.1 数据模型 1.2 一致性和…

Centos安装、迁移gitlab

Centos安装迁移gitlab 一、下载安装二、配置rb修改&#xff0c;起服务。三、访问web&#xff0c;个人偏好设置。四、数据迁移1、查看当前GitLab版本2、备份旧服务器的文件3、将上述备份文件拷贝到新服务器同一目录下&#xff0c;恢复GitLab4、停止新gitlab数据连接服务5、恢复备…

Docker、containerd、CRI-O 和 runc 之间的区别

容器与 Docker 这个名称并不紧密相关。你可以使用其他工具来运行容器 您可以使用 Docker 或一堆非Docker 的其他工具来运行容器。docker只是众多选项之一&#xff0c;Docker&#xff08;公司&#xff09;在生态系统中创建了一些很棒的工具&#xff0c;但不是全部。 容器方面有…

47.简易电压表的设计与验证(2)

&#xff08;1&#xff09;Verilog 代码&#xff1a; module adc_collect(input clk ,input reset_n ,input [7:0] adc_data ,output clk_adc );wire clk_adc_a ;…

大文件分片上传(前端TS实现)

大文件分片上传 内容 一般情况下&#xff0c;前端上传文件就是new FormData,然后把文件 append 进去&#xff0c;然后post发送给后端就完事了&#xff0c;但是文件越大&#xff0c;上传的文件也就越长&#xff0c;如果在上传过程中&#xff0c;突然网络故障&#xff0c;又或者…

【Linux操作系统】:进程间通信

目录 进程间通信介绍 1、进程间通信的概念 2、进程间通信的目的 3、进程间通信的本质 4、进程间通信的分类 管道 匿名管道 匿名管道的原理 pipe函数 创建匿名管道 管道的四种情况和五种特性 命名管道 使用命令创建命名管道 创建一个命名管道 命名管道的打开规则 …

【ROS2】高级:安全-理解安全密钥库

目标&#xff1a;探索位于 ROS 2 安全密钥库中的文件。 教程级别&#xff1a;高级 时间&#xff1a;15 分钟 内容 背景安全工件位置 公钥材料 私钥材料域治理政策 安全飞地 参加测验&#xff01; 背景 在继续之前&#xff0c;请确保您已完成设置安全教程。 sros2 包可以用来创…

Qt自定义下拉列表-可为选项设置标题、可禁用选项

在Qt中,ComboBox&#xff08;组合框&#xff09;是一种常用的用户界面控件,它提供了一个下拉列表,允许用户从预定义的选项中选择一个。在项目开发中&#xff0c;如果简单的QComboBox无法满足需求&#xff0c;可以通过自定义QComboBox来实现更复杂的功能。本文介绍一个自定义的下…