Servlet 详解

news2024/10/7 14:30:57

目录

什么是 servlet?

Servlet 是做甚的?

如何编写一个 Servlet 程序?

解析访问出错情况

Servlet 的运行原理

1. 接收请求

2. 根据请求计算响应

3. 返回响应

Servlet API 详解

HTTPServlet

HttpServletRequset

HttpServletResponse


什么是 servlet?

Servlet 是一种实现动态页面的技术, 是一组 Tomcat(一个HTTP服务器) 提供给程序员的一种 API , 帮助程序员简单高效的开发一个 web app

Servlet 也是是一些遵从Java Servlet API的Java类,这些Java类可以响应请求。尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求。 Servlet必须部署在Java servlet容器才能使用。

总的来说, servlet是完成 java Web 中处理请求和发送响应过程的一种程序,是为了解决实现动态页面的技术而衍生的东西 

Servlet 是做甚的?

  • 允许程序员注册一个类, 在 Tomcat 收到的某个特定的请求的时候, 执行这个类中的一些代码

  • 帮助程序员解析 HTTP 请求, 把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象

  • 帮助程序员构造 HTTP 响应, 程序员只要给指定的 HttpResponse 对象填写一些属性字段, Servlet 就会自动的按照 HTTP 协议的方式构造出一个 HTTP 响应字符串, 并通过 Socket 写回给客户端

如何编写一个 Servlet 程序?

  1. 创建项目

    1. 先创建一个 Maven 项目

    2. 创建完毕弹出 一个对话框 选择 Enable Auto-Import

  2. 引入依赖

  • 会自动生成一个 pom.xml 文件
  • 我们需要在 pom.xml 中引入 Servlet 依赖的 jar 包 (3.1.0)

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    
  • Servlet 的版本要和 Tomcat 的版本匹配

Groupld : 组织名称

Artifactld : 项目名称

Version : 表示版

3. 创建目录

  • 目录介绍

    • Src : 源代码所在的目录

    • main/java :源代码的根目录, 后续创建 .Java 文件就放到这个目录中

    • main/resources : 表示项目的一些资源文件所在的目录

    • test/java : 表示测试代码的根目录

  1. 创建 webapp 目录 (在 main 目录下) : 存放以下静态文件 HTML , CSS

  2. 创建 WEB-INF 目录(webapp下) 并创建一个  web.xml 写入以下代码

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>  

4. 编写代码

 

// 2.
@WebServlet("/hello")

//1. 
public class HelloServlet extends HttpServlet {

    @Override
    //doGet就是 根据请求计算响应           req 请求                    resp响应
    // 3.
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // super.doGet(req, resp);  //直接返回错误
        //这是在服务器的控制台中, 打印了字符串.(服务器看到了, 客户端看不到)
        System.out.println("hello world!");
        // 这是在 resp 的 body 中写入 hello world 字符串,这是内容就会被 HTTP 响应返回给浏览器, 显示到浏览器页面上
        resp.getWriter().write("hello world!!");
    }
    }

此时代码就可以进行运行了, 但是现在不是使用 main 作为程序的入口, mian 方法现在会包含在 Tomcat 中, 这个代码 Tomcat 会在合适的时期进行调用

这个代码只是 Tomcat 中的一小部分逻辑

  • 要想被调用, 就得满足以下这三个条件

    • 创建类的时候需要继承自 HttpServlet

    • 需要使用 @WebServlet 注解, 加上一个 HTTP路径 ("/路径名")

    • 实现 doXXX 方法

5. 打包程序​​​​​​​

要打成 war 类型的包, war 类型的包才能被 Tomcat 识别到

要想打包为 war 包,就必须进行配置, 一般情况下默认是 jar 包

<!--    //描述打包的文件是war类型-->
    <packaging>war</packaging>
    //描述包名
    <build>
        <finalName>hello_servlet</finalName>
    </build>
  • war 包和 jar 包的区别

        jar 包是普通的 java 程序打包的结果. 里面会包含一些 .class 文件. war 包是 java web 的程序, 里面除了会包含 .class 文件之外, 还会包含 HTML, CSS, JavaScript, 图 片, 以及其他的 jar 包. 打成 war 包格式才能被 Tomcat 识别

  • 完整的 pom.xml 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Servlet</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.1</version>
        </dependency>

    </dependencies>
