JAVA系列---HttpServletRequest

Servlet 处理 HTTP 请求的流程

一般情况下,浏览器(客户端)通过 HTTP 协议来访问服务器的资源,Servlet 主要用来处理 HTTP 请求。核心对象有三个

  • Servlet:提供service()方法处理请求
  • ServletRequest:请求信息载体
  • ServletRespond:响应信息载体
    在这里插入图片描述
  1. Servlet 容器接收到来自客户端的 HTTP 请求后,Servlet容器会针对该请求分别创建一个 HttpServletRequest 对象和 HttpServletReponse 对象。
  2. 容器将 HttpServletRequest 对象和 HttpServletReponse 对象以参数的形式传入 service() 方法内,并调用该方法。
  3. 在 service() 方法中 Servlet 通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。
  4. 对 HTTP 请求进行处理。
  5. 请求处理完成后,将响应信息封装到 HttpServletReponse 对象中。
  6. Servlet 容器将响应信息返回给客户端。
  7. 当 Servlet 容器将响应信息返回给客户端后,HttpServletRequest 对象和 HttpServletReponse 对象被销毁。

HttpServletRequest 和 HttpServletReponse 是 Servlet 处理 HTTP 请求流程中最重要的两个对象。HttpServletRequest 对象用于封装 HTTP 请求信息,HttpServletReponse 对象用于封装 HTTP 响应信息。

ServletRequest

ServletRequest接口是Java Servlet API中的一个接口,用于访问Servlet容器接收到的HTTP请求的信息。ServletRequest接口定义了一系列方法,用于获取HTTP请求的参数、属性、输入流等信息,以及对这些信息的操作。所以想要从请求中获取信息,得从ServletRequest 中去寻找

  • getProtocol():返回请求使用的协议的名称和版本号。例如,HTTP/1.1。
  • getScheme():返回请求的协议名称。例如,http、https。
  • getServerName():返回接收请求的服务器的名称。
  • getServerPort():返回接收请求的服务器的端口号。
  • getRemoteAddr():返回客户端的IP地址。
  • getRemoteHost():返回客户端的主机名。
  • getRemotePort():返回客户端的端口号。
  • getLocalAddr():返回服务器的IP地址。
  • getLocalName():返回服务器的主机名。
  • getLocalPort():返回服务器的端口号。
  • getParameter(String name):返回请求参数的值,如果请求参数不存在,则返回null。
  • getParameterNames():返回请求参数的名称的枚举。
  • getParameterValues(String name):返回请求参数的值的数组,如果请求参数不存在,则返回null。
  • getAttribute(String name):返回指定属性名称的属性值,如果属性不存在,则返回null。
  • getAttributeNames():返回所有属性名称的枚举。
  • setAttribute(String name, Object value):将指定属性名称的属性值设置为指定的值。
  • removeAttribute(String name):从请求中删除指定名称的属性。
  • getLocale():返回客户端的首选语言环境。
  • getLocales():返回客户端的所有语言环境。
  • getCharacterEncoding():返回请求字符编码的名称,如果字符编码未指定,则返回null。
  • getContentLength():返回请求的正文的长度,以字节为单位。
  • getContentType():返回请求正文的MIME类型。
  • getInputStream():返回请求正文的InputStream。
  • getReader():返回请求正文的Reader。
  • getProtocol():返回请求使用的协议的名称和版本号。
  • getRemoteUser():返回发出请求的用户的登录名,如果用户未经过身份验证,则返回null。
  • isSecure():返回请求是否通过安全连接传输。
  • getRequestDispatcher(String path):返回用于将请求转发到另一个资源的RequestDispatcher对象。
  • getRealPath(String path):返回指定虚拟路径的真实路径。
  • getRequestURI():返回请求的URI,不包括查询字符串。
  • getRequestURL():返回请求的URL,包括协议,服务器名称,端口号和请求URI,但不包括查询字符串。
  • getServletPath():返回Servlet的路径。
  • getSession():返回与此请求相关联的会话,如果请求没有会话,则创建一个新会话。
  • getSession(boolean create):返回与此请求相关联的会话,如果请求没有会话,则根据指定的create参数创建一个新会话或不创建。
  • isRequestedSessionIdValid():返回请求的会话ID是否仍然有效。
  • isRequestedSessionIdFromCookie():返回请求是否使用Cookie来检索会话ID。
  • isRequestedSessionIdFromURL():返回请求是否将会话ID附加到URL中。
  • isRequestedSessionIdFromUrl():已过时的方法,等效于isRequestedSessionIdFromURL()。