<!--    //描述打包的文件是war类型-->
    <packaging>war</packaging>
    <build>
        <finalName>hello_servlet</finalName>
    </build>
</project>

6. 部署程序

把 war 包拷贝到 Tomcat 的 webapps 目录下 ,启动

然后启动 Tomcat 就会自动解压缩 war 包

7. 验证程序

在浏览器中输入以下链接就可以进行打开运行 servlet 程序了

127.0.0.1:8080/hello_servlet(context 路径)/hello()

使用 IDEA 插件 smartTomcat 进行 部署

安装 Tomcat 插件

配置 smartTomcat

使用 Tomcat 插件省去了 打包 和 部署 两个步骤, 可以一键运行servlet程序 

 

解析访问出错情况

  • 404

表示用户访问的资源不存在, 大概就是 URL 的路径写的不正确

例如: 少些了 Context Path 或者是 Servlet Path

  • 405

表示对应的 HTTP 请求方法没有实现

例如: 没有实现 doGet 方法

  • 500

Servlet 代码中抛出异常导致的

  • 空页面

没有 resp.getWritter().write() 操作

响应 body 中的数据就是空数据

  • 无法访问此网站

一般情况下就是 Tomcat 启动失败了

注解 @WebServlet("/xxx") 中的 / 一定得注意写上

作为一个程序员不光要写出好的代码, 还得要很高效的调试代码

Servlet 的运行原理

Servlet 中没有 main 方法他是怎么运行的?

  • Tomcat 通过 Socket 读取到这个请求(一个字符串). 并按照 HTTP 请求的格式来解析这个请求, 根据请求中的 Context Path 确定一个 webapp, 再通过 webapp ,再通过 Servlet Path 确定一个具体的类, 再根据当亲请求的方法(GET/POST/...), 决定调用这个类的 doGet 或者 doPost 等方法, 此时我们的代码中的 doGet / doPsot 方法的第一个参数 HttpServletRequest  就包含了这个 HTTP 请求的详细信息

下面是详细的 servlet 的基本运行原理

1. 接收请求

  • 用户在浏览器中输入一个 URL , 此时浏览器就会构造出一个 HTTP 请求
  • 这个 HTTP 请求会经过网络协议栈逐层进行 封装 成二进制 bit 流, 最终通过物理层的硬件设备转换成光信号/电信号传输出去
  • 这些承载信息的光信号/电信号, 通过互联网上的一系列网络设备, 最终到达目标主机(网络层 和 数据链路层 参与)
  • 服务器主机收到这些光信号/电信号.,又会通过网络协议栈逐层进行 分用, 层层解析, 最终还原成 HTTP 请求, 交给 Tomcat 进程进行处理(根据端口号确定进程)
  • Tomcat 通过 Socket 读取到这个请求(一个字符串). 并按照 HTTP 请求的格式来解析这个请求, 根据请求中的 Context Path 确定一个 webapp, 再通过 webapp ,再通过 Servlet Path 确定一个具体的类, 再根据当亲请求的方法(GET/POST/...), 决定调用这个类的 doGet 或者 doPost 等方法, 此时我们的代码中的 doGet / doPsot 方法的第一个参数 HttpServletRequest  就包含了这个 HTTP 请求的详细信息

2. 根据请求计算响应

  • 在我们的 doGet / doPost 方法中, 就执行到了我们自己的代码, 我们自己的代码会根据请求中的一些信息, 来给 HttpServletResponse 对象设置一些属性, 例如状态码, header , body 等

3. 返回响应

  • 我们的 doGet / doPost  执行完毕后, Tomcat 就会自动把 HttpServletResponse 这个我们刚好设置好的对象转换成一个符合 HTTP 协议的字符串, 通过 Socket 把这个响应发送出去
  • 此时响应数据在服务器的主机上,通过网络协议栈进行层层封装成 bit  流, 通过物理层硬件设备转换为光信号/电信号传输出去
  • 这些承载信息的光信号/ 电信号通过互联网的一系列网络设备, 最终到达浏览器所在的主机(这个过程需要网络层 和 数据链路层 参与)
  • 浏览器主机收到这些光信号/电信号, 又会通过网络协议栈逐层进行 分用,层层解析, 最终还原成 HTTP 响应, 并交给浏览器处理
  • 浏览器也通过 Socket 读到这个响应(一个字符串), 按照 HTTP 响应的个数来解析这个响应, 并且把 body 中的数据按照一定得格式显示在浏览器的界面上

Servlet API 详解

HTTPServlet

写 Servlet 代码的时候, 第一步就是 创建类, 继承自 HttpServlet , 并重写其中的某些方法

核心方法

方法名称

调用时机

init

在 HTTPServlet 实例化之后被调用一次

destory

在 HttpServlet 实例不再使用的时候调用一次

service

收到 HTTP 请求的时候调用

doGet

收到 GET 请求的时候调用(由 service 方法调用)

doPost

收到 Post 请求的时候调用(由 service 方法调用)

doPut/doDelete/doOptions

收到其他请求的时候调用(由 service 方法调用)

代码示例: 处理 GET 请求

@WebServlet("/hello")

public class HelloServlet extends HttpServlet {

    @Override
    //doGet就是 根据请求计算响应           req 请求                    resp响应
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // super.doGet(req, resp);  //直接返回错误
        //这是在服务器的控制台中, 打印了字符串.(服务器看到了, 客户端看不到)
        System.out.println("hello world!");
        // 这是在 resp 的 body 中写入 hello world 字符串,这是内容就会被 HTTP 响应返回给浏览器, 显示到浏览器页面上
        resp.getWriter().write("hello world!!");
    }
}

 

代码示例: 处理 POST 请求

@WebServlet("/hello")

public class HelloServlet extends HttpServlet {

    @Override
    //doGet就是 根据请求计算响应           req 请求                    resp响应
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // super.doPost(req, resp);  //直接返回错误
        //这是在服务器的控制台中, 打印了字符串.(服务器看到了, 客户端看不到)
        System.out.println("dopost");
    }
}

使用 PostMan 发送请求对应的结果

 

HttpServletRequset

当 Tomcat 通过 Socket API 读取到 HTTP 请求(字符串), 并且按照 HTTP 协议的格式把字符解析为 HttpServletRequest 对象 核心方法

方法

描述

String getprotocol()

返回请求协议的名称和版本

String getMethod()

返回请求的 HTTP 方法的名称, 例如, GET. POST 或者 PUT

String getRequestURL()

返回该请求的一部分 URL

String getContextPath()

返回 ContentPath

String getQueryString()

返回包含在路径后的请求 URL 中的查询字符串

Enumeration getParaeterNames()

返回一个 String 对象的枚举, 包含在该请求中包含的参数的名称

String getParameter(String name)

以字符串形式返回请求参数的值, 或者如果参数不存在则返回 null

Enumeration getHeaderNames()

返回一个枚举, 包含在该请求中包含的所有头名

String getHeader(String name)

以字符串形式返回指定的请求头的值

String getChatacterEncoding()

返回请求主体中使用的字符编码的名称

String getContentTyoe()

返回请求主体的 MIME 类型, 如果不知道则返回 null

Int getContentLength()

以字节为单位返回请求主体的长度, 并提供输入流, 或者如果长度未知则返回 -1

InputStream getInputStream()

用于读取请求的 body 内容,返回一个 InputStream 对象

上面的方法可以 获取 到一个请求中的各个方面的信息

注意: 请求对象是服务器收到的内容, 不应该修改, 因此上面的方法也都只是 "读" 方法, 而不是 "写" 方法