HttpServletRequest

在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest 专门用于封装 HTTP 请求消息,该接口在ServletRequest接口的基础上增加了许多HTTP特定的方法,以提供更多的HTTP请求和响应相关的信息。部分新增信息如下:

  • getMethod():返回HTTP请求的方法类型(GET、POST等)。
  • getPathInfo():返回HTTP请求的路径信息。
  • getPathTranslated():返回HTTP请求的路径翻译后的信息。
  • getQueryString():返回HTTP请求的查询字符串。
  • getContentLength():返回HTTP请求的主体内容长度。
  • getContentType():返回HTTP请求的主体内容类型。
  • getServletPath():返回HTTP请求的Servlet路径。
  • getRequestURI():返回HTTP请求的统一资源标识符(URI)。
  • getRequestURL():返回HTTP请求的统一资源定位器(URL)。
  • getProtocol():返回HTTP请求的协议名称和版本号。
  • getRemoteAddr():返回HTTP请求的客户端IP地址。
  • getRemoteHost():返回HTTP请求的客户端主机名。
  • getServerName():返回HTTP请求的服务器名称。
  • getServerPort():返回HTTP请求的服务器端口号。
  • getScheme():返回HTTP请求使用的协议名称(http、https等)。
  • isSecure():返回HTTP请求是否通过安全套接字层(SSL)进行传输。

URI和URL的区别

  • URI(Uniform Resource Identifier,统一资源标识符)是一个标识某个资源的字符串,可以用来唯一地标识一个资源,包括但不限于Web页面、图片、文本文件等。URI包括两个部分:URL和URN。URN(Uniform Resource Name,统一资源名称)是通过名字来标识资源的。
  • URL(Uniform Resource Locator,统一资源定位符)则是通过地址来标识资源的,即URL是一种特定类型的URI,它通过指定地址来标识特定的资源。例如,"https://www.example.com/index.html"是一个URL,它指定了要访问的资源的地址和协议。

因此,**URL是URI的一个子集,所有的URL都是URI,但不是所有的URI都是URL。URI还可以表示一些没有直接关联到网络资源的抽象概念,例如一个人的名字或者一份文档的版本号。**而URL则是用来指定如何访问Web资源的字符串,包括协议、主机名、端口号、路径和查询参数等。

Tomcat 中创建 HttpServletRequest

在 Tomcat 中,HttpServletRequest 对象的创建是由 Catalina 处理请求的核心组件 org.apache.catalina.connector.Connector 负责的。具体来说,当 Connector 接收到客户端请求时,会创建 Request 对象(该对象封装了 HttpServletRequest 对象)并将其传递给 Tomcat 的管道处理器 Pipeline 进行处理。Pipeline 中会将 Request 对象传递给多个阶段的处理器(Valve),在每个阶段中对 Request 对象进行处理并执行相应的操作(如安全认证、过滤器等),最终将 Request 对象传递给对应的 Servlet 进行业务逻辑处理。

具体创建 HttpServletRequest 对象的源码如下所示:

@Override
public void service(SocketWrapperBase<?> socket) throws IOException {// ...// 创建 Request 对象并将其封装到 Processor 实例中Http11Processor processor = createProcessor();processor.assign(socket);if (proto.isSSLEnabled() && (socket instanceof SecureNio2Channel)) {SecureNio2Channel channel = (SecureNio2Channel) socket;SSLEngine engine = proto.getSSLEngine();if (engine != null) {channel.reset(engine);}}// 将请求交给 Pipeline 处理器进行处理pipeline.getFirst().invoke(processor.getRequest(), processor.getResponse());// ...
}

从上述代码中可以看出,当接收到客户端请求时,Tomcat 会通过 createProcessor 方法创建 Http11Processor 实例,并将 SocketWrapperBase 作为参数传递给该实例。在 Http11Processor 中,会调用 createRequest 方法创建 Request 对象,并将 SocketWrapperBase 和 Http11InputBuffer 封装到 Request 对象中。最终,Tomcat 将 Request 对象作为参数传递给 Pipeline 处理器进行处理。在 Pipeline 中,会将 Request 对象传递给多个 Valve 进行处理,最终将 Request 对象传递给对应的 Servlet 进行业务逻辑处理。