代码示例:

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/showRequest")
public class ShowRequest extends HelloServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder result = new StringBuilder();
        //获取请求的协议的名称和版本
        result.append(req.getProtocol());
        result.append("<br>");
        //返回请求的HTTP方法的名称
        result.append(req.getMethod());
        result.append("<br>");
        //获取 URL 的一部分, 唯一资源标识符
        result.append(req.getRequestURI());
        result.append("<br>");
        //获取 URL
        result.append(req.getRequestURL());
        result.append("<br>");
        //获取 contextPath
        result.append(req.getContextPath());
        result.append("<br>");
        //获取 servletPath
        result.append(req.getServletPath());
        result.append("<br>");
        //获取包含在路径后的请求 URL 中的查询字符串
        result.append(req.getQueryString());
        result.append("<br>");
        //返回一个枚举, 包含在该请求中包含的所有头名
        result.append(req.getHeaderNames());
        result.append("<br>");
        //获取一 String 对象的枚举, 包含在该请求中包含的参数的名称
        //result.append(req.getParameterValues(""));
        //以字符串的形式返回指定的请求头的值
        //result.append(req.getHeader());
        result.append("==========================<br>");

        //创建枚举进行接收, 所有的header
        Enumeration<String> headerNames = req.getHeaderNames();
        //循环读取枚举中的数据
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValues = req.getHeader(headerName);
            result.append(headerName + ": " + headerValues + "<br>");
        }

        //在响应中设置 body 的类型, 方便浏览器进行解析
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write(result.toString());

    }
}

 

代码示例 : 获取 GET 请求中的参数

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/getParameter")
public class GetParameter extends HelloServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //前端通过 url 的 query string 传递 username 和 password 两个属性
        String username = req.getParameter("username");
        if(username == null) {
            System.out.println("username 这个属性在 query string 中不存在");
        }
        String password = req.getParameter("password");
        if(password == null) {
            System.out.println("password 这个属性在 query string 中不存在");
        }
        System.out.println("username = " + username + "  password = " + password );
        resp.getWriter().write("ok");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //给请求设置字符编码 //告诉服务器字符编码
        req.setCharacterEncoding("utf8");
        //前端通过 body 以 form 表单的形式把 username 和 password 传给服务区
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null) {
            System.out.println("username 这个 key 在 body 中不存在");
        }
        if(password == null) {
            System.out.println("password 这个 key 在 body 中不存在");
        }

        System.out.println("username= "+ username + "  password= " + password);
        resp.getWriter().write("ok");
    }


}

当没有使用 query String 方法传递值的时候, getParameter 的时候,获取的值为 null

​​​​​​​

使用之后, 此时说明服务器已经获取到客户端传递过来的参数

 

HttpServletResponse

        Servlet 中的 doXX 放法的目的就是根据请求计算得到响应, 然后把响应的数据设置到 HttpServletResponse 对象中然后 Tomcat  就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串,并通过 Socket 写回给浏览器

核心方法

方法

描述

Void setStatus(int sc)

为该响应设置状态码

void setHeader(String name,String value)

设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值.

void addHeader(String name, String value)

添加一个带有给定的名称和值的 header. 如果 name 已经存在,不覆盖旧的值, 并且添加新的键值对

void setContentType(String type)

设置被发送到客户端的响应的内容类型。

Void setCharacterEncoding(String charset)

设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。

void sendRedirect(String location)

使用指定的重定向位置 URL 发送临时重定向响应到客户端。

PrintWriter getWriter()

用于往 body 中写入文本格式数据.

OutputStream getOutputStream()

用于往 body 中写入二进制格式数据.

展示常用方法的代码及运行截图

代码示例: 设置状态码

@WebServlet("/status")
public class StatusServlet extends HelloServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(200);
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("返回 200 响应!");
    }
}

 

 

代码示例 : 自动刷新

@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //每隔 1s 刷新一次
        resp.setHeader("Refresh","1");
                                           //获取毫秒级别的时间戳
        resp.getWriter().write("time = " + System.currentTimeMillis());
    }
}

         

每隔一秒进行刷新, 这里是 过了很多秒截的图

 对时间进行格式化输出

@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //每隔 1s 刷新一次
        resp.setHeader("Refresh","1");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        resp.getWriter().write("time = " + format.format(System.currentTimeMillis()));
    }
}

 总结:

        Servlet是一个用于扩展服务器功能的Java编程语言类。它是一个服务器端组件,通过HTTP或HTTPS协议接收并响应来自客户端(通常是Web浏览器)的请求。

        Servlet通常用于构建动态Web应用程序。它提供了一种处理客户端请求、执行业务逻辑和生成动态内容(如HTML页面、XML、JSON或其他类型的数据)的方式。Servlet是Java Enterprise Edition(Java EE)平台的一部分,通常部署在Web服务器上。

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

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