Servlet接收请求中创建的对象

  • HttpServletRequest 对象:封装了客户端请求的信息,包括请求参数、请求头、请求体等信息。
  • HttpServletResponse 对象:封装了响应信息,包括响应状态码、响应头、响应体等信息。
  • ServletContext 对象:代表 Servlet 上下文,可以用于在不同 Servlet 之间共享数据。
  • HttpSession 对象:代表客户端的会话,可以用于在同一客户端多次请求之间共享数据。
  • ServletConfig 对象:代表 Servlet 的配置信息,包括 Servlet 的初始化参数等信息。
  • ServletRequest 对象:是 HttpServletRequest 的父接口,定义了通用的请求方法,如获取请求参数等。
  • ServletResponse 对象:是 HttpServletResponse 的父接口,定义了通用的响应方法,如设置响应头等。

以上对象都是由 Servlet 容器在接收到客户端请求时创建的,可以在 Servlet 中直接使用。其中,HttpServletRequest 和 HttpServletResponse 对象是每个请求独有的,而 ServletContext 和 HttpSession 对象则是在多个请求之间共享的。
这就是为什么springboot中可以直接获取这两个对象,这两个对象不需要传入。

需要注意的是,具体创建对象的方式可能因 Servlet 容器而异。例如,在 Tomcat 中,HttpServletRequest 和 HttpServletResponse 对象是由 Catalina 处理请求的核心组件 org.apache.catalina.connector.Connector 负责创建的,而 ServletContext 和 HttpSession 对象则是由 org.apache.catalina.core.StandardContext 创建的。

接口中怎么使用

@RequestMapping("name2")
public Object task2() {log.info("start");RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();System.out.println(request.getHeader("Host"));return name2;
}
@RequestMapping("name2")
public Object task2( HttpServletRequest request, HttpServletResponse response) {log.info("start");System.out.println(request.getHeader("Host"));return name2;
}
@Autowired
HttpServletRequest request;@RequestMapping("name2")
public Object task2() {log.info("start");System.out.println(request.getHeader("Host"));return name2;
}

以上伪代码的作用是一致的,无论在接口上写参数还是方法内创建还是自动注入,都不会影响调用者,因为这两个对象是Servlet创建和销毁的,可以直接使用。

spring中直接注入HttpServletRequest

spring中居然可以将HttpServletRequest直接通过@Autowired注入,突然有点懵。

  • HttpServletRequest并非Spring中的类,且在没有手动通过@Bean的方式注入,Spring是怎么做到帮开发者完成注入的?理论上,我们需要注入其他包中的对象的时候,是必须在@Configuration修饰的类下面使用@Bean进行方法修饰的才行的

    @Configuration
    public class ApplicationConfig {@Beanpublic RestTemplate getRestTemplate(){return new RestTemplate();}
    }
    
  • 同时,ioc容器中默认注入的Bean是单例,而每个请求都是独立的,这样不会出问题吗?

demo分析