相关文章

String模拟实现(二)

resize resize的特点是扩容加初始化&#xff0c;如果所给的长度小于空间大小就会删除多余的数据。前面我们实现了reserve&#xff0c;但有这样一个问题&#xff0c;如果reserve的长度小于空间就会导致缩容&#xff0c;而我们知道&#xff0c;string中缩容用的是shrink_to_fit&a…

外观设计模式解读

目录 问题引进 传统方式解决影院管理 外观模式基本介绍 概念 外观模式原理类图 分类外观模式的角色 外观模式解决影院管理 传统方式解决影院管理说明 外观模式应用实例 外观模式的注意事项和细节 s统的内部细节 > 外观模式 外观模式基本介绍 概念 1) 外观模式&…

XGBoost的介绍

一、XGBoost的介绍 1.什么是XGBoost&#xff1f; XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是一种基于梯度提升树的机器学习算法&#xff0c;它在解决分类和回归问题上表现出色。它是由陈天奇在2014年开发的&#xff0c;如今已成为机器学习领域中最流行和强…

集合框架知识汇总

集合框架 集合 概念&#xff1a;对象的容器&#xff0c;定义了对多个对象进行操作的常用方法。可以实现数组功能 和数组的区别 数组长度固定&#xff0c;集合长度不固定 数组可以存储基本类型和引用类型&#xff0c;集合只能存储引用类型 总结 List集合 有序&#xff0c;有…

软考网工易混淆知识点总结(持续更新中,按照知识点先后排序)

1.数据编码--原码、反码和补码 原码 数值前面增加了一位符号位(即最高位为符号位)&#xff0c;该位为0时表示正数&#xff0c;为1时则表示负数&#xff0c;其余各位表示数值的大小反码 正数的反码与原码相同&#xff0c;负数的反码符号位为1&#xff0c;其余各位为该数绝对值的…

大型语言模(LLM) : 提示词工程(一)

今天我学习了DeepLearning.AI的 Prompt Engineering 的在线课程&#xff0c;我想和大家一起分享一下该门课程的一些主要内容。 下面是我们访问大型语言模(LLM)的主要代码&#xff1a; import openaiopenai.api_key XXXXXXXXXdef get_completion(prompt, model"gpt-3.5-…

高性能分布式API网关Kong

目录 1 kong网关简介2 为什么需要 API 网关2.1 和Spring Cloud Gateway区别 3 为什么要使用kong3.1 kong的组成部分3.2 Kong网关的特性 4 kong网关架构4.1 Kong网关请求流程 5 kong 部署5.1 搭建网络5.2 搭建数据库环境5.3 kong网关部署5.3.1 初始化kong数据5.3.2 启动Kong容器…

【项目】树莓派4B镜像安装

本文主要记录下如何使用Raspberry Pi image 软件进行树莓派镜像进行安装。 官网&#xff1a;Raspberry Pi OS – Raspberry Pi 百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1G7z1Fdvk5Chmhj894WPU3A 提取码&#xff1a;xnzw 一、格式化SD卡 若SD卡存在…

释放潜能——解读新时代OEM竞争规则,打造精雕细琢的用户体验

从消费零售全领域的实践观察来看&#xff0c;仅仅凭借产品赢得竞争的时代已经过去&#xff0c;商业模式创新体现在越来越多企业向“产品服务”转变&#xff0c;向用户全生命周期需求挖掘转变。企业与消费者之间的关系从过去的一次性、断点式产品交易&#xff0c;转向持续性、覆…

读写ini配置文件(C++)

文章目录 1、为什么要使用ini或者其它(例如xml,json)配置文件&#xff1f;2、ini文件基本介绍3、ini配置文件的格式4、C读写ini配置文件5、 代码示例6、 配置文件的解析库 文章转载于&#xff1a;https://blog.csdn.net/weixin_44517656/article/details/109014236 1、为什么要…

基于 Web 和 Deep Zoom 的高分辨率大图查看器的实践

基于 Web 和 Deep Zoom 的高分辨率大图查看器的实践 高分辨率大图像在 Web 中查看可以使用 Deep Zoom 技术&#xff0c;这是一种用于查看和浏览大型高分辨率图像的技术&#xff0c;它可以让用户以交互方式浏览高分辨率大图像&#xff0c;并且能够在不影响图像质量的情况下进行…

搭建个人网站 保姆级教程(四)Navicat链接mySql 失败

长时间没有折腾云服务器上的mysql了&#xff0c;今天再次使用Navicat连接云服务器上的mysql时&#xff0c;输入密码报错&#xff01; 1130 - Host ‘119.130.212.168’ is not allowed to connect to this MySQL server 1.于是Royal TSX 远程服务器查看mysql的状态 systemctl …

通达信标记文字中可能用到的特殊符号大全

特殊符号是难以直接输入的符号&#xff0c;特殊符号是符号的一种&#xff0c;比如说圆圈&#xff08;〇&#xff09;、叉号&#xff08;✕、✖、✘&#xff09;、五角星&#xff08;★、☆&#xff09;、勾号&#xff08;✓、✔&#xff09; 。 01.特殊符号简表 ♠♣♧♡♥❤…

chatgpt赋能python:Python强制取整:如何在Python中正确进行取整操作

Python强制取整&#xff1a;如何在Python中正确进行取整操作 Python是一种广泛使用的编程语言&#xff0c;有许多不同的用途&#xff0c;包括数据分析、web开发、机器学习、科学计算等等。Python语言非常容易学习和使用&#xff0c;但有时候它的行为可能会出人意料&#xff0c…

alpa概览

文章目录 背景alpa简介DeviceMesh跨 DeviceMeshes 的 GPU Buffer管理Ray CollectivePipeline parallelism runtime orchestration运行时 背景 LLM训练有3D并行的需求&#xff08;alpa将数据并行视为张量并行&#xff0c;即张量沿batch切分&#xff09; 算子间并行的通信成本小…

【Vue】父子组件传参 孙子调用爷爷的方法 provide inject

一. 父传子 父组件先在data中定义要传给子组件的属性名父组件在中引入子组件在components中注册使用步骤 3 中注册好的子组件在 3 中&#xff0c;父传子 &#xff08;1&#xff09;利用 : 将父组件的对象、数组、字符串等传给子组件&#xff0c;供子组件使用 &#xff08;2&am…

Rocky Linux9安装教程

序言 Centos废了&#xff0c;最近在考虑将服务器迁移至Rockylinux系统&#xff0c;在这里记录下安装过程 当前安装版本RockyLinux9.2&#xff08;minimal版本&#xff09;&#xff0c;VMware Fusion专业版13.0.2 创建虚拟机 第一步&#xff1a; 先下载好ISO文件&#xff0c…

python-高级特性

文章目录 1.生成式2.生成器3.闭包4.装饰器&#xff08;1&#xff09;万能装饰器的实现&#xff08;2&#xff09;含参数的装饰器&#xff08;3&#xff09;多装饰器 5.内置高阶函数 1.生成式 列表生成式就是一个用来生成列表的特定语法形式的表达式。是Python提供的一种生成列表…

2023.6.7小记——什么是FPGA?

最近打算开始继续做一些个人分享&#xff0c;已经太久时间没有写文章了&#xff0c;感觉这样下去肯定不是个好事&#xff0c;当程序员当然是要保持分享~ 标题就暂时先以每天我认为最重要的一点来取&#xff0c;内容不仅限于此。 1. 什么是FPGA&#xff1f; 全称是Field-Progra…

PCL 点云均值漂移算法(MeanShift)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 均值漂移算法是一种非常经典的层次聚类方式,已在二维图像中得到了广泛的应用。这里我们也已二维图像为例来阐述其整个计算过程: 算法基本思想:如下图所示,左侧为实际的图像特征的分布,右侧为基于图像特征分布计…