@RestController
public class HttpServletRequestTest {@Autowiredprivate HttpServletRequest httpServletRequest;@GetMapping("/sayHi")public void sayHi(String name) {System.out.println(httpServletRequest.getRequestURL().toString());JSONObject res = new JSONObject();res.put("requestId", UUID.randomUUID().toString());res.put("datatime", DateUtils.getDatetime());// ReturnResult.get(res);System.out.println("hello: " +  name);}@PostConstructpublic void after(){System.out.println(this.httpServletRequest);}}
  • @PostConstruct:后构造注解,见名知意,标注于方法之上,在对象加载完依赖注入后执行,常用于初始化连接源等信息。是java的注解。在Servlet生命周期中有一定作用,它通常都是一些初始化的操作,但初始化可能依赖于注入的其他组件,所以要等依赖全部加载完再执行。
  • @PreDestroy:前销毁注解,同理后构造
  • 在spring项目中,在一个bean的初始化过程中,方法执行先后顺序为Constructor > @Autowired > @PostConstruct > @PreDestroy

Spring不是只能自动注入被管理的对象吗?

作为一个外部对象,HttpServletRequest为什么可以在Spring项目中通过注入的方式获取?

@PostConstruct注解被用在执行完依赖注入之后的方法调用上,我们将断点打在上述demo的第19行,即可查看HttpServletRequest httpServletRequest实例化之后的情况。

在这里插入图片描述
由上图我们可以看到这个httpServletRequest对象是一个代理对象(org.springframework.web.context.support.WebApplicationContextUtils.RequestObjectFactory),该对象是一个请求的对象工厂。进入WebApplicationContextUtils这个类,Command + F12我们发现了一个往 ConfigurableListableBeanFactory工厂对象注入bean对象的方法registerWebApplicationScopes。

该方法有这样一行代码:

beanFactory.``registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()``);

由于HttpServletRequest正是继承自ServletRequest,这里引起了我们的关注。
在这里插入图片描述
ConfigurableListableBeanFactory的registerResolvableDependency方法又是用什么的呢?我们继续往下看。
在这里插入图片描述
使用相应的自动装配值注册一个特殊的依赖类型。
这适用于被认为可自动装配但未在工厂中定义为 bean 的工厂/上下文引用

原来Spring可以为一个类注入另一个完全不同的对象值,这样从ioc容器中引用这个类的时候其实拿到的就是这个对象值。且上面的描述正好回应了,为什么我们没有手动定义HttpServletRequest却可以完成它的自动装配,秘诀就在这里。

进一步拓展思考,上面两张图一起看,除了ServletRequest.class,ServletResponse.class,HttpSession.class以及WebRequest.class类型对象,均被Spring自动注入,可以直接通过注解的方式引用。

继续进入registerResolvableDependency方法,我们发现该方法的实现是将ServletRequest.class的依赖类型作为key, RequestObjectFactory作为装配的value,放入了resolvableDependencies这个map中。
在这里插入图片描述

Spring中的对象不是单例吗?

HttpServletRequest注入和引用我们知道了,那么针对每个独立的请求,多线程场景下,通过自动注入的方式,HttpServletRequest 是否会有线程安全的问题呢?

我们已经知道注入拿到的HttpServletRequest返回的对象其实是下面这个

org.springframework.web.context.support.WebApplicationContextUtils.``RequestObjectFactory对象,那么它是怎么做到线程安全的呢?

我们看它的具体实现。

在这里插入图片描述
沿着currentRequestAttributes()方法一路点击,最终发现它的返回值,是来自org.springframework.web.context.request.RequestContextHolder#requestAttributesHolder。

在这里插入图片描述
requestAttributesHolder对象是一个ThreadLocal对象,由此我们明白了,Spring自动注入的HttpServletRequest能够保证请求的唯一性,原来是通过跟每个线程绑定了,从ThreadLocal中取得请求信息,由此保证的线程安全!

我们再来拓展一下,既然请求信息是从ThreadLocal中取的,那么请求信息是如何放进去的呢?

我们找到requestAttributesHolder属性的set方法,在这里打一个断点,重启系统,并发起一个http请求。
在这里插入图片描述
最终,通过调用堆栈信息,我们看到了org.springframework.web.filter.RequestContextFilter#doFilterInternal
中调用了initContextHolder方法,而initContextHolder方法调用了requestAttributesHolder这个ThreadLocal的set方法。

每个http请求过来会进入RequestContextFilter这个filter,在这个filter中会将request信息设置到当前的线程里。

总结

  • 在代码中通过注解注入HttpServletRequest的方式,拿到的其实并不是真正的 HttpServletRequest,而是一个Spring项目启动时自动注入的代理对象org.springframework.web.context.support.``WebApplicationContextUtils.RequestObjectFactory。
    该对象跟ServletRequest.class做了映射关联,放入了Spring管理bean注入的map中。

    private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {@Overridepublic ServletRequest getObject() {// 获取当前 ServletRequestreturn currentRequestAttributes().getRequest();}@Overridepublic String toString() {return "Current HttpServletRequest";}}private static ServletRequestAttributes currentRequestAttributes() {RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();if (!(requestAttr instanceof ServletRequestAttributes)) {throw new IllegalStateException("Current request is not a servlet request");}return (ServletRequestAttributes) requestAttr;}
    }// 那这个“当前 ServletRequest”从哪来呢?
    //Servlet 除了 ServletContextListener 之外,还有一个 ServletRequestListener:public interface ServletRequestListener extends EventListener {void requestDestroyed(ServletRequestEvent var1);void requestInitialized(ServletRequestEvent var1);
    }
    //只要你注册了这个,就能在请求前执行requestDestroyed
    //Spring 弄了一个 org.springframework.web.context.request.RequestContextListener,在这个里面获取并存储的@Overridepublic void requestInitialized(ServletRequestEvent requestEvent) {if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {throw new IllegalArgumentException("Request is not an HttpServletRequest: " + requestEvent.getServletRequest());}HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();ServletRequestAttributes attributes = new ServletRequestAttributes(request);request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);LocaleContextHolder.setLocale(request.getLocale());// 存储 ServletRequestRequestContextHolder.setRequestAttributes(attributes);}
    
  • 每次请求时,如何保证自动注入的HttpServelet请求线程安全,等价于问 org.springframework.web.context.support.WebApplicationContextUtils.``RequestObjectFactory 怎么做到的线程安全。这个类只是一个简单的对象工厂,getObject方法最终从org.springframework.web.context.request.RequestContextHolder#requestAttributesHolder这个ThreadLocal中获取请求的信息,由此做到了请求之间的隔离。

  • 其实spring中还有很多类可以直接注入:import org.springframework.cloud.client.discovery.DiscoveryClient。

  • 直接注入和需要@Bean修饰之后才能注入的区别:一个是内部实现好了,默认已经放进去了;一个是我们业务需求自己放进去的,也就是你要把这个bean交给spring管理,这就是spring ioc 控制反转。

  • 特殊情况特殊处理。不要把ioc死板的搬过来。Request, Response, HttpEntity等都是特殊处理的。而且这几个对象和请求有关,不在窗口里面。

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

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

相关文章

linux中的调试工具gdb

目录 1.背景知识补充 2.使用 知识补充 1.背景知识补充 1.gcc下编译默认是release方式发布的&#xff0c;无法直接进行调试 如果要以debug方式发布&#xff0c;需要携带-g 可以使用grep查询 因为携带debug信息&#xff0c;其文件体积要大一些 2.使用 1.gdb 可执行程序 …

北邮《计算机网络》网络层笔记

文章目录 单词复习网络层前言路由算法&#xff08;构造路由表的算法&#xff09;静态路由算法自适应算法 拥塞控制QoS 服务质量&#xff08;小小的一节&#xff09;网络互联&#xff08;还是小小的一节&#xff09;Internet 单词复习 estimates boot off-line in advance refl…

【PyTorch单点知识】神经元网络模型剪枝prune模块介绍(上,非结构化剪枝)

文章目录 0. 前言1. 剪枝prune主要功能分类2. torch.nn.utils.prune中的方法介绍3. PyTorch实例3.1 BasePruningMethod3.2PruningContainer3.3 identity3.4random_unstructured3.5l1_unstructured 4. 总结 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己…

AI办公自动化:免费批量将英语电子书转成有声书

Edge-TTS是由微软推出的文本转语音Python库&#xff0c;通过微软Azure Cognitive Services转化文本为自然语音。可以作为付费文本转语音TTS服务的替代品&#xff0c;Edge-TTS支持40多种语言和300种声音&#xff0c;提供优质的语音输出 。 edge-tts支持英语、汉语、日语、韩语、…

基于Netron库的PyTorch 2.0模型可视化

【图书推荐】《从零开始大模型开发与微调&#xff1a;基于PyTorch与ChatGLM》_《从零开始大模型开发与微调:基于pytorch与chatglm》-CSDN博客 前面章节带领读者完成了基于PyTorch 2.0的MNIST模型的设计&#xff0c;并基于此完成了MNIST手写体数字的识别。此时可能有读者对我们…

C语言结构体包含结构体

C语言结构体可以包含另一个结构体&#xff1b; 下面通过一个例子看一下&#xff1b; struct Date {int day;int month;int year; };struct Person {char *name;struct Date birthday; }; ...... void CTestView::OnDraw(CDC* pDC) {CTestDoc* pDoc GetDocument();ASSERT_VAL…

C语言 | Leetcode C语言题解之第189题轮转数组

题目&#xff1a; 题解&#xff1a; void swap(int* a, int* b) {int t *a;*a *b, *b t; }void reverse(int* nums, int start, int end) {while (start < end) {swap(&nums[start], &nums[end]);start 1;end - 1;} }void rotate(int* nums, int numsSize, int…

国内邮件推送如何避免拦截?内容优化技巧?

国内邮件推送的平台怎么选择&#xff1f;如何提高邮件推送效果&#xff1f; 邮件营销是企业与客户沟通的重要方式&#xff0c;但在国内邮件推送过程中&#xff0c;邮件被拦截的问题屡见不鲜。为了确保邮件能够顺利送达目标用户&#xff0c;AokSend将探讨一些有效的策略&#x…

【Android】实现图片和视频混合轮播(无限循环、视频自动播放)

目录 前言一、实现效果二、具体实现1. 导入依赖2. 布局3. Banner基础配置4. Banner无限循环机制5. 轮播适配器6. 视频播放处理7. 完整源码 总结 前言 我们日常的需求基本上都是图片的轮播&#xff0c;而在一些特殊需求&#xff0c;例如用于展览的的数据大屏&#xff0c;又想展…

跟着DW学习大语言模型-什么是知识库,如何构建知识库

建立一个高效的知识库对于个人和组织来说非常重要。无论是为了个人学习和成长&#xff0c;还是为了组织的持续创新和发展&#xff0c;一个完善的知识管理系统都是不可或缺的。那么&#xff0c;如何建立一个高效的知识库呢&#xff1f; 在建立知识库之前&#xff0c;首先需要确定…

第3章 小功能大用处-事务与Lua

为了保证多条命令组合的原子性&#xff0c;Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题。 首先简单介绍Redis中事务的使用方法以及它的局限性&#xff0c;之后重点介绍Lua语言的基本使用方法&#xff0c;以及如何将Redis和Lua脚本进行集成&#xff0c;最后给出Red…

项目实训-vue(十三)

项目实训-vue&#xff08;十三&#xff09; 文章目录 项目实训-vue&#xff08;十三&#xff09;1.概述2.处理按钮 1.概述 本篇博客将记录我在图片上传页面中的工作。 2.处理按钮 实现了图片的上传之后&#xff0c;还需要设置具体的上传按钮。 这段代码使用 Element UI 的 …

Spring学习02-[Spring容器核心技术IOC学习]

Spring容器核心技术IOC学习 什么是bean?如何配置bean?Component方式bean配合配置类的方式import导入方式 什么是bean? 被Spring管理的对象就是bean,和普通对象的区别就是里面bean对象里面的属性也被注入了。 如何配置bean? Component方式、bean配合配置类的方式、import…

C语言 | Leetcode C语言题解之第190题颠倒二进制位

题目&#xff1a; 题解&#xff1a; const uint32_t M1 0x55555555; // 01010101010101010101010101010101 const uint32_t M2 0x33333333; // 00110011001100110011001100110011 const uint32_t M4 0x0f0f0f0f; // 00001111000011110000111100001111 const uint32_t M8…

【containerd】Containerd高阶命令行工具nerdctl

前言 对于习惯了使用docker cli的用户来说&#xff0c;containerd的命令行工具ctr使用起来不是很顺手&#xff0c;此时别慌&#xff0c;还有另外一个命令行工具项目nerdctl可供我们选择。 nerdctl是一个与docker cli风格兼容的containerd的cli工具。 nerdctl已经作为子项目加入…

秋招突击——6/24——复习{完全背包问题——买书,状态转换机——股票买卖V}——新作{两数相除,LRU缓存实现}

文章目录 引言复习完全背包问题——买书个人实现 状态转换机——股票买卖V个人实现参考实现 新作两数相除个人实现 新作LRU缓存实现个人实现unordered_map相关priority_queue相关 参考实现自己复现 总结 引言 今天知道拼多多挂掉了&#xff0c;难受&#xff0c;那实习就是颗粒无…

汪汪队短视频:成都柏煜文化传媒有限公司

汪汪队短视频&#xff1a;萌宠与冒险的交织乐章 在数字时代的浪潮中&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;迅速占领了人们的闲暇时光。而在这些琳琅满目的短视频中&#xff0c;有一类作品以其独特的魅力吸引了无数观众的目光&#xff0c;那就是以萌宠为…

单门户上集成多种数据库查询入口

&#xff08;作者&#xff1a;陈玓玏&#xff09; 开源项目&#xff0c;欢迎star哦&#xff0c;https://github.com/tencentmusic/cube-studio 在一家公司&#xff0c;我们通常会有多种数据库&#xff0c;每种数据库因为其特性承担不同的角色&#xff0c;比如mysql这种轻量…

AI-024人工智能指数报告(三):经济

概述 人工智能融入经济会引发许多很迷人的问题。有人预测人工智能会推动生产力得到改进&#xff0c;但其影响程度仍未确定。其中一个主要关切是大规模劳动替代的可能性——工作究竟会在多大程度上被自动化还是人工智能主要起到增强作用&#xff1f;各个行业的企业已经在用各种…

基于FPGA的温湿度检测

初始化部分就不过多赘述&#xff0c;我会给出对应的文件&#xff0c;我只说明这部分里面涉及到使用的代码部分 1、数据的读取和校验 数据的读取和检验代码如下 always (posedge clk_us)if (data_temp[7:0] data_temp[39:32] data_temp[31:24] data_temp[23:16] data_te…